Device interface library for multiple platforms including Mbed.
Dependents: DeepCover Embedded Security in IoT MaximInterface MAXREFDES155#
Maxim Interface is a library framework focused on providing flexible and expressive hardware interfaces. Both communication interfaces such as I2C and 1-Wire and device interfaces such as DS18B20 are supported. Modern C++ concepts are used extensively while keeping compatibility with C++98/C++03 and requiring no external dependencies. The embedded-friendly design does not depend on exceptions or RTTI.
The full version of the project is hosted on GitLab: https://gitlab.com/iabenz/MaximInterface
Revision 7:9cd16581b578, committed 2019-07-22
- Comitter:
- IanBenzMaxim
- Date:
- Mon Jul 22 11:44:07 2019 -0500
- Parent:
- 6:471901a04573
- Child:
- 8:5ea891c7d1a1
- Commit message:
- Updated to version 1.9.
Changed in this revision
--- a/Devices/DS18B20.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,251 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include <MaximInterface/Links/OneWireMaster.hpp> -#include <MaximInterface/Utilities/Error.hpp> -#include "DS18B20.hpp" - -namespace MaximInterface { - -const uint_least8_t DS18B20::nineBitResolution; -const uint_least8_t DS18B20::tenBitResolution; -const uint_least8_t DS18B20::elevenBitResolution; -const uint_least8_t DS18B20::twelveBitResolution; - -error_code DS18B20::initialize() { - Scratchpad::array scratchpad; - return readScratchpad(scratchpad); -} - -error_code DS18B20::writeScratchpad(uint_least8_t th, uint_least8_t tl, - uint_least8_t res) { - error_code result = selectRom(*master); - if (!result) { - const uint_least8_t sendBlock[] = {0x4E, th, tl, res}; - result = master->writeBlock(sendBlock); - if (!result) { - resolution = res; - } - } - return result; -} - -error_code DS18B20::readScratchpad(Scratchpad::span scratchpad) { - error_code result = selectRom(*master); - if (result) { - return result; - } - result = master->writeByte(0xBE); - if (result) { - return result; - } - result = master->readBlock(scratchpad); - if (result) { - return result; - } - uint_least8_t receivedCrc; - result = master->readByte(receivedCrc); - if (result) { - return result; - } - if (receivedCrc == calculateCrc8(scratchpad)) { - resolution = scratchpad[4]; - } else { - result = make_error_code(CrcError); - } - return result; -} - -error_code DS18B20::readPowerSupply(bool & localPower) { - error_code result = selectRom(*master); - if (result) { - return result; - } - result = master->writeByte(0xB4); - if (result) { - return result; - } - result = master->touchBit(localPower); - return result; -} - -error_code DS18B20::copyScratchpad() { - const uint_least8_t copyScratchpadCmd = 0x48; - - bool hasLocalPower; - error_code result = readPowerSupply(hasLocalPower); - if (result) { - return result; - } - result = selectRom(*master); - if (result) { - return result; - } - if (hasLocalPower) { - result = master->writeByte(copyScratchpadCmd); - bool recvbit = 0; - while (!recvbit && !result) { - result = master->touchBit(recvbit); - } - } else { - result = master->writeByteSetLevel(copyScratchpadCmd, - OneWireMaster::StrongLevel); - if (!result) { - sleep->invoke(10); - result = master->setLevel(OneWireMaster::NormalLevel); - } - } - return result; -} - -error_code DS18B20::convertTemperature() { - const uint_least8_t convertTemperatureCmd = 0x44; - - bool hasLocalPower; - error_code result = readPowerSupply(hasLocalPower); - if (result) { - return result; - } - result = selectRom(*master); - if (result) { - return result; - } - if (hasLocalPower) { - result = master->writeByte(convertTemperatureCmd); - bool recvbit = 0; - while (!result && !recvbit) { - result = master->touchBit(recvbit); - } - } else { - result = master->writeByteSetLevel(convertTemperatureCmd, - OneWireMaster::StrongLevel); - if (!result) { - int sleepTime; - switch (resolution) { - case nineBitResolution: - sleepTime = 94; - break; - - case tenBitResolution: - sleepTime = 188; - break; - - case elevenBitResolution: - sleepTime = 375; - break; - - case twelveBitResolution: - default: - sleepTime = 750; - break; - } - sleep->invoke(sleepTime); - result = master->setLevel(OneWireMaster::NormalLevel); - } - } - return result; -} - -error_code DS18B20::recallEeprom() { - error_code result = selectRom(*master); - if (!result) { - result = master->writeByte(0xB8); - } - return result; -} - -const error_category & DS18B20::errorCategory() { - static class : public error_category { - public: - virtual const char * name() const { return "DS18B20"; } - - virtual std::string message(int condition) const { - switch (condition) { - case CrcError: - return "CRC Error"; - - case DataError: - return "Data Error"; - - default: - return defaultErrorMessage(condition); - } - } - } instance; - return instance; -} - -error_code readTemperature(DS18B20 & ds18b20, int & temperature) { - error_code result = ds18b20.convertTemperature(); - if (result) { - return result; - } - DS18B20::Scratchpad::array scratchpad; - result = ds18b20.readScratchpad(scratchpad); - if (result) { - return result; - } - - const unsigned int tempData = - (static_cast<unsigned int>(scratchpad[1]) << 8) | scratchpad[0]; - const unsigned int signMask = 0xF800; - if ((tempData & signMask) == signMask) { - temperature = -0x800; - } else if ((tempData & signMask) == 0) { - temperature = 0; - } else { - return make_error_code(DS18B20::DataError); - } - unsigned int precisionMask; - switch (scratchpad[4]) { - case DS18B20::nineBitResolution: - default: - precisionMask = 0x7; - break; - - case DS18B20::tenBitResolution: - precisionMask = 0x3; - break; - - case DS18B20::elevenBitResolution: - precisionMask = 0x1; - break; - - case DS18B20::twelveBitResolution: - precisionMask = 0x0; - break; - } - temperature += static_cast<int>(tempData & ~(signMask | precisionMask)); - return error_code(); -} - -} // namespace MaximInterface
--- a/Devices/DS18B20.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_DS18B20 -#define MaximInterface_DS18B20 - -#include <MaximInterface/Links/SelectRom.hpp> -#include <MaximInterface/Links/Sleep.hpp> -#include <MaximInterface/Utilities/array_span.hpp> -#include <MaximInterface/Utilities/Export.h> - -namespace MaximInterface { - -/// @brief DS18B20 Programmable Resolution 1-Wire Digital Thermometer -/// @details The DS18B20 digital thermometer provides 9-bit to 12-bit -/// Celsius temperature measurements and has an alarm function with -/// nonvolatile user-programmable upper and lower trigger points. The -/// DS18B20 communicates over a 1-Wire bus that by definition requires -/// only one data line (and ground) for communication with a central -/// microprocessor. In addition, the DS18B20 can derive power directly -/// from the data line ("parasite power"), eliminating the need for an -/// external power supply. -class DS18B20 { -public: - enum ErrorValue { CrcError = 1, DataError }; - - static const uint_least8_t nineBitResolution = 0x1F; - static const uint_least8_t tenBitResolution = 0x3F; - static const uint_least8_t elevenBitResolution = 0x5F; - static const uint_least8_t twelveBitResolution = 0x7F; - - /// Holds the contents of the device scratchpad. - typedef array_span<uint_least8_t, 8> Scratchpad; - - DS18B20(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom) - : selectRom(selectRom), master(&master), sleep(&sleep), resolution(0) {} - - void setSleep(Sleep & sleep) { this->sleep = &sleep; } - - void setMaster(OneWireMaster & master) { this->master = &master; } - - void setSelectRom(const SelectRom & selectRom) { - this->selectRom = selectRom; - } - - /// Initializes the device for first time use. - MaximInterface_EXPORT error_code initialize(); - - /// Write Scratchpad Command - /// @details If the result of a temperature measurement is higher - /// than TH or lower than TL, an alarm flag inside the device is - /// set. This flag is updated with every temperature measurement. - /// As long as the alarm flag is set, the DS1920 will respond to - /// the alarm search command. - /// @param[in] th 8-bit upper temperature threshold, MSB indicates sign. - /// @param[in] tl 8-bit lower temperature threshold, LSB indicates sign. - /// @param[in] res Resolution of the DS18B20. - MaximInterface_EXPORT error_code writeScratchpad(uint_least8_t th, - uint_least8_t tl, - uint_least8_t res); - - /// Read Scratchpad Command - /// @param[out] scratchpad Contents of scratchpad. - MaximInterface_EXPORT error_code readScratchpad(Scratchpad::span scratchpad); - - /// Copy Scratchpad Command - /// @details This command copies from the scratchpad into the - /// EEPROM of the DS18B20, storing the temperature trigger bytes - /// and resolution in nonvolatile memory. - MaximInterface_EXPORT error_code copyScratchpad(); - - /// Read Power Supply command - /// @details This command determines if the DS18B20 is parasite - /// powered or has a local supply - /// @param[out] localPower - /// True if the device is powered by a local power supply, or false if the - /// device is parasitically powered. - MaximInterface_EXPORT error_code readPowerSupply(bool & localPower); - - /// Convert Temperature Command - /// @details This command begins a temperature conversion. - MaximInterface_EXPORT error_code convertTemperature(); - - /// Recall Command - /// @details This command recalls the temperature trigger values - /// and resolution stored in EEPROM to the scratchpad. - MaximInterface_EXPORT error_code recallEeprom(); - - MaximInterface_EXPORT static const error_category & errorCategory(); - -private: - SelectRom selectRom; - OneWireMaster * master; - const Sleep * sleep; - uint_least8_t resolution; -}; - -/// Reads the current temperature as an integer value with decimal. -/// @param ds18b20 Device to read. -/// @param[out] temperature Temperature in degrees Celsius multiplied by 16. -MaximInterface_EXPORT error_code readTemperature(DS18B20 & ds18b20, - int & temperature); - -inline error_code make_error_code(DS18B20::ErrorValue e) { - return error_code(e, DS18B20::errorCategory()); -} - -} // namespace MaximInterface - -#endif
--- a/Devices/DS1920.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,145 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include <MaximInterface/Links/OneWireMaster.hpp> -#include <MaximInterface/Utilities/Error.hpp> -#include "DS1920.hpp" - -namespace MaximInterface { - -error_code DS1920::writeScratchpad(uint_least8_t th, uint_least8_t tl) { - error_code result = selectRom(*master); - if (!result) { - const uint_least8_t sendBlock[] = {0x4E, th, tl}; - result = master->writeBlock(sendBlock); - } - return result; -} - -error_code DS1920::readScratchpad(Scratchpad::span scratchpad) { - error_code result = selectRom(*master); - if (!result) { - result = master->writeByte(0xBE); - if (!result) { - result = master->readBlock(scratchpad); - if (!result) { - uint_least8_t receivedCrc; - result = master->readByte(receivedCrc); - if (!result && (receivedCrc != calculateCrc8(scratchpad))) { - result = make_error_code(CrcError); - } - } - } - } - return result; -} - -error_code DS1920::copyScratchpad() { - error_code result = selectRom(*master); - if (!result) { - result = master->writeByteSetLevel(0x48, OneWireMaster::StrongLevel); - if (!result) { - sleep->invoke(10); - result = master->setLevel(OneWireMaster::NormalLevel); - } - } - return result; -} - -error_code DS1920::convertTemperature() { - error_code result = selectRom(*master); - if (!result) { - result = master->writeByteSetLevel(0x44, OneWireMaster::StrongLevel); - if (!result) { - sleep->invoke(750); - result = master->setLevel(OneWireMaster::NormalLevel); - } - } - return result; -} - -error_code DS1920::recallEeprom() { - error_code result = selectRom(*master); - if (!result) { - result = master->writeByte(0xB8); - } - return result; -} - -const error_category & DS1920::errorCategory() { - static class : public error_category { - public: - virtual const char * name() const { return "DS1920"; } - - virtual std::string message(int condition) const { - switch (condition) { - case CrcError: - return "CRC Error"; - - case DataError: - return "Data Error"; - - default: - return defaultErrorMessage(condition); - } - } - } instance; - return instance; -} - -error_code readTemperature(DS1920 & ds1920, int & temperature) { - error_code result = ds1920.convertTemperature(); - if (result) { - return result; - } - DS1920::Scratchpad::array scratchpad; - result = ds1920.readScratchpad(scratchpad); - if (result) { - return result; - } - - unsigned int tempData = - (static_cast<unsigned int>(scratchpad[1]) << 8) | scratchpad[0]; - const unsigned int signMask = 0xFF00; - if ((tempData & signMask) == signMask) { - temperature = -0x100; - tempData &= ~signMask; - } else if ((tempData & signMask) == 0) { - temperature = 0; - } else { - return make_error_code(DS1920::DataError); - } - temperature += static_cast<int>(tempData); - return error_code(); -} - -} // namespace MaximInterface
--- a/Devices/DS1920.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,121 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_DS1920 -#define MaximInterface_DS1920 - -#include <MaximInterface/Links/SelectRom.hpp> -#include <MaximInterface/Links/Sleep.hpp> -#include <MaximInterface/Utilities/array_span.hpp> -#include <MaximInterface/Utilities/Export.h> - -namespace MaximInterface { - -/// @brief DS1920 1-Wire Temperature iButton -/// @details The iButton® temperature logger (DS1920) provides -/// direct-to-digital 9-bit temperature readings over a range of -/// -55°C to +100°C in 0.5° increments. The iButton communicates with -/// a processor using the 1-Wire® protocol through a hardware port -/// interface. The port interface provides both the physical link and -/// handles the communication protocols that enable the processor to -/// access iButton resources with simple commands. Two bytes of -/// EEPROM can be used either to set alarm triggers or for storing -/// user data. -class DS1920 { -public: - enum ErrorValue { CrcError = 1, DataError }; - - /// Holds the contents of the device scratchpad. - typedef array_span<uint_least8_t, 8> Scratchpad; - - DS1920(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom) - : selectRom(selectRom), master(&master), sleep(&sleep) {} - - void setSleep(Sleep & sleep) { this->sleep = &sleep; } - - void setMaster(OneWireMaster & master) { this->master = &master; } - - void setSelectRom(const SelectRom & selectRom) { - this->selectRom = selectRom; - } - - /// @brief Write Scratchpad Command - /// @details If the result of a temperature measurement is higher - /// than TH or lower than TL, an alarm flag inside the device is - /// set. This flag is updated with every temperature measurement. - /// As long as the alarm flag is set, the DS1920 will respond to - /// the alarm search command. - /// @param[in] th 8-bit upper temperature threshold, MSB indicates sign. - /// @param[in] tl 8-bit lower temperature threshold, MSB indicates sign. - MaximInterface_EXPORT error_code writeScratchpad(uint_least8_t th, - uint_least8_t tl); - - /// @brief Read Scratchpad Command - /// @param[out] scratchpad Contents of scratchpad. - MaximInterface_EXPORT error_code readScratchpad(Scratchpad::span scratchpad); - - /// @brief Copy Scratchpad Command - /// @details This command copies from the scratchpad into the - /// EEPROM of the DS1920, storing the temperature trigger bytes - /// in nonvolatile memory. - MaximInterface_EXPORT error_code copyScratchpad(); - - /// @brief Convert Temperature Command - /// @details This command begins a temperature conversion. - MaximInterface_EXPORT error_code convertTemperature(); - - /// @brief Recall Command - /// @details This command recalls the temperature trigger values - /// stored in EEPROM to the scratchpad. - MaximInterface_EXPORT error_code recallEeprom(); - - MaximInterface_EXPORT static const error_category & errorCategory(); - -private: - SelectRom selectRom; - OneWireMaster * master; - const Sleep * sleep; -}; - -/// @brief Reads the current temperature as an integer value. -/// @param ds1920 Device to read. -/// @param[out] temperature Temperature in degrees Celsius multiplied by 2. -MaximInterface_EXPORT error_code readTemperature(DS1920 & ds1920, - int & temperature); - -inline error_code make_error_code(DS1920::ErrorValue e) { - return error_code(e, DS1920::errorCategory()); -} - -} // namespace MaximInterface - -#endif
--- a/Devices/DS2413.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,124 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include <MaximInterface/Links/OneWireMaster.hpp> -#include <MaximInterface/Utilities/Error.hpp> -#include "DS2413.hpp" - -namespace MaximInterface { - -error_code DS2413::readStatus(Status & status) const { - uint_least8_t val; - const error_code result = pioAccessRead(val); - if (!result) { - status = val; - } - return result; -} - -error_code DS2413::writeOutputState(bool pioAState, bool pioBState) { - uint_least8_t val = 0xFC; - if (pioAState) { - val |= 0x1; - } - if (pioBState) { - val |= 0x2; - } - return pioAccessWrite(val); -} - -error_code DS2413::pioAccessRead(uint_least8_t & val) const { - error_code result = selectRom(*master); - if (!result) { - result = master->writeByte(0xF5); - if (!result) { - result = master->readByte(val); - if (!result && (val != ((val ^ 0xF0) >> 4))) { - result = make_error_code(CommunicationError); - } - } - } - return result; -} - -error_code DS2413::pioAccessWrite(uint_least8_t val) { - error_code result = selectRom(*master); - if (!result) { - uint_least8_t block[] = {0x5A, val, static_cast<uint_least8_t>(val ^ 0xFF)}; - result = master->writeBlock(block); - if (!result) { - result = master->readByte(block[0]); - if (!result && block[0] != 0xAA) { - result = make_error_code(CommunicationError); - } - } - } - return result; -} - -const error_category & DS2413::errorCategory() { - static class : public error_category { - public: - virtual const char * name() const { return "DS2413"; } - - virtual std::string message(int condition) const { - switch (condition) { - case CommunicationError: - return "Communication Error"; - } - return defaultErrorMessage(condition); - } - } instance; - return instance; -} - -error_code writePioAOutputState(DS2413 & ds2413, bool pioAState) { - DS2413::Status status; - error_code result = ds2413.readStatus(status); - if (!result && pioAState != status[DS2413::PioAOutputState]) { - result = - ds2413.writeOutputState(pioAState, status[DS2413::PioBOutputState]); - } - return result; -} - -error_code writePioBOutputState(DS2413 & ds2413, bool pioBState) { - DS2413::Status status; - error_code result = ds2413.readStatus(status); - if (!result && pioBState != status[DS2413::PioBOutputState]) { - result = - ds2413.writeOutputState(status[DS2413::PioAOutputState], pioBState); - } - return result; -} - -} // namespace MaximInterface
--- a/Devices/DS2413.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_DS2413 -#define MaximInterface_DS2413 - -#include <stdint.h> -#include <MaximInterface/Links/SelectRom.hpp> -#include <MaximInterface/Utilities/Export.h> -#include <MaximInterface/Utilities/FlagSet.hpp> - -namespace MaximInterface { - -/// @brief DS2413 1-Wire Dual Channel Addressable Switch -/// @details The DS2413 is a dual-channel programmable I/O 1-Wire® -/// chip. The PIO outputs are configured as open-drain and provide up -/// to 20mA continuous sink capability and off-state operating voltage -/// up to 28V. Control and sensing of the PIO pins is performed with -/// a dedicated device-level command protocol. To provide a high level -/// of fault tolerance in the end application, the 1-Wire I/O and PIO -/// pins are all capable of withstanding continuous application of -/// voltages up to 28V max. Communication and operation of the DS2413 -/// is performed with the single contact Maxim 1-Wire serial interface. -class DS2413 { -public: - enum ErrorValue { CommunicationError = 1 }; - - enum StatusFlags { - PioAInputState = 0x1, - PioAOutputState = 0x2, - PioBInputState = 0x4, - PioBOutputState = 0x8 - }; - typedef FlagSet<StatusFlags, 4> Status; - - DS2413(OneWireMaster & master, const SelectRom & selectRom) - : selectRom(selectRom), master(&master) {} - - void setMaster(OneWireMaster & master) { this->master = &master; } - - void setSelectRom(const SelectRom & selectRom) { - this->selectRom = selectRom; - } - - /// Read the input and output logic states for all PIO pins. - MaximInterface_EXPORT error_code readStatus(Status & status) const; - - /// Write the output logic states for all PIO pins. - MaximInterface_EXPORT error_code writeOutputState(bool pioAState, - bool pioBState); - - MaximInterface_EXPORT static const error_category & errorCategory(); - -private: - error_code pioAccessRead(uint_least8_t & val) const; - error_code pioAccessWrite(uint_least8_t val); - - SelectRom selectRom; - OneWireMaster * master; -}; - -/// Write the output logic state for only PIOA. -MaximInterface_EXPORT error_code writePioAOutputState(DS2413 & ds2413, - bool pioAState); - -/// Write the output logic state for only PIOB. -MaximInterface_EXPORT error_code writePioBOutputState(DS2413 & ds2413, - bool pioBState); - -inline error_code make_error_code(DS2413::ErrorValue e) { - return error_code(e, DS2413::errorCategory()); -} - -} // namespace MaximInterface - -#endif
--- a/Devices/DS2431.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,176 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include <algorithm> -#include <MaximInterface/Links/OneWireMaster.hpp> -#include <MaximInterface/Utilities/Error.hpp> -#include "DS2431.hpp" - -namespace MaximInterface { - -error_code writeMemory(DS2431 & device, DS2431::Address targetAddress, - DS2431::Scratchpad::const_span data) { - error_code result = device.writeScratchpad(targetAddress, data); - if (result) { - return result; - } - DS2431::Scratchpad::array readData; - uint_least8_t esByte; - result = device.readScratchpad(readData, esByte); - if (result) { - return result; - } - result = device.copyScratchpad(targetAddress, esByte); - return result; -} - -error_code DS2431::readMemory(Address beginAddress, - span<uint_least8_t> data) const { - error_code result = selectRom(*master); - if (result) { - return result; - } - const uint_least8_t sendBlock[] = {0xF0, beginAddress, 0x00}; - result = master->writeBlock(sendBlock); - if (result) { - return result; - } - result = master->readBlock(data); - return result; -} - -error_code DS2431::writeScratchpad(Address targetAddress, - Scratchpad::const_span data) { - error_code result = selectRom(*master); - if (result) { - return result; - } - uint_least8_t block[3 + Scratchpad::size] = {0x0F, targetAddress, 0x00}; - std::copy(data.begin(), data.end(), block + 3); - result = master->writeBlock(block); - if (result) { - return result; - } - const uint_fast16_t calculatedCrc = calculateCrc16(block) ^ 0xFFFFU; - result = master->readBlock(make_span(block, 2)); - if (result) { - return result; - } - if (calculatedCrc != - ((static_cast<uint_fast16_t>(block[1]) << 8) | block[0])) { - result = make_error_code(CrcError); - } - return result; -} - -error_code DS2431::readScratchpad(Scratchpad::span data, - uint_least8_t & esByte) { - typedef array<uint_least8_t, 6 + Scratchpad::size> Block; - - error_code result = selectRom(*master); - if (result) { - return result; - } - Block block = {0xAA}; - result = master->writeByte(block.front()); - if (result) { - return result; - } - result = master->readBlock(make_span(block).subspan(1)); - if (result) { - return result; - } - Block::const_iterator blockIt = block.end(); - uint_fast16_t receivedCrc = static_cast<uint_fast16_t>(*(--blockIt)) << 8; - receivedCrc |= *(--blockIt); - const uint_fast16_t expectedCrc = - calculateCrc16(make_span(block.data(), block.size() - 2)) ^ 0xFFFFU; - if (expectedCrc == receivedCrc) { - Block::const_iterator blockItEnd = blockIt; - blockIt -= data.size(); - std::copy(blockIt, blockItEnd, data.begin()); - esByte = *(--blockIt); - } else { - result = make_error_code(CrcError); - } - return result; -} - -error_code DS2431::copyScratchpad(Address targetAddress, uint_least8_t esByte) { - error_code result = selectRom(*master); - if (result) { - return result; - } - uint_least8_t block[] = {0x55, targetAddress, 0x00}; - result = master->writeBlock(block); - if (result) { - return result; - } - result = master->writeByteSetLevel(esByte, OneWireMaster::StrongLevel); - if (result) { - return result; - } - sleep->invoke(10); - result = master->setLevel(OneWireMaster::NormalLevel); - if (result) { - return result; - } - result = master->readByte(block[0]); - if (result) { - return result; - } - if (block[0] != 0xAA) { - result = make_error_code(OperationFailure); - } - return result; -} - -const error_category & DS2431::errorCategory() { - static class : public error_category { - public: - virtual const char * name() const { return "DS2431"; } - - virtual std::string message(int condition) const { - switch (condition) { - case CrcError: - return "CRC Error"; - - case OperationFailure: - return "Operation Failure"; - } - return defaultErrorMessage(condition); - } - } instance; - return instance; -} - -} // namespace MaximInterface
--- a/Devices/DS2431.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,124 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_DS2431 -#define MaximInterface_DS2431 - -#include <MaximInterface/Links/SelectRom.hpp> -#include <MaximInterface/Links/Sleep.hpp> -#include <MaximInterface/Utilities/array_span.hpp> -#include <MaximInterface/Utilities/Export.h> - -namespace MaximInterface { - -/// @brief DS2431 1024-bit 1-Wire EEPROM -/// @details The DS2431 is a 1024-bit, 1-Wire® EEPROM chip organized -/// as four memory pages of 256 bits each. Data is written to an 8-byte -/// scratchpad, verified, and then copied to the EEPROM memory. As a -/// special feature, the four memory pages can individually be write -/// protected or put in EPROM-emulation mode, where bits can only be -/// changed from a 1 to a 0 state. The DS2431 communicates over the -/// single-conductor 1-Wire bus. The communication follows the standard -/// 1-Wire protocol. Each device has its own unalterable and unique -/// 64-bit ROM registration number that is factory lasered into the chip. -/// The registration number is used to address the device in a multidrop, -/// 1-Wire net environment. -class DS2431 { -public: - enum ErrorValue { CrcError = 1, OperationFailure }; - - typedef array_span<uint_least8_t, 8> Scratchpad; - typedef uint_least8_t Address; - - DS2431(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom) - : selectRom(selectRom), master(&master), sleep(&sleep) {} - - void setSleep(Sleep & sleep) { this->sleep = &sleep; } - - void setMaster(OneWireMaster & master) { this->master = &master; } - - void setSelectRom(const SelectRom & selectRom) { - this->selectRom = selectRom; - } - - /// @brief Reads block of data from EEPROM memory. - /// @param[in] beginAddress EEPROM memory address to start reading from. - /// @param[out] data EEPROM data read from the device. - MaximInterface_EXPORT error_code readMemory(Address beginAddress, - span<uint_least8_t> data) const; - - /// @brief Writes 8 bytes to the scratchpad. - /// @param[in] targetAddress - /// EEPROM memory address that this data will be copied to. - /// Must be on row boundary. - /// @param[in] data Data to write to scratchpad. - MaximInterface_EXPORT error_code writeScratchpad(Address targetAddress, - Scratchpad::const_span data); - - /// @brief Reads contents of scratchpad. - /// @param[out] data Data read from scratchpad. - /// @param[out] esByte E/S byte read before scratchpad data. - MaximInterface_EXPORT error_code readScratchpad(Scratchpad::span data, - uint_least8_t & esByte); - - /// @brief Copies contents of scratchpad to EEPROM. - /// @param[in] targetAddress EEPROM memory address that scratchpad - /// will be copied to. Must be on row boundary. - /// @param[in] esByte E/S byte from preceding Read Scratchpad command. - MaximInterface_EXPORT error_code copyScratchpad(Address targetAddress, - uint_least8_t esByte); - - MaximInterface_EXPORT static const error_category & errorCategory(); - -private: - SelectRom selectRom; - OneWireMaster * master; - const Sleep * sleep; -}; - -/// @brief -/// Writes data to EEPROM using Write Scratchpad, Read Scratchpad, -/// and Copy Scratchpad commands. -/// @param device Device to write. -/// @param[in] targetAddress EEPROM memory address to start writing at. -/// @param[in] data Data to write to EEPROM. -MaximInterface_EXPORT error_code writeMemory(DS2431 & device, - DS2431::Address targetAddress, - DS2431::Scratchpad::const_span data); - -inline error_code make_error_code(DS2431::ErrorValue e) { - return error_code(e, DS2431::errorCategory()); -} - -} // namespace MaximInterface - -#endif
--- a/Devices/DS2465.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,782 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include <MaximInterface/Utilities/Error.hpp> -#include "DS2465.hpp" - -namespace MaximInterface { - -using namespace Sha256; - -/// Delay required after writing an EEPROM segment. -static const int eepromSegmentWriteDelayMs = 10; -/// Delay required after writing an EEPROM page such as the secret memory. -static const int eepromPageWriteDelayMs = 8 * eepromSegmentWriteDelayMs; -/// Delay required for a SHA computation to complete. -static const int shaComputationDelayMs = 2; - -static const uint_least8_t scratchpad = 0x00; -static const uint_least8_t commandReg = 0x60; - -static const uint_least8_t owTransmitBlockCmd = 0x69; - -/// DS2465 Status bits. -enum StatusBit { - Status_1WB = 0x01, - Status_PPD = 0x02, - Status_SD = 0x04, - Status_LL = 0x08, - Status_RST = 0x10, - Status_SBR = 0x20, - Status_TSB = 0x40, - Status_DIR = 0x80 -}; - -static const int maxBlockSize = 63; - -const int DS2465::memoryPages; -const int DS2465::segmentsPerPage; - -error_code DS2465::initialize(Config config) { - // reset DS2465 - error_code result = resetDevice(); - if (!result) { - // write the default configuration setup - result = writeConfig(config); - } - return result; -} - -error_code DS2465::computeNextMasterSecret(bool swap, int pageNum, - PageRegion region) { - error_code result = make_error_code(ArgumentOutOfRangeError); - if (pageNum >= 0) { - const uint_least8_t command[] = { - 0x1E, static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region) - : 0xBF)}; - result = writeMemory(commandReg, command); - } - return result; -} - -error_code DS2465::computeWriteMac(bool regwrite, bool swap, int pageNum, - int segmentNum) const { - error_code result = make_error_code(ArgumentOutOfRangeError); - if (pageNum >= 0 && segmentNum >= 0) { - const uint_least8_t command[] = { - 0x2D, static_cast<uint_least8_t>((regwrite << 7) | (swap << 6) | - (pageNum << 4) | segmentNum)}; - result = writeMemory(commandReg, command); - if (!result) { - sleep->invoke(shaComputationDelayMs); - } - } - return result; -} - -error_code DS2465::computeAuthMac(bool swap, int pageNum, - PageRegion region) const { - error_code result = make_error_code(ArgumentOutOfRangeError); - if (pageNum >= 0) { - const uint_least8_t command[] = { - 0x3C, static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region) - : 0xBF)}; - result = writeMemory(commandReg, command); - if (!result) { - sleep->invoke(shaComputationDelayMs * 2); - } - } - return result; -} - -error_code DS2465::computeSlaveSecret(bool swap, int pageNum, - PageRegion region) { - error_code result = make_error_code(ArgumentOutOfRangeError); - if (pageNum >= 0) { - const uint_least8_t command[] = { - 0x4B, static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region) - : 0xBF)}; - result = writeMemory(commandReg, command); - if (!result) { - sleep->invoke(shaComputationDelayMs * 2); - } - } - return result; -} - -error_code DS2465::readPage(int pageNum, Page::span data) const { - uint_least8_t addr; - switch (pageNum) { - case 0: - addr = 0x80; - break; - case 1: - addr = 0xA0; - break; - default: - return make_error_code(ArgumentOutOfRangeError); - } - return readMemory(addr, data); -} - -error_code DS2465::writePage(int pageNum, Page::const_span data) { - error_code result = writeMemory(scratchpad, data); - if (!result) { - result = copyScratchpad(false, pageNum, false, 0); - } - if (!result) { - sleep->invoke(eepromPageWriteDelayMs); - } - return result; -} - -error_code DS2465::writeSegment(int pageNum, int segmentNum, - Segment::const_span data) { - error_code result = writeMemory(scratchpad, data); - if (!result) { - result = copyScratchpad(false, pageNum, true, segmentNum); - } - if (!result) { - sleep->invoke(eepromSegmentWriteDelayMs); - } - return result; -} - -error_code DS2465::writeMasterSecret(Hash::const_span masterSecret) { - error_code result = writeMemory(scratchpad, masterSecret); - if (!result) { - result = copyScratchpad(true, 0, false, 0); - } - if (!result) { - sleep->invoke(eepromPageWriteDelayMs); - } - return result; -} - -error_code DS2465::copyScratchpad(bool destSecret, int pageNum, bool notFull, - int segmentNum) { - error_code result = make_error_code(ArgumentOutOfRangeError); - if (pageNum >= 0 && segmentNum >= 0) { - const uint_least8_t command[] = { - 0x5A, - static_cast<uint_least8_t>(destSecret ? 0 - : (0x80 | (pageNum << 4) | - (notFull << 3) | segmentNum))}; - result = writeMemory(commandReg, command); - } - return result; -} - -error_code DS2465::configureLevel(Level level) { - // Check if supported level - if (!((level == NormalLevel) || (level == StrongLevel))) { - return make_error_code(InvalidLevelError); - } - // Check if requested level already set - if (curConfig.getSPU() == (level == StrongLevel)) { - return error_code(); - } - // Set the level - return writeConfig(Config(curConfig).setSPU(level == StrongLevel)); -} - -error_code DS2465::setLevel(Level newLevel) { - if (newLevel == StrongLevel) { - return make_error_code(InvalidLevelError); - } - - return configureLevel(newLevel); -} - -error_code DS2465::setSpeed(Speed newSpeed) { - // Check if supported speed - if (!((newSpeed == OverdriveSpeed) || (newSpeed == StandardSpeed))) { - return make_error_code(InvalidSpeedError); - } - // Check if requested speed is already set - if (curConfig.get1WS() == (newSpeed == OverdriveSpeed)) { - return error_code(); - } - // Set the speed - return writeConfig(Config(curConfig).set1WS(newSpeed == OverdriveSpeed)); -} - -error_code DS2465::triplet(TripletData & data) { - // 1-Wire Triplet (Case B) - // S AD,0 [A] 1WT [A] SS [A] Sr AD,1 [A] [Status] A [Status] A\ P - // \--------/ - // Repeat until 1WB bit has changed to 0 - // [] indicates from slave - // SS indicates byte containing search direction bit value in msbit - - const uint_least8_t command[] = { - 0x78, static_cast<uint_least8_t>(data.writeBit ? 0x80 : 0x00)}; - error_code result = writeMemory(commandReg, command); - if (!result) { - uint_least8_t status; - result = pollBusy(&status); - if (!result) { - // check bit results in status byte - data.readBit = ((status & Status_SBR) == Status_SBR); - data.readBitComplement = ((status & Status_TSB) == Status_TSB); - data.writeBit = ((status & Status_DIR) == Status_DIR); - } - } - return result; -} - -error_code DS2465::readBlock(span<uint_least8_t> recvBuf) { - // 1-Wire Receive Block (Case A) - // S AD,0 [A] CommandReg [A] 1WRF [A] PR [A] P - // [] indicates from slave - // PR indicates byte containing parameter - - error_code result; - span<uint_least8_t>::index_type recvIdx = 0; - while (recvIdx < recvBuf.size() && !result) { - const uint_least8_t command[] = { - 0xE1, - static_cast<uint_least8_t>(std::min<span<uint_least8_t>::index_type>( - recvBuf.size() - recvIdx, maxBlockSize))}; - result = writeMemory(commandReg, command); - if (!result) { - result = pollBusy(); - } - if (!result) { - result = readMemory(scratchpad, recvBuf.subspan(recvIdx, command[1])); - } - recvIdx += command[1]; - } - return result; -} - -error_code DS2465::writeBlock(span<const uint_least8_t> sendBuf) { - error_code result; - span<const uint_least8_t>::index_type sendIdx = 0; - while (sendIdx < sendBuf.size() && !result) { - const uint_least8_t command[] = { - owTransmitBlockCmd, static_cast<uint_least8_t>( - std::min<span<const uint_least8_t>::index_type>( - sendBuf.size() - sendIdx, maxBlockSize))}; - - // prefill scratchpad with required data - result = writeMemory(scratchpad, sendBuf.subspan(sendIdx, command[1])); - - // 1-Wire Transmit Block (Case A) - // S AD,0 [A] CommandReg [A] 1WTB [A] PR [A] P - // [] indicates from slave - // PR indicates byte containing parameter - if (!result) { - result = writeMemory(commandReg, command); - } - if (!result) { - result = pollBusy(); - } - sendIdx += command[1]; - } - return result; -} - -error_code DS2465::writeMacBlock() const { - // 1-Wire Transmit Block (Case A) - // S AD,0 [A] CommandReg [A] 1WTB [A] PR [A] P - // [] indicates from slave - // PR indicates byte containing parameter - - const uint_least8_t command[] = {owTransmitBlockCmd, 0xFF}; - error_code result = writeMemory(commandReg, command); - if (!result) { - result = pollBusy(); - } - return result; -} - -error_code DS2465::readByteSetLevel(uint_least8_t & recvByte, - Level afterLevel) { - // 1-Wire Read Bytes (Case C) - // S AD,0 [A] CommandReg [A] 1WRB [A] Sr AD,1 [A] [Status] A [Status] A - // \--------/ - // Repeat until 1WB bit has changed to 0 - // Sr AD,0 [A] SRP [A] E1 [A] Sr AD,1 [A] DD A\ P - // - // [] indicates from slave - // DD data read - - error_code result = configureLevel(afterLevel); - if (result) { - return result; - } - - const uint_least8_t command = 0x96; - result = writeMemory(commandReg, make_span(&command, 1)); - if (result) { - return result; - } - - result = pollBusy(); - if (result) { - return result; - } - - result = readMemory(0x62, make_span(&recvByte, 1)); - return result; -} - -error_code DS2465::writeByteSetLevel(uint_least8_t sendByte, Level afterLevel) { - // 1-Wire Write Byte (Case B) - // S AD,0 [A] CommandReg [A] 1WWB [A] DD [A] Sr AD,1 [A] [Status] A [Status] - // A\ P - // \--------/ - // Repeat until 1WB bit has changed to 0 - // [] indicates from slave - // DD data to write - - error_code result = configureLevel(afterLevel); - if (result) { - return result; - } - - const uint_least8_t command[] = {0xA5, sendByte}; - result = writeMemory(commandReg, command); - if (result) { - return result; - } - - result = pollBusy(); - return result; -} - -error_code DS2465::touchBitSetLevel(bool & sendRecvBit, Level afterLevel) { - // 1-Wire bit (Case B) - // S AD,0 [A] CommandReg [A] 1WSB [A] BB [A] Sr AD,1 [A] [Status] A [Status] - // A\ P - // \--------/ - // Repeat until 1WB bit has changed to 0 - // [] indicates from slave - // BB indicates byte containing bit value in msbit - - error_code result = configureLevel(afterLevel); - if (result) { - return result; - } - - const uint_least8_t command[] = { - 0x87, static_cast<uint_least8_t>(sendRecvBit ? 0x80 : 0x00)}; - result = writeMemory(commandReg, command); - if (result) { - return result; - } - - uint_least8_t status; - result = pollBusy(&status); - if (!result) { - sendRecvBit = ((status & Status_SBR) == Status_SBR); - } - return result; -} - -error_code DS2465::writeMemory(uint_least8_t addr, - span<const uint_least8_t> buf) const { - // Write SRAM (Case A) - // S AD,0 [A] VSA [A] DD [A] P - // \-----/ - // Repeat for each data byte - // [] indicates from slave - // VSA valid SRAM memory address - // DD memory data to write - - error_code result = master->start(address_); - if (result) { - master->stop(); - return result; - } - result = master->writeByte(addr); - if (result) { - master->stop(); - return result; - } - result = master->writeBlock(buf); - if (result) { - master->stop(); - return result; - } - result = master->stop(); - return result; -} - -error_code DS2465::readMemory(uint_least8_t addr, - span<uint_least8_t> buf) const { - // Read (Case A) - // S AD,0 [A] MA [A] Sr AD,1 [A] [DD] A [DD] A\ P - // \-----/ - // Repeat for each data byte, NAK last byte - // [] indicates from slave - // MA memory address - // DD memory data read - - error_code result = master->start(address_); - if (result) { - master->stop(); - return result; - } - result = master->writeByte(addr); - if (result) { - master->stop(); - return result; - } - result = readMemory(buf); - return result; -} - -error_code DS2465::readMemory(span<uint_least8_t> buf) const { - error_code result = master->start(address_ | 1); - if (result) { - master->stop(); - return result; - } - result = master->readBlock(I2CMaster::Nack, buf); - if (result) { - master->stop(); - return result; - } - result = master->stop(); - return result; -} - -error_code DS2465::writeConfig(Config config) { - const uint_least8_t configReg = 0x67; - uint_least8_t configBuf = - ((config.readByte() ^ 0xF) << 4) | config.readByte(); - error_code result = writeMemory(configReg, make_span(&configBuf, 1)); - if (!result) { - result = readMemory(configReg, make_span(&configBuf, 1)); - } - if (!result) { - if (configBuf != config.readByte()) - result = make_error_code(HardwareError); - } - if (!result) { - curConfig = config; - } - return result; -} - -error_code DS2465::writePortParameter(PortParameter param, int val) { - if (val < 0 || val > 15) { - return make_error_code(ArgumentOutOfRangeError); - } - - uint_least8_t addr = 0; - switch (param) { - case tRSTL_STD: - case tRSTL_OD: - addr = 0x68; - break; - case tMSP_STD: - case tMSP_OD: - addr = 0x69; - break; - case tW0L_STD: - case tW0L_OD: - addr = 0x6A; - break; - case tREC0: - addr = 0x6B; - break; - case RWPU: - addr = 0x6C; - break; - case tW1L_OD: - addr = 0x6D; - break; - } - - uint_least8_t data; - error_code result = readMemory(addr, make_span(&data, 1)); - if (result) { - return result; - } - - uint_least8_t newData; - if (param == tRSTL_OD || param == tMSP_OD || param == tW0L_OD) { - newData = (data & 0x0F) | (val << 4); - } else { - newData = (data & 0xF0) | val; - } - - if (newData != data) { - result = writeMemory(addr, make_span(&newData, 1)); - } - return result; -} - -error_code DS2465::pollBusy(uint_least8_t * pStatus) const { - const int pollLimit = 200; - - int pollCount = 0; - uint_least8_t status; - do { - error_code result = readMemory(make_span(&status, 1)); - if (result) { - return result; - } - if (pStatus != NULL) { - *pStatus = status; - } - if (pollCount++ >= pollLimit) { - return make_error_code(HardwareError); - } - } while (status & Status_1WB); - - return error_code(); -} - -error_code DS2465::reset() { - // 1-Wire reset (Case B) - // S AD,0 [A] CommandReg [A] 1WRS [A] Sr AD,1 [A] [Status] A [Status] A\ P - // \--------/ - // Repeat until 1WB bit has changed to 0 - // [] indicates from slave - - uint_least8_t buf = 0xB4; - error_code result = writeMemory(commandReg, make_span(&buf, 1)); - - if (!result) { - result = pollBusy(&buf); - } - - if (!result) { - if ((buf & Status_SD) == Status_SD) { - result = make_error_code(ShortDetectedError); - } else if ((buf & Status_PPD) != Status_PPD) { - result = make_error_code(NoSlaveError); - } - } - - return result; -} - -error_code DS2465::resetDevice() { - // Device Reset - // S AD,0 [A] CommandReg [A] 1WMR [A] Sr AD,1 [A] [SS] A\ P - // [] indicates from slave - // SS status byte to read to verify state - - uint_least8_t buf = 0xF0; - error_code result = writeMemory(commandReg, make_span(&buf, 1)); - - if (!result) { - result = readMemory(make_span(&buf, 1)); - } - - if (!result) { - if ((buf & 0xF7) != 0x10) { - result = make_error_code(HardwareError); - } - } - - if (!result) { - reset(); // do a command to get 1-Wire master reset out of holding state - } - - return result; -} - -error_code -DS2465::computeNextMasterSecret(AuthenticationData::const_span data) { - error_code result = writeMemory(scratchpad, data); - if (!result) { - result = computeNextMasterSecret(false, 0, FullPage); - } - return result; -} - -error_code -DS2465::computeNextMasterSecretWithSwap(AuthenticationData::const_span data, - int pageNum, PageRegion region) { - error_code result = writeMemory(scratchpad, data); - if (!result) { - result = computeNextMasterSecret(true, pageNum, region); - } - return result; -} - -error_code DS2465::computeWriteMac(WriteMacData::const_span data) const { - error_code result = writeMemory(scratchpad, data); - if (!result) { - result = computeWriteMac(false, false, 0, 0); - } - return result; -} - -error_code DS2465::computeWriteMac(WriteMacData::const_span data, - Hash::span mac) const { - error_code result = computeWriteMac(data); - if (!result) { - result = readMemory(mac); - } - return result; -} - -error_code -DS2465::computeAndTransmitWriteMac(WriteMacData::const_span data) const { - error_code result = computeWriteMac(data); - if (!result) { - result = writeMacBlock(); - } - return result; -} - -error_code DS2465::computeWriteMacWithSwap(WriteMacData::const_span data, - int pageNum, int segmentNum) const { - error_code result = writeMemory(scratchpad, data); - if (!result) { - result = computeWriteMac(false, true, pageNum, segmentNum); - } - return result; -} - -error_code DS2465::computeWriteMacWithSwap(WriteMacData::const_span data, - int pageNum, int segmentNum, - Hash::span mac) const { - error_code result = computeWriteMacWithSwap(data, pageNum, segmentNum); - if (!result) { - result = readMemory(mac); - } - return result; -} - -error_code -DS2465::computeAndTransmitWriteMacWithSwap(WriteMacData::const_span data, - int pageNum, int segmentNum) const { - error_code result = computeWriteMacWithSwap(data, pageNum, segmentNum); - if (!result) { - result = writeMacBlock(); - } - return result; -} - -error_code DS2465::computeSlaveSecret(AuthenticationData::const_span data) { - error_code result = writeMemory(scratchpad, data); - if (!result) { - result = computeSlaveSecret(false, 0, FullPage); - } - return result; -} - -error_code -DS2465::computeSlaveSecretWithSwap(AuthenticationData::const_span data, - int pageNum, PageRegion region) { - error_code result = writeMemory(scratchpad, data); - if (!result) { - result = computeSlaveSecret(true, pageNum, region); - } - return result; -} - -error_code DS2465::computeAuthMac(AuthenticationData::const_span data) const { - error_code result = writeMemory(scratchpad, data); - if (!result) { - result = computeAuthMac(false, 0, FullPage); - } - return result; -} - -error_code DS2465::computeAuthMac(AuthenticationData::const_span data, - Hash::span mac) const { - error_code result = computeAuthMac(data); - if (!result) { - result = readMemory(mac); - } - return result; -} - -error_code -DS2465::computeAndTransmitAuthMac(AuthenticationData::const_span data) const { - error_code result = computeAuthMac(data); - if (!result) { - result = writeMacBlock(); - } - return result; -} - -error_code DS2465::computeAuthMacWithSwap(AuthenticationData::const_span data, - int pageNum, - PageRegion region) const { - error_code result = writeMemory(scratchpad, data); - if (!result) { - result = computeAuthMac(true, pageNum, region); - } - return result; -} - -error_code DS2465::computeAuthMacWithSwap(AuthenticationData::const_span data, - int pageNum, PageRegion region, - Hash::span mac) const { - error_code result = computeAuthMacWithSwap(data, pageNum, region); - if (!result) { - result = readMemory(mac); - } - return result; -} - -error_code DS2465::computeAndTransmitAuthMacWithSwap( - AuthenticationData::const_span data, int pageNum, PageRegion region) const { - error_code result = computeAuthMacWithSwap(data, pageNum, region); - if (!result) { - result = writeMacBlock(); - } - return result; -} - -const error_category & DS2465::errorCategory() { - static class : public error_category { - public: - virtual const char * name() const { return "DS2465"; } - - virtual std::string message(int condition) const { - switch (condition) { - case HardwareError: - return "Hardware Error"; - - case ArgumentOutOfRangeError: - return "Argument Out of Range Error"; - - default: - return defaultErrorMessage(condition); - } - } - } instance; - return instance; -} - -} // namespace MaximInterface
--- a/Devices/DS2465.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,404 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_DS2465 -#define MaximInterface_DS2465 - -#include <MaximInterface/Links/I2CMaster.hpp> -#include <MaximInterface/Links/OneWireMaster.hpp> -#include <MaximInterface/Links/Sleep.hpp> -#include <MaximInterface/Utilities/array_span.hpp> -#include <MaximInterface/Utilities/Export.h> -#include <MaximInterface/Utilities/Sha256.hpp> - -namespace MaximInterface { - -/// Interface to the DS2465 1-Wire master and SHA-256 coprocessor. -class DS2465 : public OneWireMaster { -public: - enum ErrorValue { HardwareError = 1, ArgumentOutOfRangeError }; - - /// @brief 1-Wire port adjustment parameters. - /// @note See datasheet page 13. - enum PortParameter { - tRSTL_STD, - tRSTL_OD, - tMSP_STD, - tMSP_OD, - tW0L_STD, - tW0L_OD, - tREC0, - RWPU, - tW1L_OD - }; - - /// Page region to use for swapping. - enum PageRegion { FullPage = 0x03, FirstHalf = 0x01, SecondHalf = 0x02 }; - - /// Holds the contents of a device memory segment. - typedef array_span<uint_least8_t, 4> Segment; - - /// Holds the contents of a device memory page. - typedef array_span<uint_least8_t, 32> Page; - - static const int memoryPages = 2; - static const int segmentsPerPage = Page::size / Segment::size; - - /// Represents a DS2465 configuration. - class Config { - public: - /// Default construct with power-on config. - explicit Config(uint_least8_t readByte = optionAPU) - : readByte_(readByte & 0xF) {} - - /// @name 1WS - /// @brief 1-Wire Speed - /// @{ - - /// Get 1WS bit. - bool get1WS() const { return (readByte_ & option1WS) == option1WS; } - - /// Set 1WS bit. - Config & set1WS(bool new1WS) { - if (new1WS) { - readByte_ |= option1WS; - } else { - readByte_ &= ~option1WS; - } - return *this; - } - - /// @} - - /// @name SPU - /// @brief Strong Pullup - /// @{ - - /// Get SPU bit. - bool getSPU() const { return (readByte_ & optionSPU) == optionSPU; } - - /// Set SPU bit. - Config & setSPU(bool newSPU) { - if (newSPU) { - readByte_ |= optionSPU; - } else { - readByte_ &= ~optionSPU; - } - return *this; - } - - /// @} - - /// @name PDN - /// @brief 1-Wire Power Down - /// @{ - - /// Get PDN bit. - bool getPDN() const { return (readByte_ & optionPDN) == optionPDN; } - - /// Set PDN bit. - Config & setPDN(bool newPDN) { - if (newPDN) { - readByte_ |= optionPDN; - } else { - readByte_ &= ~optionPDN; - } - return *this; - } - - /// @} - - /// @name APU - /// @brief Active Pullup - /// @{ - - /// Get APU bit. - bool getAPU() const { return (readByte_ & optionAPU) == optionAPU; } - - /// Set APU bit. - Config & setAPU(bool newAPU) { - if (newAPU) { - readByte_ |= optionAPU; - } else { - readByte_ &= ~optionAPU; - } - return *this; - } - - /// @} - - /// Byte representation that is read from the DS2465. - uint_least8_t readByte() const { return readByte_; } - - private: - static const unsigned int option1WS = 0x8; - static const unsigned int optionSPU = 0x4; - static const unsigned int optionPDN = 0x2; - static const unsigned int optionAPU = 0x1; - - uint_least8_t readByte_; - }; - - // Const member functions should not change the settings of the DS2465 or - // affect the state of the 1-Wire bus. Read pointer, scratchpad, MAC output - // register, and command register on the DS2465 are considered mutable. - - DS2465(Sleep & sleep, I2CMaster & master, uint_least8_t address = 0x30) - : sleep(&sleep), master(&master), address_(address & 0xFE) {} - - void setSleep(Sleep & sleep) { this->sleep = &sleep; } - - void setMaster(I2CMaster & master) { this->master = &master; } - - uint_least8_t address() const { return address_; } - - void setAddress(uint_least8_t address) { address_ = address & 0xFE; } - - /// Initialize hardware for use. - MaximInterface_EXPORT error_code initialize(Config config = Config()); - - /// @brief Write a new configuration to the DS2465. - /// @param[in] config New configuration to write. - MaximInterface_EXPORT error_code writeConfig(Config config); - - /// @brief Write a new port configuration parameter to the DS2465. - /// @param[in] param Parameter to adjust. - /// @param[in] val - /// New parameter value to set. Consult datasheet for value mappings. - MaximInterface_EXPORT error_code writePortParameter(PortParameter param, - int val); - - // 1-Wire Master Commands - - MaximInterface_EXPORT virtual error_code reset(); - - MaximInterface_EXPORT virtual error_code touchBitSetLevel(bool & sendRecvBit, - Level afterLevel); - - MaximInterface_EXPORT virtual error_code - readByteSetLevel(uint_least8_t & recvByte, Level afterLevel); - - MaximInterface_EXPORT virtual error_code - writeByteSetLevel(uint_least8_t sendByte, Level afterLevel); - - MaximInterface_EXPORT virtual error_code - readBlock(span<uint_least8_t> recvBuf); - - MaximInterface_EXPORT virtual error_code - writeBlock(span<const uint_least8_t> sendBuf); - - MaximInterface_EXPORT virtual error_code setSpeed(Speed newSpeed); - - /// @copydoc OneWireMaster::setLevel - /// @note - /// The DS2465 only supports enabling strong pullup following a 1-Wire read or - /// write operation. - MaximInterface_EXPORT virtual error_code setLevel(Level newLevel); - - MaximInterface_EXPORT virtual error_code triplet(TripletData & data); - - // DS2465 Coprocessor Commands - - /// @brief Read data from an EEPROM memory page. - /// @param pageNum Page number to read from. - /// @param[out] data Data that was read. - MaximInterface_EXPORT error_code readPage(int pageNum, Page::span data) const; - - /// @brief Write data to an EEPROM memory page. - /// @param pageNum Page number to copy to. - /// @param data Data to write. - MaximInterface_EXPORT error_code writePage(int pageNum, - Page::const_span data); - - /// @brief Write data to an EEPROM memory segment. - /// @param pageNum Page number to copy to. - /// @param segmentNum Segment number to copy to. - /// @param data Data to write. - MaximInterface_EXPORT error_code writeSegment(int pageNum, int segmentNum, - Segment::const_span data); - - /// Write data to the secret EEPROM memory page. - MaximInterface_EXPORT error_code - writeMasterSecret(Sha256::Hash::const_span masterSecret); - - /// @brief Compute Next Master Secret. - /// @param data Combined data fields for computation. - MaximInterface_EXPORT error_code - computeNextMasterSecret(Sha256::AuthenticationData::const_span data); - - /// @brief Compute Next Master Secret with page swapping. - /// @param data Combined data fields for computation. - /// @param pageNum Page number to swap in. - /// @param region Region of the page to swap in. - MaximInterface_EXPORT error_code - computeNextMasterSecretWithSwap(Sha256::AuthenticationData::const_span data, - int pageNum, PageRegion region); - - /// @brief Compute Write MAC. - /// @param data Combined data fields for computation. - /// @param[out] mac Computed Write MAC. - MaximInterface_EXPORT error_code computeWriteMac( - Sha256::WriteMacData::const_span data, Sha256::Hash::span mac) const; - - /// @brief Compute Write MAC. - /// @param data Combined data fields for computation. - MaximInterface_EXPORT error_code - computeAndTransmitWriteMac(Sha256::WriteMacData::const_span data) const; - - /// @brief Compute Write MAC with page swapping. - /// @param data Combined data fields for computation. - /// @param pageNum Page number to swap in. - /// @param segmentNum Segment number to swap in. - /// @param[out] mac Computed Write MAC. - MaximInterface_EXPORT error_code - computeWriteMacWithSwap(Sha256::WriteMacData::const_span data, int pageNum, - int segmentNum, Sha256::Hash::span mac) const; - - /// @brief Compute Write MAC with page swapping. - /// @param data Combined data fields for computation. - /// @param pageNum Page number to swap in. - /// @param segmentNum Segment number to swap in. - MaximInterface_EXPORT error_code computeAndTransmitWriteMacWithSwap( - Sha256::WriteMacData::const_span data, int pageNum, int segmentNum) const; - - /// @brief Compute Slave Secret (S-Secret). - /// @param data Combined data fields for computation. - MaximInterface_EXPORT error_code - computeSlaveSecret(Sha256::AuthenticationData::const_span data); - - /// @brief Compute Slave Secret (S-Secret) with page swapping. - /// @param data Combined data fields for computation. - /// @param pageNum Page number to swap in. - /// @param region Region of the page to swap in. - MaximInterface_EXPORT error_code - computeSlaveSecretWithSwap(Sha256::AuthenticationData::const_span data, - int pageNum, PageRegion region); - - /// @brief Compute Authentication MAC. - /// @param data Combined data fields for computation. - /// @param[out] mac Computed Auth MAC. - MaximInterface_EXPORT error_code - computeAuthMac(Sha256::AuthenticationData::const_span data, - Sha256::Hash::span mac) const; - - /// @brief Compute Authentication MAC. - /// @param data Combined data fields for computation. - MaximInterface_EXPORT error_code - computeAndTransmitAuthMac(Sha256::AuthenticationData::const_span data) const; - - /// @brief Compute Authentication MAC with page swapping. - /// @param data Combined data fields for computation. - /// @param pageNum Page number to swap in. - /// @param region Region of the page to swap in. - /// @param[out] mac Computed Auth MAC. - MaximInterface_EXPORT error_code computeAuthMacWithSwap( - Sha256::AuthenticationData::const_span data, int pageNum, - PageRegion region, Sha256::Hash::span mac) const; - - /// @brief Compute Authentication MAC with page swapping. - /// @param data Combined data fields for computation. - /// @param pageNum Page number to swap in. - /// @param region Region of the page to swap in. - MaximInterface_EXPORT error_code - computeAndTransmitAuthMacWithSwap(Sha256::AuthenticationData::const_span data, - int pageNum, PageRegion region) const; - - MaximInterface_EXPORT static const error_category & errorCategory(); - -private: - const Sleep * sleep; - I2CMaster * master; - uint_least8_t address_; - Config curConfig; - - /// @brief Performs a soft reset on the DS2465. - /// @note This is not a 1-Wire Reset. - error_code resetDevice(); - - /// @brief - /// Polls the DS2465 status waiting for the 1-Wire Busy bit (1WB) to be - /// cleared. - /// @param[out] pStatus Optionally retrive the status byte when 1WB cleared. - /// @returns Success or TimeoutError if poll limit reached. - error_code pollBusy(uint_least8_t * pStatus = NULL) const; - - /// @brief Ensure that the desired 1-Wire level is set in the configuration. - /// @param level Desired 1-Wire level. - error_code configureLevel(Level level); - - /// @note Const since only for internal use. - error_code writeMemory(uint_least8_t addr, - span<const uint_least8_t> buf) const; - - /// @brief Read memory from the DS2465. - /// @param addr Address to begin reading from. - /// @param[out] buf Buffer to hold read data. - error_code readMemory(uint_least8_t addr, span<uint_least8_t> buf) const; - - /// @brief Read memory from the DS2465 at the current pointer. - /// @param[out] buf Buffer to hold read data. - error_code readMemory(span<uint_least8_t> buf) const; - - /// Write the last computed MAC to the 1-Wire bus. - error_code writeMacBlock() const; - - error_code computeWriteMac(Sha256::WriteMacData::const_span data) const; - - error_code computeWriteMacWithSwap(Sha256::WriteMacData::const_span data, - int pageNum, int segmentNum) const; - - error_code computeAuthMac(Sha256::AuthenticationData::const_span data) const; - - error_code computeAuthMacWithSwap(Sha256::AuthenticationData::const_span data, - int pageNum, PageRegion region) const; - - // Legacy implementations - error_code copyScratchpad(bool destSecret, int pageNum, bool notFull, - int segmentNum); - - error_code computeNextMasterSecret(bool swap, int pageNum, PageRegion region); - - error_code computeWriteMac(bool regwrite, bool swap, int pageNum, - int segmentNum) const; - - error_code computeSlaveSecret(bool swap, int pageNum, PageRegion region); - - error_code computeAuthMac(bool swap, int pageNum, PageRegion region) const; -}; - -inline error_code make_error_code(DS2465::ErrorValue e) { - return error_code(e, DS2465::errorCategory()); -} - -} // namespace MaximInterface - -#endif
--- a/Devices/DS2480B.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,559 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include <MaximInterface/Utilities/Error.hpp> -#include "DS2480B.hpp" - -// Mode Commands -#define MODE_DATA 0xE1 -#define MODE_COMMAND 0xE3 -#define MODE_STOP_PULSE 0xF1 - -// Return byte value -#define RB_CHIPID_MASK 0x1C -#define RB_RESET_MASK 0x03 -#define RB_1WIRESHORT 0x00 -#define RB_PRESENCE 0x01 -#define RB_ALARMPRESENCE 0x02 -#define RB_NOPRESENCE 0x03 - -#define RB_BIT_MASK 0x03 -#define RB_BIT_ONE 0x03 -#define RB_BIT_ZERO 0x00 - -// Masks for all bit ranges -#define CMD_MASK 0x80 -#define FUNCTSEL_MASK 0x60 -#define BITPOL_MASK 0x10 -#define SPEEDSEL_MASK 0x0C -#define MODSEL_MASK 0x02 -#define PARMSEL_MASK 0x70 -#define PARMSET_MASK 0x0E - -// Command or config bit -#define CMD_COMM 0x81 -#define CMD_CONFIG 0x01 - -// Function select bits -#define FUNCTSEL_BIT 0x00 -#define FUNCTSEL_SEARCHON 0x30 -#define FUNCTSEL_SEARCHOFF 0x20 -#define FUNCTSEL_RESET 0x40 -#define FUNCTSEL_CHMOD 0x60 - -// Bit polarity/Pulse voltage bits -#define BITPOL_ONE 0x10 -#define BITPOL_ZERO 0x00 -#define BITPOL_5V 0x00 -#define BITPOL_12V 0x10 - -// One Wire speed bits -#define SPEEDSEL_STD 0x00 -#define SPEEDSEL_FLEX 0x04 -#define SPEEDSEL_OD 0x08 -#define SPEEDSEL_PULSE 0x0C - -// Data/Command mode select bits -#define MODSEL_DATA 0x00 -#define MODSEL_COMMAND 0x02 - -// 5V Follow Pulse select bits -#define PRIME5V_TRUE 0x02 -#define PRIME5V_FALSE 0x00 - -// Parameter select bits -#define PARMSEL_PARMREAD 0x00 -#define PARMSEL_SLEW 0x10 -#define PARMSEL_12VPULSE 0x20 -#define PARMSEL_5VPULSE 0x30 -#define PARMSEL_WRITE1LOW 0x40 -#define PARMSEL_SAMPLEOFFSET 0x50 -#define PARMSEL_ACTIVEPULLUPTIME 0x60 -#define PARMSEL_BAUDRATE 0x70 - -// Pull down slew rate. -#define PARMSET_Slew15Vus 0x00 -#define PARMSET_Slew2p2Vus 0x02 -#define PARMSET_Slew1p65Vus 0x04 -#define PARMSET_Slew1p37Vus 0x06 -#define PARMSET_Slew1p1Vus 0x08 -#define PARMSET_Slew0p83Vus 0x0A -#define PARMSET_Slew0p7Vus 0x0C -#define PARMSET_Slew0p55Vus 0x0E - -// 12V programming pulse time table -#define PARMSET_32us 0x00 -#define PARMSET_64us 0x02 -#define PARMSET_128us 0x04 -#define PARMSET_256us 0x06 -#define PARMSET_512us 0x08 -#define PARMSET_1024us 0x0A -#define PARMSET_2048us 0x0C -#define PARMSET_infinite 0x0E - -// 5V strong pull up pulse time table -#define PARMSET_16p4ms 0x00 -#define PARMSET_65p5ms 0x02 -#define PARMSET_131ms 0x04 -#define PARMSET_262ms 0x06 -#define PARMSET_524ms 0x08 -#define PARMSET_1p05s 0x0A -#define PARMSET_dynamic 0x0C -#define PARMSET_infinite 0x0E - -// Write 1 low time -#define PARMSET_Write8us 0x00 -#define PARMSET_Write9us 0x02 -#define PARMSET_Write10us 0x04 -#define PARMSET_Write11us 0x06 -#define PARMSET_Write12us 0x08 -#define PARMSET_Write13us 0x0A -#define PARMSET_Write14us 0x0C -#define PARMSET_Write15us 0x0E - -// Data sample offset and Write 0 recovery time -#define PARMSET_SampOff3us 0x00 -#define PARMSET_SampOff4us 0x02 -#define PARMSET_SampOff5us 0x04 -#define PARMSET_SampOff6us 0x06 -#define PARMSET_SampOff7us 0x08 -#define PARMSET_SampOff8us 0x0A -#define PARMSET_SampOff9us 0x0C -#define PARMSET_SampOff10us 0x0E - -// Active pull up on time -#define PARMSET_PullUp0p0us 0x00 -#define PARMSET_PullUp0p5us 0x02 -#define PARMSET_PullUp1p0us 0x04 -#define PARMSET_PullUp1p5us 0x06 -#define PARMSET_PullUp2p0us 0x08 -#define PARMSET_PullUp2p5us 0x0A -#define PARMSET_PullUp3p0us 0x0C -#define PARMSET_PullUp3p5us 0x0E - -// Baud rate bits -#define PARMSET_9600 0x00 -#define PARMSET_19200 0x02 -#define PARMSET_57600 0x04 -#define PARMSET_115200 0x06 - -// DS2480B program voltage available -#define DS2480BPROG_MASK 0x20 - -namespace MaximInterface { - -error_code DS2480B::initialize() { - level = NormalLevel; - mode = MODSEL_COMMAND; - speed = SPEEDSEL_STD; - - // Send a break to reset the DS2480B. - // Switch to lower baud rate to ensure break is longer than 2 ms. - error_code result = uart->setBaudRate(4800); - if (result) { - return result; - } - result = uart->sendBreak(); - if (result) { - return result; - } - result = uart->setBaudRate(9600); - if (result) { - return result; - } - - // Wait for master reset. - sleep->invoke(1); - - // Flush the read buffer. - result = uart->clearReadBuffer(); - if (result) { - return result; - } - - // Send the timing byte. - result = uart->writeByte(CMD_COMM | FUNCTSEL_RESET | SPEEDSEL_STD); - if (result) { - return result; - } - - // Change the DS2480 baud rate. - result = uart->writeByte(CMD_CONFIG | PARMSEL_BAUDRATE | PARMSET_115200); - if (result) { - return result; - } - - // Change our baud rate. - result = uart->setBaudRate(115200); - if (result) { - return result; - } - - uint_least8_t response; - - // Verify response. - result = uart->readByte(response); - if (result) { - return result; - } - if ((response & (PARMSEL_MASK | PARMSET_MASK)) != - (PARMSEL_BAUDRATE | PARMSET_115200)) { - return make_error_code(HardwareError); - } - - // Set the SPUD time value. - result = uart->writeByte(CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite); - if (result) { - return result; - } - - // Verify response. - result = uart->readByte(response); - if (result) { - return result; - } - if ((response & (PARMSEL_MASK | PARMSET_MASK)) != - (PARMSEL_5VPULSE | PARMSET_infinite)) { - return make_error_code(HardwareError); - } - - return result; -} - -error_code DS2480B::reset() { - if (level != NormalLevel) { - return make_error_code(InvalidLevelError); - } - - uint_least8_t packet[2]; - int packetLen = 0; - - // Check for correct mode. - if (mode != MODSEL_COMMAND) { - mode = MODSEL_COMMAND; - packet[packetLen++] = MODE_COMMAND; - } - - // Construct the command. - packet[packetLen++] = CMD_COMM | FUNCTSEL_RESET | speed; - - // Send the packet. - error_code result = uart->writeBlock(make_span(packet, packetLen)); - if (result) { - return result; - } - - // Read back the response. - result = uart->readByte(packet[0]); - if (result) { - return result; - } - - // Make sure this byte looks like a reset byte. - if ((packet[0] & RB_RESET_MASK) == RB_1WIRESHORT) { - result = make_error_code(ShortDetectedError); - } else if ((packet[0] & RB_RESET_MASK) == RB_NOPRESENCE) { - result = make_error_code(NoSlaveError); - } - return result; -} - -error_code DS2480B::touchBitSetLevel(bool & sendRecvBit, Level afterLevel) { - if (level != NormalLevel) { - return make_error_code(InvalidLevelError); - } - - uint_least8_t packet[3]; - int packetLen = 0; - - // Check for correct mode. - if (mode != MODSEL_COMMAND) { - mode = MODSEL_COMMAND; - packet[packetLen++] = MODE_COMMAND; - } - - // Construct the command. - packet[packetLen++] = CMD_COMM | FUNCTSEL_BIT | - (sendRecvBit ? BITPOL_ONE : BITPOL_ZERO) | speed; - switch (afterLevel) { - case NormalLevel: - break; - - case StrongLevel: - // Add the command to begin the pulse. - packet[packetLen++] = - CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V | PRIME5V_FALSE; - break; - - default: - return make_error_code(InvalidLevelError); - } - - // Send the packet. - error_code result = uart->writeBlock(make_span(packet, packetLen)); - if (result) { - return result; - } - - // Read back the response. - result = uart->readByte(packet[0]); - if (result) { - return result; - } - - // Interpret the response. - if ((packet[0] & 0xE0) == 0x80) { - sendRecvBit = ((packet[0] & RB_BIT_MASK) == RB_BIT_ONE); - level = afterLevel; - } else { - result = make_error_code(HardwareError); - } - return result; -} - -error_code DS2480B::writeByteSetLevel(uint_least8_t sendByte, - Level afterLevel) { - if (level != NormalLevel) { - return make_error_code(InvalidLevelError); - } - - switch (afterLevel) { - case NormalLevel: - break; - - case StrongLevel: - return OneWireMaster::writeByteSetLevel(sendByte, afterLevel); - - default: - return make_error_code(InvalidLevelError); - } - - uint_least8_t packet[3]; - int packetLen = 0; - - // Check for correct mode. - if (mode != MODSEL_DATA) { - mode = MODSEL_DATA; - packet[packetLen++] = MODE_DATA; - } - - // Add the byte to send. - packet[packetLen++] = sendByte; - - // Check for duplication of data that looks like COMMAND mode. - if (sendByte == MODE_COMMAND) { - packet[packetLen++] = sendByte; - } - - // Send the packet. - error_code result = uart->writeBlock(make_span(packet, packetLen)); - if (result) { - return result; - } - - // Read back the response. - result = uart->readByte(packet[0]); - if (result) { - return result; - } - - // Interpret the response. - if (packet[0] != sendByte) { - result = make_error_code(HardwareError); - } - return result; -} - -error_code DS2480B::readByteSetLevel(uint_least8_t & recvByte, - Level afterLevel) { - if (level != NormalLevel) { - return make_error_code(InvalidLevelError); - } - - switch (afterLevel) { - case NormalLevel: - break; - - case StrongLevel: - return OneWireMaster::readByteSetLevel(recvByte, afterLevel); - - default: - return make_error_code(InvalidLevelError); - } - - uint_least8_t packet[2]; - int packetLen = 0; - - // Check for correct mode. - if (mode != MODSEL_DATA) { - mode = MODSEL_DATA; - packet[packetLen++] = MODE_DATA; - } - - // Add the byte to send. - packet[packetLen++] = 0xFF; - - // Send the packet. - error_code result = uart->writeBlock(make_span(packet, packetLen)); - if (result) { - return result; - } - - // Read back the response. - result = uart->readByte(recvByte); - return result; -} - -error_code DS2480B::setSpeed(Speed newSpeed) { - uint_least8_t newSpeedByte; - switch (newSpeed) { - case OverdriveSpeed: - newSpeedByte = SPEEDSEL_OD; - break; - - case StandardSpeed: - newSpeedByte = SPEEDSEL_STD; - break; - - default: - return make_error_code(InvalidSpeedError); - } - if (speed == newSpeedByte) { - return error_code(); - } - speed = newSpeedByte; - - uint_least8_t packet[2]; - int packetLen = 0; - - // Check for correct mode. - if (mode != MODSEL_COMMAND) { - mode = MODSEL_COMMAND; - packet[packetLen++] = MODE_COMMAND; - } - - // Change DS2480 speed. - packet[packetLen++] = CMD_COMM | FUNCTSEL_SEARCHOFF | speed; - - // Send the packet. - return uart->writeBlock(make_span(packet, packetLen)); -} - -error_code DS2480B::setLevel(Level newLevel) { - if (level == newLevel) { - return error_code(); - } - - uint_least8_t packet[2]; - int packetLen = 0; - - switch (newLevel) { - case NormalLevel: - // Stop pulse command. - packet[packetLen++] = MODE_STOP_PULSE; - break; - - case StrongLevel: - // Check for correct mode. - if (mode != MODSEL_COMMAND) { - mode = MODSEL_COMMAND; - packet[packetLen++] = MODE_COMMAND; - } - - // Add the command to begin the pulse. - packet[packetLen++] = - CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V | PRIME5V_FALSE; - break; - - default: - return make_error_code(InvalidLevelError); - } - - // Send the packet. - error_code result = uart->writeBlock(make_span(packet, packetLen)); - if (result) { - return result; - } - - if (newLevel == NormalLevel) { - // Read back the response. - result = uart->readByte(packet[0]); - if (result) { - return result; - } - - // Interpret the response. - if ((packet[0] & 0xE0) != 0xE0) { - return make_error_code(HardwareError); - } - } - - level = newLevel; - return result; -} - -error_code DS2480B::sendCommand(uint_least8_t command) { - uint_least8_t packet[2]; - int packetLen = 0; - - // Check for correct mode. - if (mode != MODSEL_COMMAND) { - mode = MODSEL_COMMAND; - packet[packetLen++] = MODE_COMMAND; - } - - // Add command. - packet[packetLen++] = command; - - // Send the packet. - return uart->writeBlock(make_span(packet, packetLen)); -} - -const error_category & DS2480B::errorCategory() { - static class : public error_category { - public: - virtual const char * name() const { return "DS2480B"; } - - virtual std::string message(int condition) const { - switch (condition) { - case HardwareError: - return "Hardware Error"; - - default: - return defaultErrorMessage(condition); - } - } - } instance; - return instance; -} - -} // namespace MaximInterface
--- a/Devices/DS2480B.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_DS2480B -#define MaximInterface_DS2480B - -#include <MaximInterface/Links/OneWireMaster.hpp> -#include <MaximInterface/Links/Sleep.hpp> -#include <MaximInterface/Links/Uart.hpp> -#include <MaximInterface/Utilities/Export.h> - -namespace MaximInterface { - -/// Serial to 1-Wire Line Driver -class DS2480B : public OneWireMaster { -public: - enum ErrorValue { HardwareError = 1 }; - - DS2480B(Sleep & sleep, Uart & uart) : sleep(&sleep), uart(&uart) {} - - void setSleep(Sleep & sleep) { this->sleep = &sleep; } - void setUart(Uart & uart) { this->uart = &uart; } - - MaximInterface_EXPORT error_code initialize(); - - MaximInterface_EXPORT virtual error_code reset(); - - MaximInterface_EXPORT virtual error_code touchBitSetLevel(bool & sendRecvBit, - Level afterLevel); - - MaximInterface_EXPORT virtual error_code - writeByteSetLevel(uint_least8_t sendByte, Level afterLevel); - - MaximInterface_EXPORT virtual error_code - readByteSetLevel(uint_least8_t & recvByte, Level afterLevel); - - MaximInterface_EXPORT virtual error_code setSpeed(Speed newSpeed); - - MaximInterface_EXPORT virtual error_code setLevel(Level newLevel); - - MaximInterface_EXPORT static const error_category & errorCategory(); - -protected: - MaximInterface_EXPORT error_code sendCommand(uint_least8_t command); - -private: - const Sleep * sleep; - Uart * uart; - - Level level; - uint_least8_t mode; - uint_least8_t speed; -}; - -inline error_code make_error_code(DS2480B::ErrorValue e) { - return error_code(e, DS2480B::errorCategory()); -} - -} // namespace MaximInterface - -#endif
--- a/Devices/DS2482_DS2484.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,424 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include <MaximInterface/Utilities/Error.hpp> -#include "DS2482_DS2484.hpp" - -namespace MaximInterface { - -// Device Status bits -enum StatusBit { - Status_1WB = 0x01, - Status_PPD = 0x02, - Status_SD = 0x04, - Status_LL = 0x08, - Status_RST = 0x10, - Status_SBR = 0x20, - Status_TSB = 0x40, - Status_DIR = 0x80 -}; - -error_code DS2482_DS2484::initialize(Config config) { - error_code result = resetDevice(); - if (result) { - return result; - } - // Write the default configuration setup. - result = writeConfig(config); - return result; -} - -error_code DS2482_DS2484::resetDevice() { - // Device Reset - // S AD,0 [A] DRST [A] Sr AD,1 [A] [SS] A\ P - // [] indicates from slave - // SS status byte to read to verify state - - error_code result = sendCommand(0xF0); - if (result) { - return result; - } - - uint_least8_t buf; - result = readRegister(buf); - if (result) { - return result; - } - - if ((buf & 0xF7) != 0x10) { - return make_error_code(HardwareError); - } - - // Do a command to get 1-Wire master reset out of holding state. - reset(); - - return result; -} - -error_code DS2482_DS2484::triplet(TripletData & data) { - // 1-Wire Triplet (Case B) - // S AD,0 [A] 1WT [A] SS [A] Sr AD,1 [A] [Status] A [Status] A\ P - // \--------/ - // Repeat until 1WB bit has changed to 0 - // [] indicates from slave - // SS indicates byte containing search direction bit value in msbit - - error_code result = sendCommand(0x78, data.writeBit ? 0x80 : 0x00); - if (!result) { - uint_least8_t status; - result = pollBusy(&status); - if (!result) { - data.readBit = ((status & Status_SBR) == Status_SBR); - data.readBitComplement = ((status & Status_TSB) == Status_TSB); - data.writeBit = ((status & Status_DIR) == Status_DIR); - } - } - return result; -} - -error_code DS2482_DS2484::reset() { - // 1-Wire reset (Case B) - // S AD,0 [A] 1WRS [A] Sr AD,1 [A] [Status] A [Status] A\ P - // \--------/ - // Repeat until 1WB bit has changed to 0 - // [] indicates from slave - - error_code result = sendCommand(0xB4); - if (result) { - return result; - } - - uint_least8_t buf; - result = pollBusy(&buf); - if (result) { - return result; - } - - if ((buf & Status_SD) == Status_SD) { - result = make_error_code(ShortDetectedError); - } else if ((buf & Status_PPD) != Status_PPD) { - result = make_error_code(NoSlaveError); - } - - return result; -} - -error_code DS2482_DS2484::touchBitSetLevel(bool & sendRecvBit, - Level afterLevel) { - // 1-Wire bit (Case B) - // S AD,0 [A] 1WSB [A] BB [A] Sr AD,1 [A] [Status] A [Status] A\ P - // \--------/ - // Repeat until 1WB bit has changed to 0 - // [] indicates from slave - // BB indicates byte containing bit value in msbit - - error_code result = configureLevel(afterLevel); - if (result) { - return result; - } - - result = sendCommand(0x87, sendRecvBit ? 0x80 : 0x00); - if (result) { - return result; - } - - uint_least8_t status; - result = pollBusy(&status); - if (!result) { - sendRecvBit = ((status & Status_SBR) == Status_SBR); - } - return result; -} - -error_code DS2482_DS2484::writeByteSetLevel(uint_least8_t sendByte, - Level afterLevel) { - // 1-Wire Write Byte (Case B) - // S AD,0 [A] 1WWB [A] DD [A] Sr AD,1 [A] [Status] A [Status] A\ P - // \--------/ - // Repeat until 1WB bit has changed to 0 - // [] indicates from slave - // DD data to write - - error_code result = configureLevel(afterLevel); - if (result) { - return result; - } - - result = sendCommand(0xA5, sendByte); - if (result) { - return result; - } - - result = pollBusy(); - return result; -} - -error_code DS2482_DS2484::readByteSetLevel(uint_least8_t & recvByte, - Level afterLevel) { - // 1-Wire Read Bytes (Case C) - // S AD,0 [A] 1WRB [A] Sr AD,1 [A] [Status] A [Status] A - // \--------/ - // Repeat until 1WB bit has changed to 0 - // Sr AD,0 [A] SRP [A] E1 [A] Sr AD,1 [A] DD A\ P - // - // [] indicates from slave - // DD data read - - error_code result = configureLevel(afterLevel); - if (result) { - return result; - } - - result = sendCommand(0x96); - if (result) { - return result; - } - - result = pollBusy(); - if (result) { - return result; - } - - result = readRegister(0xE1, recvByte); - return result; -} - -error_code DS2482_DS2484::setSpeed(Speed newSpeed) { - // Check if supported speed - if (!((newSpeed == OverdriveSpeed) || (newSpeed == StandardSpeed))) { - return make_error_code(InvalidSpeedError); - } - // Check if requested speed is already set - if (curConfig.get1WS() == (newSpeed == OverdriveSpeed)) { - return error_code(); - } - // Set the speed - return writeConfig(Config(curConfig).set1WS(newSpeed == OverdriveSpeed)); -} - -error_code DS2482_DS2484::setLevel(Level newLevel) { - if (newLevel == StrongLevel) { - return make_error_code(InvalidLevelError); - } - - return configureLevel(newLevel); -} - -error_code DS2482_DS2484::writeConfig(Config config) { - uint_least8_t configBuf = - ((config.readByte() ^ 0xF) << 4) | config.readByte(); - error_code result = sendCommand(0xD2, configBuf); - if (!result) { - result = readRegister(0xC3, configBuf); - } - if (!result) { - if (configBuf != config.readByte()) { - result = make_error_code(HardwareError); - } - } - if (!result) { - curConfig = config; - } - return result; -} - -error_code DS2482_DS2484::readRegister(uint_least8_t reg, - uint_least8_t & buf) const { - error_code result = sendCommand(0xE1, reg); - if (!result) { - result = readRegister(buf); - } - return result; -} - -error_code DS2482_DS2484::readRegister(uint_least8_t & buf) const { - return master->readPacket(address_, make_span(&buf, 1)); -} - -error_code DS2482_DS2484::pollBusy(uint_least8_t * pStatus) { - const int pollLimit = 200; - - int pollCount = 0; - uint_least8_t status; - do { - error_code result = readRegister(status); - if (result) { - return result; - } - if (pStatus != NULL) { - *pStatus = status; - } - if (pollCount++ >= pollLimit) { - return make_error_code(HardwareError); - } - } while (status & Status_1WB); - - return error_code(); -} - -error_code DS2482_DS2484::configureLevel(Level level) { - // Check if supported level - if (!((level == NormalLevel) || (level == StrongLevel))) { - return make_error_code(InvalidLevelError); - } - // Check if requested level already set - if (curConfig.getSPU() == (level == StrongLevel)) { - return error_code(); - } - // Set the level - return writeConfig(Config(curConfig).setSPU(level == StrongLevel)); -} - -error_code DS2482_DS2484::sendCommand(uint_least8_t cmd) const { - return master->writePacket(address_, make_span(&cmd, 1)); -} - -error_code DS2482_DS2484::sendCommand(uint_least8_t cmd, - uint_least8_t param) const { - uint_least8_t buf[] = {cmd, param}; - return master->writePacket(address_, buf); -} - -const error_category & DS2482_DS2484::errorCategory() { - static class : public error_category { - public: - virtual const char * name() const { return "DS2482_DS2484"; } - - virtual std::string message(int condition) const { - switch (condition) { - case HardwareError: - return "Hardware Error"; - - case ArgumentOutOfRangeError: - return "Argument Out of Range Error"; - - default: - return defaultErrorMessage(condition); - } - } - } instance; - return instance; -} - -error_code DS2482_800::selectChannel(int channel) { - // Channel Select (Case A) - // S AD,0 [A] CHSL [A] CC [A] Sr AD,1 [A] [RR] A\ P - // [] indicates from slave - // CC channel value - // RR channel read back - - uint_least8_t ch; - uint_least8_t ch_read; - switch (channel) { - case 0: - ch = 0xF0; - ch_read = 0xB8; - break; - - case 1: - ch = 0xE1; - ch_read = 0xB1; - break; - - case 2: - ch = 0xD2; - ch_read = 0xAA; - break; - - case 3: - ch = 0xC3; - ch_read = 0xA3; - break; - - case 4: - ch = 0xB4; - ch_read = 0x9C; - break; - - case 5: - ch = 0xA5; - ch_read = 0x95; - break; - - case 6: - ch = 0x96; - ch_read = 0x8E; - break; - - case 7: - ch = 0x87; - ch_read = 0x87; - break; - - default: - return make_error_code(ArgumentOutOfRangeError); - }; - - error_code result = sendCommand(0xC3, ch); - if (!result) { - result = readRegister(ch); - if (!result) { - // check for failure due to incorrect read back of channel - if (ch != ch_read) { - result = make_error_code(HardwareError); - } - } - } - - return result; -} - -error_code DS2484::adjustPort(PortParameter param, int val) { - if (val < 0 || val > 15) { - return make_error_code(ArgumentOutOfRangeError); - } - - error_code result = sendCommand(0xC3, (param << 4) | val); - if (result) { - return result; - } - - uint_least8_t portConfig = val + 1; - for (int reads = -1; reads < param; ++reads) { - result = readRegister(portConfig); - if (result) { - return result; - } - } - if (val != portConfig) { - result = make_error_code(HardwareError); - } - - return result; -} - -} // namespace MaximInterface
--- a/Devices/DS2482_DS2484.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,261 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_DS2482_DS2484 -#define MaximInterface_DS2482_DS2484 - -#include <MaximInterface/Links/OneWireMaster.hpp> -#include <MaximInterface/Links/I2CMaster.hpp> -#include <MaximInterface/Utilities/Export.h> - -namespace MaximInterface { - -/// Interface to the DS2484, DS2482-100, DS2482-101, DS2482-800 1-Wire masters. -class DS2482_DS2484 : public OneWireMaster { -public: - enum ErrorValue { HardwareError = 1, ArgumentOutOfRangeError }; - - /// Represents a device configuration. - class Config { - public: - /// Default construct with power-on config. - explicit Config(uint_least8_t readByte = optionAPU) - : readByte_(readByte & 0xF) {} - - /// @name 1WS - /// @brief 1-Wire Speed - /// @{ - - /// Get 1WS bit. - bool get1WS() const { return (readByte_ & option1WS) == option1WS; } - - /// Set 1WS bit. - Config & set1WS(bool new1WS) { - if (new1WS) { - readByte_ |= option1WS; - } else { - readByte_ &= ~option1WS; - } - return *this; - } - - /// @} - - /// @name SPU - /// @brief Strong Pullup - /// @{ - - /// Get SPU bit. - bool getSPU() const { return (readByte_ & optionSPU) == optionSPU; } - - /// Set SPU bit. - Config & setSPU(bool newSPU) { - if (newSPU) { - readByte_ |= optionSPU; - } else { - readByte_ &= ~optionSPU; - } - return *this; - } - - /// @} - - /// @name PDN - /// @brief 1-Wire Power Down - /// @{ - - /// Get PDN bit. - bool getPDN() const { return (readByte_ & optionPDN) == optionPDN; } - - /// Set PDN bit. - Config & setPDN(bool newPDN) { - if (newPDN) { - readByte_ |= optionPDN; - } else { - readByte_ &= ~optionPDN; - } - return *this; - } - - /// @} - - /// @name APU - /// @brief Active Pullup - /// @{ - - /// Get APU bit. - bool getAPU() const { return (readByte_ & optionAPU) == optionAPU; } - - /// Set APU bit. - Config & setAPU(bool newAPU) { - if (newAPU) { - readByte_ |= optionAPU; - } else { - readByte_ &= ~optionAPU; - } - return *this; - } - - /// @} - - /// Byte representation that is read from the device. - uint_least8_t readByte() const { return readByte_; } - - private: - static const unsigned int option1WS = 0x8; - static const unsigned int optionSPU = 0x4; - static const unsigned int optionPDN = 0x2; - static const unsigned int optionAPU = 0x1; - - uint_least8_t readByte_; - }; - - void setMaster(I2CMaster & master) { this->master = &master; } - - uint_least8_t address() const { return address_; } - - void setAddress(uint_least8_t address) { address_ = address; } - - /// Initialize hardware for use. - MaximInterface_EXPORT error_code initialize(Config config = Config()); - - /// @brief Write a new configuration to the device. - /// @param[in] config New configuration to write. - MaximInterface_EXPORT error_code writeConfig(Config config); - - MaximInterface_EXPORT virtual error_code triplet(TripletData & data); - - MaximInterface_EXPORT virtual error_code reset(); - - MaximInterface_EXPORT virtual error_code touchBitSetLevel(bool & sendRecvBit, - Level afterLevel); - - MaximInterface_EXPORT virtual error_code - readByteSetLevel(uint_least8_t & recvByte, Level afterLevel); - - MaximInterface_EXPORT virtual error_code - writeByteSetLevel(uint_least8_t sendByte, Level afterLevel); - - MaximInterface_EXPORT virtual error_code setSpeed(Speed newSpeed); - - MaximInterface_EXPORT virtual error_code setLevel(Level newLevel); - - MaximInterface_EXPORT static const error_category & errorCategory(); - -protected: - DS2482_DS2484(I2CMaster & master, uint_least8_t address) - : master(&master), address_(address) {} - - /// @note Allow marking const since not public. - error_code sendCommand(uint_least8_t cmd) const; - - /// @note Allow marking const since not public. - error_code sendCommand(uint_least8_t cmd, uint_least8_t param) const; - - /// @brief Reads a register from the device. - /// @param reg Register to read from. - /// @param[out] buf Buffer to hold read data. - error_code readRegister(uint_least8_t reg, uint_least8_t & buf) const; - - /// @brief Reads the current register from the device. - /// @param[out] buf Buffer to hold read data. - error_code readRegister(uint_least8_t & buf) const; - -private: - /// @brief Performs a soft reset on the device. - /// @note This is not a 1-Wire Reset. - error_code resetDevice(); - - /// @brief - /// Polls the device status waiting for the 1-Wire Busy bit (1WB) to be cleared. - /// @param[out] pStatus Optionally retrieve the status byte when 1WB cleared. - /// @returns Success or TimeoutError if poll limit reached. - error_code pollBusy(uint_least8_t * pStatus = NULL); - - /// @brief Ensure that the desired 1-Wire level is set in the configuration. - /// @param level Desired 1-Wire level. - error_code configureLevel(Level level); - - I2CMaster * master; - uint_least8_t address_; - Config curConfig; -}; - -inline error_code make_error_code(DS2482_DS2484::ErrorValue e) { - return error_code(e, DS2482_DS2484::errorCategory()); -} - -class DS2482_100 : public DS2482_DS2484 { -public: - DS2482_100(I2CMaster & i2c_bus, uint_least8_t adrs) - : DS2482_DS2484(i2c_bus, adrs) {} -}; - -/// DS2482-800 I2C to 1-Wire Master -class DS2482_800 : public DS2482_DS2484 { -public: - DS2482_800(I2CMaster & i2c_bus, uint_least8_t adrs) - : DS2482_DS2484(i2c_bus, adrs) {} - - /// @brief Select the active 1-Wire channel. - /// @param channel Channel number to select from 0 to 7. - MaximInterface_EXPORT error_code selectChannel(int channel); -}; - -/// DS2484 I2C to 1-Wire Master -class DS2484 : public DS2482_DS2484 { -public: - /// @brief 1-Wire port adjustment parameters. - /// @note See datasheet page 13. - enum PortParameter { - tRSTL = 0, - tRSTL_OD, - tMSP, - tMSP_OD, - tW0L, - tW0L_OD, - tREC0, // OD N/A - RWPU = 8 // OD N/A - }; - - explicit DS2484(I2CMaster & i2c_bus, uint_least8_t adrs = 0x30) - : DS2482_DS2484(i2c_bus, adrs) {} - - /// @brief Adjust 1-Wire port parameters. - /// @param param Parameter to adjust. - /// @param val New parameter value to set. Consult datasheet for value mappings. - MaximInterface_EXPORT error_code adjustPort(PortParameter param, int val); -}; - -} // namespace MaximInterface - -#endif
--- a/Devices/DS28C36_DS2476.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,724 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include <algorithm> -#include <MaximInterface/Links/I2CMaster.hpp> -#include <MaximInterface/Utilities/Error.hpp> -#include <MaximInterface/Utilities/RomId.hpp> -#include "DS28C36_DS2476.hpp" - -namespace MaximInterface { - -using namespace Ecc256; -using std::copy; - -static error_code convertResultByte(uint_least8_t resultByte) { - error_code errorCode; - if (resultByte != 0xAA) { - errorCode.assign((resultByte == 0x00) - ? static_cast<int>(DS28C36::AuthenticationError) - : resultByte, - DS28C36::errorCategory()); - } - return errorCode; -} - -const int DS28C36::publicKeyAxPage; -const int DS28C36::publicKeyAyPage; -const int DS28C36::publicKeyBxPage; -const int DS28C36::publicKeyByPage; -const int DS28C36::publicKeyCxPage; -const int DS28C36::publicKeyCyPage; -const int DS28C36::privateKeyAPage; -const int DS28C36::privateKeyBPage; -const int DS28C36::privateKeyCPage; -const int DS28C36::secretAPage; -const int DS28C36::secretBPage; -const int DS28C36::decrementCounterPage; -const int DS28C36::romOptionsPage; -const int DS28C36::gpioControlPage; -const int DS28C36::publicKeySxPage; -const int DS28C36::publicKeySyPage; -const int DS28C36::memoryPages; - -error_code DS28C36::writeMemory(int pageNum, Page::const_span page) { - if (pageNum < 0 || pageNum >= memoryPages) { - return make_error_code(InvalidParameterError); - } - - uint_least8_t buffer[1 + Page::size]; - buffer[0] = pageNum; - copy(page.begin(), page.end(), buffer + 1); - error_code result = writeCommand(0x96, buffer); - if (!result) { - sleep(writeMemoryTimeMs); - result = readFixedLengthResponse(make_span(buffer, 1)); - if (!result) { - result = convertResultByte(buffer[0]); - } - } - return result; -} - -error_code DS28C36::readMemory(int pageNum, Page::span page) { - if (pageNum < 0 || pageNum >= memoryPages) { - return make_error_code(InvalidParameterError); - } - - const uint_least8_t parameter = pageNum; - error_code result = writeCommand(0x69, make_span(¶meter, 1)); - if (!result) { - sleep(readMemoryTimeMs); - array<uint_least8_t, 1 + Page::size> response; - result = readFixedLengthResponse(response); - if (!result) { - result = convertResultByte(response[0]); - copy(response.begin() + 1, response.end(), page.begin()); - } - } - return result; -} - -error_code DS28C36::writeBuffer(span<const uint_least8_t> data) { - return writeCommand(0x87, data); -} - -error_code DS28C36::readBuffer(std::vector<uint_least8_t> & data) { - error_code result = writeCommand(0x5A); - if (!result) { - data.resize(80); - span<uint_least8_t> dataSpan(data); - result = readVariableLengthResponse(dataSpan); - if (result) { - data.clear(); - } else { - data.resize(dataSpan.size()); - } - } - return result; -} - -error_code DS28C36::readPageProtection(int pageNum, - PageProtection & protection) { - if (pageNum < 0 || pageNum >= memoryPages) { - return make_error_code(InvalidParameterError); - } - - uint_least8_t buffer = pageNum; - error_code result = writeCommand(0xAA, make_span(&buffer, 1)); - if (!result) { - sleep(readMemoryTimeMs); - result = readFixedLengthResponse(make_span(&buffer, 1)); - if (!result) { - protection = buffer; - } - } - return result; -} - -error_code DS28C36::setPageProtection(int pageNum, - const PageProtection & protection) { - if (pageNum < 0 || pageNum >= memoryPages) { - return make_error_code(InvalidParameterError); - } - - uint_least8_t buffer[] = {static_cast<uint_least8_t>(pageNum), - static_cast<uint_least8_t>(protection.to_ulong())}; - error_code result = writeCommand(0xC3, buffer); - if (!result) { - sleep(writeMemoryTimeMs); - result = readFixedLengthResponse(make_span(buffer, 1)); - if (!result) { - result = convertResultByte(buffer[0]); - } - } - return result; -} - -error_code DS28C36::decrementCounter() { - error_code result = writeCommand(0xC9); - if (!result) { - sleep(writeMemoryTimeMs); - uint_least8_t response; - result = readFixedLengthResponse(make_span(&response, 1)); - if (!result) { - result = convertResultByte(response); - } - } - return result; -} - -error_code DS28C36::readRng(span<uint_least8_t> data) { - if ((data.size() < 1) || (data.size() > 64)) { - return make_error_code(InvalidParameterError); - } - - data[0] = static_cast<uint_least8_t>(data.size() - 1); - error_code result = writeCommand(0xD2, data.first(1)); - if (!result) { - sleep(sha256ComputationTimeMs); - result = readFixedLengthResponse(data); - } - return result; -} - -error_code DS28C36::encryptedReadMemory(int pageNum, SecretNum secretNum, - EncryptionChallenge::span challenge, - Page::span data) { - if (pageNum < 0 || pageNum >= memoryPages) { - return make_error_code(InvalidParameterError); - } - - const uint_least8_t parameter = (secretNum << 6) | pageNum; - error_code result = writeCommand(0x4B, make_span(¶meter, 1)); - if (!result) { - sleep(readMemoryTimeMs + sha256ComputationTimeMs); - uint_least8_t response[1 + EncryptionChallenge::size + Page::size]; - result = readFixedLengthResponse(response); - if (!result) { - result = convertResultByte(response[0]); - const uint_least8_t * begin = response + 1; - const uint_least8_t * end = begin + challenge.size(); - copy(begin, end, challenge.begin()); - begin = end; - end = begin + data.size(); - copy(begin, end, data.begin()); - } - } - return result; -} - -error_code DS28C36::computeAndReadPageAuthentication(int pageNum, - AuthType authType) { - if (pageNum < 0 || pageNum >= memoryPages) { - return make_error_code(InvalidParameterError); - } - - const uint_least8_t parameter = (authType << 5) | pageNum; - return writeCommand(0xA5, make_span(¶meter, 1)); -} - -error_code -DS28C36::computeAndReadPageAuthentication(int pageNum, KeyNum keyNum, - Signature::span signature) { - AuthType authType; - switch (keyNum) { - case KeyNumA: - authType = EcdsaWithKeyA; - break; - case KeyNumB: - authType = EcdsaWithKeyB; - break; - case KeyNumC: - authType = EcdsaWithKeyC; - break; - default: - return make_error_code(InvalidParameterError); - } - error_code result = computeAndReadPageAuthentication(pageNum, authType); - if (!result) { - sleep(readMemoryTimeMs + generateEcdsaSignatureTimeMs); - uint_least8_t response[1 + 2 * Scalar::size]; - result = readFixedLengthResponse(response); - if (!result) { - result = convertResultByte(response[0]); - const uint_least8_t * begin = response + 1; - const uint_least8_t * end = begin + signature.s.size(); - copy(begin, end, signature.s.begin()); - begin = end; - end = begin + signature.r.size(); - copy(begin, end, signature.r.begin()); - } - } - return result; -} - -error_code DS28C36::computeAndReadPageAuthentication(int pageNum, - SecretNum secretNum, - Sha256::Hash::span hmac) { - AuthType authType; - switch (secretNum) { - case SecretNumA: - authType = HmacWithSecretA; - break; - case SecretNumB: - authType = HmacWithSecretB; - break; - case SecretNumS: - authType = HmacWithSecretS; - break; - default: - return make_error_code(InvalidParameterError); - } - error_code result = computeAndReadPageAuthentication(pageNum, authType); - if (!result) { - sleep(readMemoryTimeMs + sha256ComputationTimeMs); - array<uint_least8_t, 1 + Sha256::Hash::size> response; - result = readFixedLengthResponse(response); - if (!result) { - result = convertResultByte(response[0]); - copy(response.begin() + 1, response.end(), hmac.begin()); - } - } - return result; -} - -error_code DS28C36::authenticatedSha2WriteMemory(int pageNum, - SecretNum secretNum, - Page::const_span page) { - if (pageNum < 0 || pageNum >= memoryPages) { - return make_error_code(InvalidParameterError); - } - - uint_least8_t buffer[1 + Page::size]; - buffer[0] = (secretNum << 6) | pageNum; - copy(page.begin(), page.end(), buffer + 1); - error_code result = writeCommand(0x99, buffer); - if (!result) { - sleep(writeMemoryTimeMs + (2 * sha256ComputationTimeMs)); - result = readFixedLengthResponse(make_span(buffer, 1)); - if (!result) { - result = convertResultByte(buffer[0]); - } - } - return result; -} - -error_code DS28C36::computeAndLockSha2Secret(int pageNum, SecretNum msecretNum, - SecretNum dsecretNum, - bool writeProtectEnable) { - // User pages only - if (pageNum < 0 || pageNum > 15) { - return make_error_code(InvalidParameterError); - } - - uint_least8_t buffer[] = { - static_cast<uint_least8_t>((dsecretNum << 6) | (msecretNum << 4) | - pageNum), - static_cast<uint_least8_t>(writeProtectEnable ? 0x80 : 0x00)}; - error_code result = writeCommand(0x3C, buffer); - if (!result) { - sleep(sha256ComputationTimeMs + - ((writeProtectEnable ? 2 : 1) * writeMemoryTimeMs)); - result = readFixedLengthResponse(make_span(buffer, 1)); - if (!result) { - result = convertResultByte(buffer[0]); - } - } - return result; -} - -error_code DS28C36::generateEcc256KeyPair(KeyNum keyNum, - bool writeProtectEnable) { - if (keyNum == KeyNumS) { - return make_error_code(InvalidParameterError); - } - - uint_least8_t buffer = keyNum; - if (writeProtectEnable) { - buffer |= 0x80; - } - error_code result = writeCommand(0xCB, make_span(&buffer, 1)); - if (!result) { - sleep(generateEccKeyPairTimeMs); - result = readFixedLengthResponse(make_span(&buffer, 1)); - if (!result) { - result = convertResultByte(buffer); - } - } - return result; -} - -error_code DS28C36::computeMultiblockHash(bool firstBlock, bool lastBlock, - span<const uint_least8_t> data) { - const span<const uint_least8_t>::index_type maxDataSize = 64; - - if (data.size() < 1 || data.size() > maxDataSize) { - return make_error_code(InvalidParameterError); - } - - uint_least8_t buffer[1 + maxDataSize]; - buffer[0] = 0; - if (firstBlock) { - buffer[0] |= 0x40; - } - if (lastBlock) { - buffer[0] |= 0x80; - } - copy(data.begin(), data.end(), buffer + 1); - error_code result = writeCommand(0x33, make_span(buffer, data.size() + 1)); - if (!result) { - sleep(sha256ComputationTimeMs); - result = readFixedLengthResponse(make_span(buffer, 1)); - if (!result) { - result = convertResultByte(buffer[0]); - } - } - return result; -} - -error_code DS28C36::verifyEcdsaSignature(KeyNum keyNum, HashType hashType, - Signature::const_span signature, - PioState pioa, PioState piob) { - uint_least8_t buffer[1 + 2 * Scalar::size]; - buffer[0] = keyNum | (hashType << 2); - if (pioa != Unchanged) { - buffer[0] |= 0x20; - } - if (pioa == Conducting) { - buffer[0] |= 0x10; - } - if (piob != Unchanged) { - buffer[0] |= 0x80; - } - if (piob == Conducting) { - buffer[0] |= 0x40; - } - uint_least8_t * bufferIt = - copy(signature.r.begin(), signature.r.end(), buffer + 1); - copy(signature.s.begin(), signature.s.end(), bufferIt); - error_code result = writeCommand(0x59, buffer); - if (!result) { - sleep(verifyEsdsaSignatureOrComputeEcdhTimeMs + - ((hashType == DataInBuffer) ? sha256ComputationTimeMs : 0)); - result = readFixedLengthResponse(make_span(buffer, 1)); - if (!result) { - result = convertResultByte(buffer[0]); - } - } - return result; -} - -error_code -DS28C36::authenticateEcdsaPublicKey(bool authWrites, bool ecdh, KeyNum keyNum, - int csOffset, - Signature::const_span signature) { - if (((keyNum != KeyNumA) && (keyNum != KeyNumB)) || (csOffset < 0) || - (csOffset > 31)) { - return make_error_code(InvalidParameterError); - } - - uint_least8_t buffer[1 + 2 * Scalar::size]; - buffer[0] = (csOffset << 3) | (keyNum << 2); - if (ecdh) { - buffer[0] |= 0x02; - } - if (authWrites) { - buffer[0] |= 0x01; - } - uint_least8_t * bufferIt = - copy(signature.r.begin(), signature.r.end(), buffer + 1); - copy(signature.s.begin(), signature.s.end(), bufferIt); - error_code result = writeCommand(0xA8, buffer); - if (!result) { - sleep((ecdh ? 2 : 1) * verifyEsdsaSignatureOrComputeEcdhTimeMs); - result = readFixedLengthResponse(make_span(buffer, 1)); - if (!result) { - result = convertResultByte(buffer[0]); - } - } - return result; -} - -error_code DS28C36::authenticatedEcdsaWriteMemory(int pageNum, - Page::const_span page) { - if (pageNum < 0 || pageNum >= memoryPages) { - return make_error_code(InvalidParameterError); - } - - uint_least8_t buffer[1 + Page::size]; - buffer[0] = pageNum; - copy(page.begin(), page.end(), buffer + 1); - error_code result = writeCommand(0x89, buffer); - if (!result) { - sleep(verifyEsdsaSignatureOrComputeEcdhTimeMs + writeMemoryTimeMs + - sha256ComputationTimeMs); - result = readFixedLengthResponse(make_span(buffer, 1)); - if (!result) { - result = convertResultByte(buffer[0]); - } - } - return result; -} - -error_code DS28C36::writeCommand(uint_least8_t command, - span<const uint_least8_t> parameters) { - error_code result = master->start(address_); - if (result) { - master->stop(); - return result; - } - result = master->writeByte(command); - if (result) { - master->stop(); - return result; - } - if (!parameters.empty()) { - result = master->writeByte(static_cast<uint_least8_t>(parameters.size())); - if (result) { - master->stop(); - return result; - } - result = master->writeBlock(parameters); - if (result) { - master->stop(); - return result; - } - } - result = master->stop(); - return result; -} - -error_code DS28C36::readVariableLengthResponse(span<uint_least8_t> & response) { - error_code result = master->start(address_ | 1); - if (result) { - master->stop(); - return result; - } - uint_least8_t length; - result = master->readByte(I2CMaster::Ack, length); - if (result) { - master->stop(); - return result; - } - if (length > response.size()) { - master->stop(); - return make_error_code(InvalidResponseError); - } - response = response.first(length); - if (!response.empty()) { - result = master->readBlock(I2CMaster::Nack, response); - if (result) { - master->stop(); - return result; - } - } - result = master->stop(); - return result; -} - -error_code DS28C36::readFixedLengthResponse(span<uint_least8_t> response) { - const span<uint_least8_t>::index_type requestedResponseSize = response.size(); - error_code result = readVariableLengthResponse(response); - if (!result && response.size() != requestedResponseSize) { - result = make_error_code(InvalidResponseError); - } - return result; -} - -const error_category & DS28C36::errorCategory() { - static class : public error_category { - public: - virtual const char * name() const { return "DS28C36"; } - - virtual std::string message(int condition) const { - switch (condition) { - case ProtectionError: - return "Protection Error"; - - case InvalidParameterError: - return "Invalid Parameter Error"; - - case InvalidSequenceError: - return "Invalid Sequence Error"; - - case InvalidEcdsaInputOrResultError: - return "Invalid ECDSA Input or Result Error"; - - case AuthenticationError: - return "Authentication Error"; - - case InvalidResponseError: - return "Invalid Response Error"; - - default: - return defaultErrorMessage(condition); - } - } - } instance; - return instance; -} - -error_code DS2476::generateEcdsaSignature(KeyNum keyNum, - Signature::span signature) { - if (keyNum == KeyNumS) { - return make_error_code(InvalidParameterError); - } - - const uint_least8_t parameter = keyNum; - error_code result = writeCommand(0x1E, make_span(¶meter, 1)); - if (!result) { - sleep(generateEcdsaSignatureTimeMs); - uint_least8_t response[1 + 2 * Scalar::size]; - result = readFixedLengthResponse(response); - if (!result) { - result = convertResultByte(response[0]); - const uint_least8_t * begin = response + 1; - const uint_least8_t * end = begin + signature.s.size(); - copy(begin, end, signature.s.begin()); - begin = end; - end = begin + signature.r.size(); - copy(begin, end, signature.r.begin()); - } - } - return result; -} - -error_code DS2476::computeSha2UniqueSecret(SecretNum msecretNum) { - uint_least8_t buffer = msecretNum << 4; - error_code result = writeCommand(0x55, make_span(&buffer, 1)); - if (!result) { - sleep(sha256ComputationTimeMs); - result = readFixedLengthResponse(make_span(&buffer, 1)); - if (!result) { - convertResultByte(buffer); - } - } - return result; -} - -error_code DS2476::computeSha2Hmac(Sha256::Hash::span hmac) { - error_code result = writeCommand(0x2D); - if (!result) { - sleep(sha256ComputationTimeMs); - array<uint_least8_t, 1 + Sha256::Hash::size> response; - result = readFixedLengthResponse(response); - if (!result) { - result = convertResultByte(response[0]); - copy(response.begin() + 1, response.end(), hmac.begin()); - } - } - return result; -} - -error_code computeMultiblockHash(DS28C36 & ds28c36, - span<const uint_least8_t> data) { - error_code result; - span<const uint_least8_t>::index_type dataIdx = 0; - while (dataIdx < data.size() && !result) { - const span<const uint_least8_t>::index_type remainingSize = - data.size() - dataIdx; - const span<const uint_least8_t>::index_type chunkSize = - std::min<span<const uint_least8_t>::index_type>(remainingSize, 64); - result = - ds28c36.computeMultiblockHash(dataIdx == 0, remainingSize == chunkSize, - data.subspan(dataIdx, chunkSize)); - dataIdx += chunkSize; - } - return result; -} - -error_code verifyEcdsaSignature(DS28C36 & ds28c36, DS28C36::KeyNum publicKey, - span<const uint_least8_t> data, - Signature::const_span signature, - DS28C36::PioState pioa, - DS28C36::PioState piob) { - error_code result = computeMultiblockHash(ds28c36, data); - if (!result) { - result = ds28c36.verifyEcdsaSignature(publicKey, DS28C36::THASH, signature, - pioa, piob); - } - return result; -} - -error_code verifyEcdsaSignature(DS28C36 & ds28c36, - PublicKey::const_span publicKey, - span<const uint_least8_t> data, - Signature::const_span signature, - DS28C36::PioState pioa, - DS28C36::PioState piob) { - error_code result = - ds28c36.writeMemory(DS28C36::publicKeySxPage, publicKey.x); - if (!result) { - result = ds28c36.writeMemory(DS28C36::publicKeySyPage, publicKey.y); - } - if (!result) { - result = verifyEcdsaSignature(ds28c36, DS28C36::KeyNumS, data, signature, - pioa, piob); - } - return result; -} - -error_code readRomIdAndManId(DS28C36 & ds28c36, RomId::span romId, - ManId::span manId) { - DS28C36::Page::array page; - error_code result = ds28c36.readMemory(DS28C36::romOptionsPage, page); - if (!result) { - const DS28C36::RomOptions romOptions(page); - copy(romOptions.romId(), romId); - copy(romOptions.manId(), manId); - } - return result; -} - -error_code enableCoprocessor(DS2476 & ds2476) { - DS2476::Page::array page; - error_code result = ds2476.readMemory(DS2476::gpioControlPage, page); - if (!result) { - DS2476::GpioControl gpioControl(page); - if (!gpioControl.pioaConducting()) { - gpioControl.setPioaConducting(true); - result = ds2476.writeMemory(DS2476::gpioControlPage, page); - } - } - return result; -} - -error_code enableRomId(DS2476 & ds2476) { - DS2476::Page::array page; - error_code result = ds2476.readMemory(DS2476::romOptionsPage, page); - if (!result) { - DS2476::RomOptions romOptions(page); - if (!romOptions.romBlockDisable()) { - romOptions.setRomBlockDisable(true); - result = ds2476.writeMemory(DS2476::romOptionsPage, page); - } - } - return result; -} - -static void setAnonymous(RomId::span romId) { - std::fill(romId.begin(), romId.end(), 0xFF); -} - -DS28C36::PageAuthenticationData & -DS28C36::PageAuthenticationData::setAnonymousRomId() { - setAnonymous(romId()); - return *this; -} - -DS28C36::EncryptionHmacData & DS28C36::EncryptionHmacData::setAnonymousRomId() { - setAnonymous(romId()); - return *this; -} - -} // namespace MaximInterface
--- a/Devices/DS28C36_DS2476.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,923 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_DS28C36_DS2476 -#define MaximInterface_DS28C36_DS2476 - -#include <stdint.h> -#include <vector> -#include <MaximInterface/Links/I2CMaster.hpp> -#include <MaximInterface/Links/Sleep.hpp> -#include <MaximInterface/Utilities/array_span.hpp> -#include <MaximInterface/Utilities/Ecc256.hpp> -#include <MaximInterface/Utilities/Export.h> -#include <MaximInterface/Utilities/RomId.hpp> -#include <MaximInterface/Utilities/ManId.hpp> -#include <MaximInterface/Utilities/Sha256.hpp> -#include <MaximInterface/Utilities/system_error.hpp> -#include <MaximInterface/Utilities/FlagSet.hpp> - -namespace MaximInterface { - -/// Interface to the DS28C36 authenticator. -class DS28C36 { -public: - /// Device command results. - enum ErrorValue { - ProtectionError = 0x55, - InvalidParameterError = 0x77, - InvalidSequenceError = 0x33, - InvalidEcdsaInputOrResultError = 0x22, - AuthenticationError = 0x100, - InvalidResponseError = 0x101 ///< Response does not match expected format. - }; - - /// @name Device memory pages - /// @{ - - static const int publicKeyAxPage = 16; - static const int publicKeyAyPage = 17; - static const int publicKeyBxPage = 18; - static const int publicKeyByPage = 19; - static const int publicKeyCxPage = 20; - static const int publicKeyCyPage = 21; - static const int privateKeyAPage = 22; - static const int privateKeyBPage = 23; - static const int privateKeyCPage = 24; - static const int secretAPage = 25; - static const int secretBPage = 26; - static const int decrementCounterPage = 27; - static const int romOptionsPage = 28; - static const int gpioControlPage = 29; - static const int publicKeySxPage = 30; - static const int publicKeySyPage = 31; - - /// @} - - /// Number of memory pages on the device. - static const int memoryPages = 32; - - /// Available keys for ECDSA operations. - enum KeyNum { KeyNumA = 0, KeyNumB = 1, KeyNumC = 2, KeyNumS = 3 }; - - /// Available secrets for HMAC operations. - enum SecretNum { SecretNumA = 0, SecretNumB = 1, SecretNumS = 2 }; - - /// Data hash type when verifying an ECDSA signature. - enum HashType { - HashInBuffer = 0, ///< Hash is loaded in the buffer. - DataInBuffer = 1, ///< Compute hash from data loaded in the buffer. - THASH = 2 ///< Use THASH from Compute Multiblock Hash command. - }; - - /// Available PIO states when verifying an ECDSA signature. - enum PioState { Unchanged, Conducting, HighImpedance }; - - /// Holds a device memory page. - typedef array_span<uint_least8_t, 32> Page; - - // Format page authentication input data. - class PageAuthenticationData; - - // Format authenticated write input data. - class WriteAuthenticationData; - - // Format compute secret input data. - class ComputeSecretData; - - // Format encryption or decryption HMAC input data. - class EncryptionHmacData; - - // Access fields in the ROM Options page. - class RomOptions; - - // Access fields in the GPIO Control page. - class GpioControl; - - /// Page protection types. - enum PageProtectionType { - RP = 0x01, ///< Read protection. - WP = 0x02, ///< Write protection. - EM = 0x04, ///< EPROM emulation mode. - APH = 0x08, ///< Authentication write protection HMAC. - EPH = 0x10, ///< Encryption and authenticated write protection HMAC. - AUTH = 0x20, ///< Public Key C is set to authority public key. - ECH = 0x40, ///< Encrypted read and write using shared key from ECDH. - ECW = 0x80 ///< Authentication write protection ECDSA. - }; - typedef FlagSet<PageProtectionType, 8> PageProtection; - - /// Challenge for an encrypted device memory page. - typedef array_span<uint_least8_t, 8> EncryptionChallenge; - - DS28C36(Sleep & sleep, I2CMaster & master, uint_least8_t address = 0x36) - : sleep_(&sleep), master(&master), address_(address & 0xFE) {} - - void setSleep(Sleep & sleep) { sleep_ = &sleep; } - - void setMaster(I2CMaster & master) { this->master = &master; } - - uint_least8_t address() const { return address_; } - - void setAddress(uint_least8_t address) { address_ = address & 0xFE; } - - /// @brief Write memory with no protection. - /// @param pageNum Number of page to write. - /// @param page Data to write. - MaximInterface_EXPORT error_code writeMemory(int pageNum, - Page::const_span page); - - /// @brief Read memory with no protection. - /// @param pageNum Number of page to read. - /// @param[out] page Data that was read. - MaximInterface_EXPORT error_code readMemory(int pageNum, Page::span page); - - /// @brief Write the temporary buffer. - /// @param data Data to write. - MaximInterface_EXPORT error_code writeBuffer(span<const uint_least8_t> data); - - /// @brief Read the temporary buffer. - /// @param[out] data Data that was read. - MaximInterface_EXPORT error_code - readBuffer(std::vector<uint_least8_t> & data); - - /// @brief Read the protection settings of a page. - /// @param pageNum Number of page to read. - /// @param[out] protection Protection that was read. - MaximInterface_EXPORT error_code - readPageProtection(int pageNum, PageProtection & protection); - - /// @brief Set the protection settings of a page. - /// @param pageNum Number of page to write. - /// @param protection Protection to write. - MaximInterface_EXPORT error_code - setPageProtection(int pageNum, const PageProtection & protection); - - /// Decrement the decrement-only counter. - MaximInterface_EXPORT error_code decrementCounter(); - - /// @brief Read a block of random data from the RNG. - /// @param[out] data Random data from RNG with length from 1 to 64. - MaximInterface_EXPORT error_code readRng(span<uint_least8_t> data); - - /// @brief Read memory with encryption. - /// @param pageNum Number of page to read from. - /// @param secretNum Secret to use for encryption. - /// @param[out] challenge Encryption challenge that was read. - /// @param[out] data Encrypted page data that was read. - MaximInterface_EXPORT error_code - encryptedReadMemory(int pageNum, SecretNum secretNum, - EncryptionChallenge::span challenge, Page::span data); - - /// @brief Compute and read page authentication with ECDSA. - /// @param pageNum Number of page to authenticate. - /// @param keyNum - /// Private key to use for authentication. - /// Key S cannot be used with this command. - /// @param[out] signature Computed page signature. - MaximInterface_EXPORT error_code computeAndReadPageAuthentication( - int pageNum, KeyNum keyNum, Ecc256::Signature::span signature); - - /// @brief Compute and read page authentication with HMAC. - /// @param pageNum Number of page to authenticate. - /// @param secretNum Secret to use for authentication. - /// @param[out] hmac Computed page HMAC. - MaximInterface_EXPORT error_code computeAndReadPageAuthentication( - int pageNum, SecretNum secretNum, Sha256::Hash::span hmac); - - /// @brief Write with SHA2 authentication. - /// @param pageNum Number of page to write. - /// @param secretNum Secret to use for authentication. - /// @param page Data to write. - MaximInterface_EXPORT error_code authenticatedSha2WriteMemory( - int pageNum, SecretNum secretNum, Page::const_span page); - - /// @brief Compute SHA2 secret and optionally lock. - /// @param pageNum Number of page to use in computation. - /// @param msecretNum Master secret to use in computation. - /// @param dsecretNum Destination secret to receive the computation result. - /// @param writeProtectEnable - /// True to lock the destination secret against further writes. - MaximInterface_EXPORT error_code - computeAndLockSha2Secret(int pageNum, SecretNum msecretNum, - SecretNum dsecretNum, bool writeProtectEnable); - - /// @brief Generate a new ECDSA key pair. - /// @param keyNum Key to generate. Key S cannot be used with this command. - /// @param writeProtectEnable True to lock the key against further writes. - MaximInterface_EXPORT error_code - generateEcc256KeyPair(KeyNum keyNum, bool writeProtectEnable); - - /// @brief Compute a hash over multiple blocks. - /// @param firstBlock True if this is the first block being hashed. - /// @param lastBlock True if this is the last block being hashed. - /// @param data - /// Data block to hash. Should be 64 bytes unless this is the last block. - MaximInterface_EXPORT error_code computeMultiblockHash( - bool firstBlock, bool lastBlock, span<const uint_least8_t> data); - - /// @brief Verify ECDSA signature. - /// @param keyNum Public key to use for verification. - /// @param hashType Source of the data hash input. - /// @param signature Signature to verify. - /// @param pioa New state of PIOA if verification successful. - /// @param piob New state of PIOB if verification successful. - MaximInterface_EXPORT error_code verifyEcdsaSignature( - KeyNum keyNum, HashType hashType, Ecc256::Signature::const_span signature, - PioState pioa = Unchanged, PioState piob = Unchanged); - - /// @brief - /// Authenticate a public key for authenticated writes or encrypted reads - /// with ECDH. - /// @param authWrites True to select authentication for writes. - /// @param ecdh True to select ECDH key exchange. - /// @param keyNum - /// Private key to use for ECDH key exchange. Key A or B can be selected. - /// @param csOffset Certificate customization field ending offset in buffer. - /// @param signature Signature to use for authentication of public key S. - MaximInterface_EXPORT error_code authenticateEcdsaPublicKey( - bool authWrites, bool ecdh, KeyNum keyNum, int csOffset, - Ecc256::Signature::const_span signature); - - /// @brief Write with ECDSA authentication. - /// @param pageNum Number of page to write. - /// @param page Data to write. - MaximInterface_EXPORT error_code - authenticatedEcdsaWriteMemory(int pageNum, Page::const_span page); - - MaximInterface_EXPORT static const error_category & errorCategory(); - -protected: - // Timing constants. - static const int generateEcdsaSignatureTimeMs = 50; - static const int generateEccKeyPairTimeMs = 100; - static const int verifyEsdsaSignatureOrComputeEcdhTimeMs = 150; - static const int sha256ComputationTimeMs = 3; - static const int readMemoryTimeMs = /*1*/ 2; - static const int writeMemoryTimeMs = 15; - - error_code writeCommand(uint_least8_t command, - span<const uint_least8_t> parameters); - - error_code writeCommand(uint_least8_t command) { - return writeCommand(command, span<const uint_least8_t>()); - } - - error_code readVariableLengthResponse(span<uint_least8_t> & response); - - error_code readFixedLengthResponse(span<uint_least8_t> response); - - void sleep(int ms) const { sleep_->invoke(ms); } - -private: - enum AuthType { - HmacWithSecretA = 0, - HmacWithSecretB = 1, - HmacWithSecretS = 2, - EcdsaWithKeyA = 3, - EcdsaWithKeyB = 4, - EcdsaWithKeyC = 5 - }; - - const Sleep * sleep_; - I2CMaster * master; - uint_least8_t address_; - - error_code computeAndReadPageAuthentication(int pageNum, AuthType authType); -}; - -/// Interface to the DS2476 coprocessor. -class DS2476 : public DS28C36 { -public: - DS2476(Sleep & sleep, I2CMaster & master, uint_least8_t address = 0x76) - : DS28C36(sleep, master, address) {} - - /// @brief Generate ECDSA signature. - /// @param keyNum - /// Private key to use to create signature. - /// Key S cannot be used with this command. - /// @param[out] signature Computed signature. - MaximInterface_EXPORT error_code - generateEcdsaSignature(KeyNum keyNum, Ecc256::Signature::span signature); - - /// @brief Compute unique SHA2 secret. - /// @param msecretNum Master secret to use in computation. - MaximInterface_EXPORT error_code - computeSha2UniqueSecret(SecretNum msecretNum); - - /// @brief Compute SHA2 HMAC. - /// @param[out] hmac Computed HMAC. - MaximInterface_EXPORT error_code computeSha2Hmac(Sha256::Hash::span hmac); -}; - -inline error_code make_error_code(DS28C36::ErrorValue e) { - return error_code(e, DS28C36::errorCategory()); -} - -/// @brief -/// Hash arbitrary length data with successive Compute Multiblock Hash commands. -/// @param ds28c36 Device for computation. -/// @param data Data to hash. -MaximInterface_EXPORT error_code -computeMultiblockHash(DS28C36 & ds28c36, span<const uint_least8_t> data); - -/// @brief Verify ECDSA signature. -/// @param ds28c36 Device for computation. -/// @param publicKey Public key to use for verification. -/// @param data Data to verify. -/// @param signature Signature to verify. -/// @param pioa New state of PIOA if verification successful. -/// @param piob New state of PIOB if verification successful. -MaximInterface_EXPORT error_code verifyEcdsaSignature( - DS28C36 & ds28c36, DS28C36::KeyNum publicKey, - span<const uint_least8_t> data, Ecc256::Signature::const_span signature, - DS28C36::PioState pioa = DS28C36::Unchanged, - DS28C36::PioState piob = DS28C36::Unchanged); - -/// @brief Verify ECDSA signature. -/// @param ds28c36 Device for computation. -/// @param publicKey -/// Public key to use for verification which is loaded into Public Key S. -/// @param data Data to verify. -/// @param signature Signature to verify. -/// @param pioa New state of PIOA if verification successful. -/// @param piob New state of PIOB if verification successful. -MaximInterface_EXPORT error_code verifyEcdsaSignature( - DS28C36 & ds28c36, Ecc256::PublicKey::const_span publicKey, - span<const uint_least8_t> data, Ecc256::Signature::const_span signature, - DS28C36::PioState pioa = DS28C36::Unchanged, - DS28C36::PioState piob = DS28C36::Unchanged); - -/// @brief -/// Read the device ROM ID and MAN ID using the Read Memory command on the -/// ROM Options page. -/// @param ds28c36 Device to read. -/// @param[out] romId Read ROM ID valid when operation is successful. -/// @param[out] manId Read MAN ID valid when operation is successful. -MaximInterface_EXPORT error_code readRomIdAndManId(DS28C36 & ds28c36, - RomId::span romId, - ManId::span manId); - -/// @brief -/// Enable coprocessor functionality on the DS2476 by writing to the -/// GPIO Control page. -MaximInterface_EXPORT error_code enableCoprocessor(DS2476 & ds2476); - -/// @brief -/// Disable blocking of the ROM ID on the DS2476 by writing to the -/// ROM Options page. -MaximInterface_EXPORT error_code enableRomId(DS2476 & ds2476); - -/// Format page authentication input data. -class DS28C36::PageAuthenticationData { -public: - typedef array_span<uint_least8_t, - RomId::size + 2 * Page::size + 1 + ManId::size> - Result; - - PageAuthenticationData() : result_() {} - - /// Formatted data result. - Result::const_span result() const { return result_; } - - /// @name ROM ID - /// @brief 1-Wire ROM ID of the device. - /// @{ - - /// Get mutable ROM ID. - RomId::span romId() { - return make_span(result_).subspan<romIdIdx, RomId::size>(); - } - - /// Get immutable ROM ID. - RomId::const_span romId() const { - return const_cast<PageAuthenticationData &>(*this).romId(); - } - - /// Set ROM ID. - PageAuthenticationData & setRomId(RomId::const_span romId) { - copy(romId, this->romId()); - return *this; - } - - /// Set ROM ID for use in anonymous mode. - MaximInterface_EXPORT PageAuthenticationData & setAnonymousRomId(); - - /// @} - - /// @name Page - /// @brief Data from a device memory page. - /// @{ - - /// Get mutable page. - Page::span page() { - return make_span(result_).subspan<pageIdx, Page::size>(); - } - - /// Get immutable page. - Page::const_span page() const { - return const_cast<PageAuthenticationData &>(*this).page(); - } - - /// Set page. - PageAuthenticationData & setPage(Page::const_span page) { - copy(page, this->page()); - return *this; - } - - /// @} - - /// @name Challenge - /// @brief Random challenge used to prevent replay attacks. - /// @{ - - /// Get mutable Challenge. - Page::span challenge() { - return make_span(result_).subspan<challengeIdx, Page::size>(); - } - - /// Get immutable Challenge. - Page::const_span challenge() const { - return const_cast<PageAuthenticationData &>(*this).challenge(); - } - - /// Set Challenge. - PageAuthenticationData & setChallenge(Page::const_span challenge) { - copy(challenge, this->challenge()); - return *this; - } - - /// @} - - /// @name Page number - /// @brief Number of the page to use data from. - /// @{ - - /// Get page number. - int pageNum() const { return result_[pageNumIdx]; } - - /// Set page number. - PageAuthenticationData & setPageNum(int pageNum) { - result_[pageNumIdx] = pageNum; - return *this; - } - - /// @} - - /// @name MAN ID - /// @brief Manufacturer ID of the device. - /// @{ - - /// Get mutable MAN ID. - ManId::span manId() { - return make_span(result_).subspan<manIdIdx, ManId::size>(); - } - - /// Get immutable MAN ID. - ManId::const_span manId() const { - return const_cast<PageAuthenticationData &>(*this).manId(); - } - - /// Set MAN ID. - PageAuthenticationData & setManId(ManId::const_span manId) { - copy(manId, this->manId()); - return *this; - } - - /// @} - -private: - typedef Result::span::index_type index; - - static const index romIdIdx = 0; - static const index pageIdx = romIdIdx + RomId::size; - static const index challengeIdx = pageIdx + Page::size; - static const index pageNumIdx = challengeIdx + Page::size; - static const index manIdIdx = pageNumIdx + 1; - - Result::array result_; -}; - -/// Format authenticated write input data. -class DS28C36::WriteAuthenticationData { -public: - typedef PageAuthenticationData::Result Result; - - WriteAuthenticationData() : data() {} - - /// Formatted data result. - Result::const_span result() const { return data.result(); } - - /// @name ROM ID - /// @brief 1-Wire ROM ID of the device. - /// @{ - - /// Get mutable ROM ID. - RomId::span romId() { return data.romId(); } - - /// Get immutable ROM ID. - RomId::const_span romId() const { return data.romId(); } - - /// Set ROM ID. - WriteAuthenticationData & setRomId(RomId::const_span romId) { - data.setRomId(romId); - return *this; - } - - /// Set ROM ID for use in anonymous mode. - WriteAuthenticationData & setAnonymousRomId() { - data.setAnonymousRomId(); - return *this; - } - - /// @} - - /// @name Old page - /// @brief Existing data contained in the page. - /// @{ - - /// Get mutable old page. - Page::span oldPage() { return data.page(); } - - /// Get immutable old page. - Page::const_span oldPage() const { return data.page(); } - - /// Set old page. - WriteAuthenticationData & setOldPage(Page::const_span oldPage) { - data.setPage(oldPage); - return *this; - } - - /// @} - - /// @name New page - /// @brief New data to write to the page. - /// @{ - - /// Get mutable new page. - Page::span newPage() { return data.challenge(); } - - /// Get immutable new page. - Page::const_span newPage() const { return data.challenge(); } - - /// Set new page. - WriteAuthenticationData & setNewPage(Page::const_span newPage) { - data.setChallenge(newPage); - return *this; - } - - /// @} - - /// @name Page number - /// @brief Page number for write operation. - /// @{ - - /// Get page number. - int pageNum() const { return data.pageNum(); } - - /// Set page number. - WriteAuthenticationData & setPageNum(int pageNum) { - data.setPageNum(pageNum); - return *this; - } - - /// @} - - /// @name MAN ID - /// @brief Manufacturer ID of the device. - /// @{ - - /// Get mutable MAN ID. - ManId::span manId() { return data.manId(); } - - /// Get immutable MAN ID. - ManId::const_span manId() const { return data.manId(); } - - /// Set MAN ID. - WriteAuthenticationData & setManId(ManId::const_span manId) { - data.setManId(manId); - return *this; - } - - /// @} - -private: - PageAuthenticationData data; -}; - -/// Format compute secret input data. -class DS28C36::ComputeSecretData { -public: - typedef PageAuthenticationData::Result Result; - - ComputeSecretData() : data() {} - - /// Formatted data result. - Result::const_span result() const { return data.result(); } - - /// @name ROM ID - /// @brief 1-Wire ROM ID of the device. - /// @{ - - /// Get mutable ROM ID. - RomId::span romId() { return data.romId(); } - - /// Get immutable ROM ID. - RomId::const_span romId() const { return data.romId(); } - - /// Set ROM ID. - ComputeSecretData & setRomId(RomId::const_span romId) { - data.setRomId(romId); - return *this; - } - - /// @} - - /// @name Binding Data - /// @brief Binding Data contained in the selected page. - /// @{ - - /// Get mutable Binding Data. - Page::span bindingData() { return data.page(); } - - /// Get immutable Binding Data. - Page::const_span bindingData() const { return data.page(); } - - /// Set Binding Data. - ComputeSecretData & setBindingData(Page::const_span bindingData) { - data.setPage(bindingData); - return *this; - } - - /// @} - - /// @name Partial Secret - /// @brief Partial Secret used for customization. - /// @{ - - /// Get mutable Partial Secret. - Page::span partialSecret() { return data.challenge(); } - - /// Get immutable Partial Secret. - Page::const_span partialSecret() const { return data.challenge(); } - - /// Set Partial Secret. - ComputeSecretData & setPartialSecret(Page::const_span partialSecret) { - data.setChallenge(partialSecret); - return *this; - } - - /// @} - - /// @name Page number - /// @brief Page number for Binding Data. - /// @{ - - /// Get page number. - int pageNum() const { return data.pageNum(); } - - /// Set page number. - ComputeSecretData & setPageNum(int pageNum) { - data.setPageNum(pageNum); - return *this; - } - - /// @} - - /// @name MAN ID - /// @brief Manufacturer ID of the device. - /// @{ - - /// Get mutable MAN ID. - ManId::span manId() { return data.manId(); } - - /// Get immutable MAN ID. - ManId::const_span manId() const { return data.manId(); } - - /// Set MAN ID. - ComputeSecretData & setManId(ManId::const_span manId) { - data.setManId(manId); - return *this; - } - - /// @} - -private: - PageAuthenticationData data; -}; - -/// Format encryption or decryption HMAC input data. -class DS28C36::EncryptionHmacData { -public: - typedef array_span<uint_least8_t, - EncryptionChallenge::size + RomId::size + 1 + ManId::size> - Result; - - EncryptionHmacData() : result_() {} - - /// Formatted data result. - Result::const_span result() const { return result_; } - - /// @name Encryption Challenge - /// @brief Random challenge used to prevent replay attacks. - /// @{ - - /// Get mutable Encryption Challenge. - EncryptionChallenge::span encryptionChallenge() { - return make_span(result_) - .subspan<encryptionChallengeIdx, EncryptionChallenge::size>(); - } - - /// Get immutable Encryption Challenge. - EncryptionChallenge::const_span encryptionChallenge() const { - return const_cast<EncryptionHmacData &>(*this).encryptionChallenge(); - } - - /// Set Encryption Challenge. - EncryptionHmacData & - setEncryptionChallenge(EncryptionChallenge::const_span encryptionChallenge) { - copy(encryptionChallenge, this->encryptionChallenge()); - return *this; - } - - /// @} - - /// @name ROM ID - /// @brief 1-Wire ROM ID of the device. - /// @{ - - /// Get mutable ROM ID. - RomId::span romId() { - return make_span(result_).subspan<romIdIdx, RomId::size>(); - } - - /// Get immutable ROM ID. - RomId::const_span romId() const { - return const_cast<EncryptionHmacData &>(*this).romId(); - } - - /// Set ROM ID. - EncryptionHmacData & setRomId(RomId::const_span romId) { - copy(romId, this->romId()); - return *this; - } - - /// Set ROM ID for use in anonymous mode. - MaximInterface_EXPORT EncryptionHmacData & setAnonymousRomId(); - - /// @} - - /// @name Page number - /// @brief Number of the page to use data from. - /// @{ - - /// Get page number. - int pageNum() const { return result_[pageNumIdx]; } - - /// Set page number. - EncryptionHmacData & setPageNum(int pageNum) { - result_[pageNumIdx] = pageNum; - return *this; - } - - /// @} - - /// @name MAN ID - /// @brief Manufacturer ID of the device. - /// @{ - - /// Get mutable MAN ID. - ManId::span manId() { - return make_span(result_).subspan<manIdIdx, ManId::size>(); - } - - /// Get immutable MAN ID. - ManId::const_span manId() const { - return const_cast<EncryptionHmacData &>(*this).manId(); - } - - /// Set MAN ID. - EncryptionHmacData & setManId(ManId::const_span manId) { - copy(manId, this->manId()); - return *this; - } - - /// @} - -private: - typedef Result::span::index_type index; - - static const index encryptionChallengeIdx = 0; - static const index romIdIdx = - encryptionChallengeIdx + EncryptionChallenge::size; - static const index pageNumIdx = romIdIdx + RomId::size; - static const index manIdIdx = pageNumIdx + 1; - - Result::array result_; -}; - -/// Access fields in the ROM Options page. -class DS28C36::RomOptions { -public: - explicit RomOptions(Page::span page) : page(page) {} - - bool romBlockDisable() const { - return page[romBlockDisableIdx] == enabledValue; - } - - RomOptions & setRomBlockDisable(bool romBlockDisable) { - page[romBlockDisableIdx] = (romBlockDisable ? enabledValue : 0); - return *this; - } - - bool anonymous() const { return page[anonymousIdx] == enabledValue; } - - RomOptions & setAnonymous(bool anonymous) { - page[anonymousIdx] = (anonymous ? enabledValue : 0); - return *this; - } - - ManId::const_span manId() const { - return page.subspan<22, ManId::size>(); - } - - RomId::const_span romId() const { - return page.subspan<24, RomId::size>(); - } - -private: - static const Page::span::index_type romBlockDisableIdx = 0; - static const Page::span::index_type anonymousIdx = 1; - static const Page::span::value_type enabledValue = 0xAA; - - Page::span page; -}; - -/// Access fields in the GPIO Control page. -class DS28C36::GpioControl { -public: - explicit GpioControl(Page::span page) : page(page) {} - - bool pioaConducting() const { - return page[pioaConductingIdx] == pioConductingValue; - } - - GpioControl & setPioaConducting(bool pioaConducting) { - page[pioaConductingIdx] = (pioaConducting ? pioConductingValue : 0x55); - return *this; - } - - bool piobConducting() const { - return page[piobConductingIdx] == pioConductingValue; - } - - GpioControl & setPiobConducting(bool piobConducting) { - page[piobConductingIdx] = (piobConducting ? pioConductingValue : 0x55); - return *this; - } - - bool pioaLevel() const { return page[2] == pioLevelValue; } - - bool piobLevel() const { return page[3] == pioLevelValue; } - -private: - static const Page::span::index_type pioaConductingIdx = 0; - static const Page::span::index_type piobConductingIdx = 1; - static const Page::span::value_type pioConductingValue = 0xAA; - static const Page::span::value_type pioLevelValue = 0x55; - - Page::span page; -}; - -} // namespace MaximInterface - -#endif
--- a/Devices/DS28E15_22_25.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,653 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include <algorithm> -#include <MaximInterface/Utilities/crc.hpp> -#include <MaximInterface/Utilities/Error.hpp> -#include "DS28E15_22_25.hpp" - -namespace MaximInterface { - -using namespace Sha256; -using std::copy; - -static const int shaComputationDelayMs = 3; -static const int eepromWriteDelayMs = 10; -static inline int secretEepromWriteDelayMs(bool lowPower) { - return lowPower ? 200 : 100; -} - -static const int ds28e22_25_pagesPerBlock = 2; - -static error_code -writeDataWithCrc(OneWireMaster & master, span<const uint_least8_t> data, - OneWireMaster::Level level = OneWireMaster::NormalLevel, - uint_fast16_t crcStart = 0) { - error_code result = master.writeBlock(data); - if (result) { - return result; - } - uint_least8_t response[2]; - result = master.readByte(response[0]); - if (result) { - return result; - } - result = master.readByteSetLevel(response[1], level); - if (result) { - return result; - } - if (calculateCrc16(response, calculateCrc16(data, crcStart)) != 0xB001) { - result = make_error_code(DS28E15_22_25::CrcError); - } - return result; -} - -const int DS28E15_22_25::segmentsPerPage; - -DS28E15_22_25::AuthenticationData & -DS28E15_22_25::AuthenticationData::setAnonymousRomId() { - std::fill(romId().begin(), romId().end(), 0xFF); - return *this; -} - -error_code -DS28E15_22_25::writeCommandWithCrc(Command command, uint_least8_t parameter, - OneWireMaster::Level level) const { - error_code result = selectRom(*master); - if (!result) { - const uint_least8_t data[] = {static_cast<uint_least8_t>(command), - parameter}; - result = writeDataWithCrc(*master, data); - } - return result; -} - -static error_code readDataWithCrc(OneWireMaster & master, - span<uint_least8_t> data) { - error_code result = master.readBlock(data); - if (result) { - return result; - } - uint_least8_t response[2]; - result = master.readBlock(response); - if (result) { - return result; - } - if (calculateCrc16(response, calculateCrc16(data)) != 0xB001) { - result = make_error_code(DS28E15_22_25::CrcError); - } - return result; -} - -static error_code readCsByte(OneWireMaster & master) { - uint_least8_t response; - error_code result = master.readByte(response); - if (result) { - return result; - } - if (response != 0xAA) { - result = make_error_code(DS28E15_22_25::OperationFailure); - } - return result; -} - -static error_code releaseSequence(OneWireMaster & master, Sleep & sleep, - int delayTimeMs) { - error_code result = master.writeBytePower(0xAA); - if (result) { - return result; - } - sleep(delayTimeMs); - result = master.setLevel(OneWireMaster::NormalLevel); - if (result) { - return result; - } - return readCsByte(master); -} - -DS28E15_22_25::BlockProtection & -DS28E15_22_25::BlockProtection::setBlockNum(int blockNum) { - status &= ~blockNumMask; - status |= (blockNum & blockNumMask); - return *this; -} - -bool DS28E15_22_25::BlockProtection::noProtection() const { - return !readProtection() && !writeProtection() && !eepromEmulation() && - !authProtection(); -} - -DS28E15_22_25::BlockProtection & -DS28E15_22_25::BlockProtection::setReadProtection(bool readProtection) { - if (readProtection) { - status |= readProtectionMask; - } else { - status &= ~readProtectionMask; - } - return *this; -} - -DS28E15_22_25::BlockProtection & -DS28E15_22_25::BlockProtection::setWriteProtection(bool writeProtection) { - if (writeProtection) { - status |= writeProtectionMask; - } else { - status &= ~writeProtectionMask; - } - return *this; -} - -DS28E15_22_25::BlockProtection & -DS28E15_22_25::BlockProtection::setEepromEmulation(bool eepromEmulation) { - if (eepromEmulation) { - status |= eepromEmulationMask; - } else { - status &= ~eepromEmulationMask; - } - return *this; -} - -DS28E15_22_25::BlockProtection & -DS28E15_22_25::BlockProtection::setAuthProtection(bool authProtection) { - if (authProtection) { - status |= authProtectionMask; - } else { - status &= ~authProtectionMask; - } - return *this; -} - -DS28E15_22_25::ProtectionWriteMacData::ProtectionWriteMacData() - : result_(), oldProtection_(), newProtection_() { - setOldProtection(oldProtection_); - setNewProtection(newProtection_); -} - -DS28E15_22_25::ProtectionWriteMacData & -DS28E15_22_25::ProtectionWriteMacData::setOldProtection( - BlockProtection oldProtection) { - result_[oldProtectionIdx] = oldProtection.authProtection() ? 1 : 0; - result_[oldProtectionIdx + 1] = oldProtection.eepromEmulation() ? 1 : 0; - result_[oldProtectionIdx + 2] = oldProtection.writeProtection() ? 1 : 0; - result_[oldProtectionIdx + 3] = oldProtection.readProtection() ? 1 : 0; - oldProtection_ = oldProtection; - return *this; -} - -DS28E15_22_25::ProtectionWriteMacData & -DS28E15_22_25::ProtectionWriteMacData::setNewProtection( - BlockProtection newProtection) { - result_[blockNumIdx] = newProtection.blockNum(); - result_[newProtectionIdx] = newProtection.authProtection() ? 1 : 0; - result_[newProtectionIdx + 1] = newProtection.eepromEmulation() ? 1 : 0; - result_[newProtectionIdx + 2] = newProtection.writeProtection() ? 1 : 0; - result_[newProtectionIdx + 3] = newProtection.readProtection() ? 1 : 0; - newProtection_ = newProtection; - return *this; -} - -error_code -DS28E15_22_25::writeAuthBlockProtection(BlockProtection newProtection, - Hash::const_span mac) { - error_code result = - writeCommandWithCrc(AuthWriteBlockProtection, newProtection.statusByte(), - OneWireMaster::StrongLevel); - if (result) { - return result; - } - - sleep->invoke(shaComputationDelayMs); - result = master->setLevel(OneWireMaster::NormalLevel); - if (result) { - return result; - } - - result = writeDataWithCrc(*master, mac); - if (result) { - return result; - } - - result = readCsByte(*master); - if (result) { - return result; - } - - result = releaseSequence(*master, *sleep, eepromWriteDelayMs); - return result; -} - -error_code DS28E15_22_25::writeBlockProtection(BlockProtection protection) { - error_code result = - writeCommandWithCrc(WriteBlockProtection, protection.statusByte()); - if (result) { - return result; - } - - result = releaseSequence(*master, *sleep, eepromWriteDelayMs); - return result; -} - -error_code DS28E15_22_25::doReadBlockProtection(int blockNum, - BlockProtection & protection, - Variant variant) const { - uint_least8_t buffer = blockNum; - if (variant == DS28E22 || variant == DS28E25) { - buffer *= ds28e22_25_pagesPerBlock; - } - error_code result = writeCommandWithCrc(ReadStatus, buffer); - if (!result) { - result = master->readByte(buffer); - if (!result) { - protection.setStatusByte(buffer); - } - } - return result; -} - -error_code DS28E15_22_25::computeReadPageMac(int page_num, bool anon, - Hash::span mac) const { - error_code result = - writeCommandWithCrc(ComputePageMac, (anon ? 0xE0 : 0x00) | page_num, - OneWireMaster::StrongLevel); - if (result) { - return result; - } - - sleep->invoke(shaComputationDelayMs * 2); - result = master->setLevel(OneWireMaster::NormalLevel); - if (result) { - return result; - } - - result = readCsByte(*master); - if (result) { - return result; - } - - result = readDataWithCrc(*master, mac); - return result; -} - -error_code DS28E15_22_25::doComputeSecret(int page_num, bool lock, - bool lowPower) { - error_code result = writeCommandWithCrc(ComputeAndLockSecret, - lock ? (0xE0 | page_num) : page_num); - if (result) { - return result; - } - - result = releaseSequence(*master, *sleep, - shaComputationDelayMs * 2 + - secretEepromWriteDelayMs(lowPower)); - return result; -} - -error_code DS28E15_22_25::doWriteScratchpad(Scratchpad::const_span data, - Variant variant) { - const uint_least8_t parameter = - (variant == DS28E22 || variant == DS28E25) ? 0x20 : 0x00; - error_code result = writeCommandWithCrc(ReadWriteScratchpad, parameter); - if (result) { - return result; - } - - result = writeDataWithCrc(*master, data); - return result; -} - -error_code DS28E15_22_25::doReadScratchpad(Scratchpad::span data, - Variant variant) const { - const uint_least8_t parameter = - (variant == DS28E22 || variant == DS28E25) ? 0x2F : 0x0F; - error_code result = writeCommandWithCrc(ReadWriteScratchpad, parameter); - if (result) { - return result; - } - - result = readDataWithCrc(*master, data); - return result; -} - -error_code DS28E15_22_25::doLoadSecret(bool lock, bool lowPower) { - error_code result = - writeCommandWithCrc(LoadAndLockSecret, lock ? 0xE0 : 0x00); - if (result) { - return result; - } - - result = releaseSequence(*master, *sleep, secretEepromWriteDelayMs(lowPower)); - return result; -} - -error_code DS28E15_22_25::readPage(int page, Page::span rdbuf) const { - error_code result = writeCommandWithCrc(ReadMemory, page); - if (result) { - return result; - } - - result = continueReadPage(rdbuf); - return result; -} - -error_code DS28E15_22_25::continueReadPage(Page::span rdbuf) const { - return readDataWithCrc(*master, rdbuf); -} - -error_code DS28E15_22_25::doWriteAuthSegment(Segment::const_span newData, - Hash::const_span mac, - Variant variant, bool continuing) { - // CRC gets calculated with CS byte when continuing on DS28E22 and DS28E25. - const uint_fast16_t crcStart = - ((variant == DS28E22 || variant == DS28E25) && continuing) - ? calculateCrc16(0xAA) - : 0; - error_code result = - writeDataWithCrc(*master, newData, OneWireMaster::StrongLevel, crcStart); - if (result) { - return result; - } - - sleep->invoke(shaComputationDelayMs); - result = master->setLevel(OneWireMaster::NormalLevel); - if (result) { - return result; - } - - result = writeDataWithCrc(*master, mac); - if (result) { - return result; - } - - result = readCsByte(*master); - if (result) { - return result; - } - - result = releaseSequence(*master, *sleep, eepromWriteDelayMs); - return result; -} - -error_code DS28E15_22_25::doWriteAuthSegment(int pageNum, int segmentNum, - Segment::const_span newData, - Hash::const_span mac, - Variant variant) { - error_code result = - writeCommandWithCrc(AuthWriteMemory, (segmentNum << 5) | pageNum); - if (result) { - return result; - } - - result = doWriteAuthSegment(newData, mac, variant, false); - return result; -} - -error_code DS28E15_22_25::doContinueWriteAuthSegment( - Segment::const_span newData, Hash::const_span mac, Variant variant) { - return doWriteAuthSegment(newData, mac, variant, true); -} - -error_code DS28E15_22_25::readSegment(int page, int segment, - Segment::span data) const { - error_code result = writeCommandWithCrc(ReadMemory, (segment << 5) | page); - if (result) { - return result; - } - - result = continueReadSegment(data); - return result; -} - -error_code DS28E15_22_25::continueReadSegment(Segment::span data) const { - return master->readBlock(data); -} - -error_code DS28E15_22_25::writeSegment(int page, int block, - Segment::const_span data) { - error_code result = writeCommandWithCrc(WriteMemory, (block << 5) | page); - if (result) { - return result; - } - - result = continueWriteSegment(data); - return result; -} - -error_code DS28E15_22_25::continueWriteSegment(Segment::const_span data) { - error_code result = writeDataWithCrc(*master, data); - if (result) { - return result; - } - - result = releaseSequence(*master, *sleep, eepromWriteDelayMs); - return result; -} - -error_code -DS28E15_22_25::doReadAllBlockProtection(span<BlockProtection> protection, - Variant variant) const { - error_code result = writeCommandWithCrc(ReadStatus, 0); - if (!result) { - if (variant == DS28E22 || variant == DS28E25) { - // Need to read extra data on DS28E22 to get CRC16. - uint_least8_t buf[DS28E25::memoryPages]; - result = readDataWithCrc(*master, buf); - if (!result) { - const int blocks = ((variant == DS28E22) ? DS28E22::memoryPages - : DS28E25::memoryPages) / - ds28e22_25_pagesPerBlock; - for (span<BlockProtection>::index_type i = 0; - i < std::min<span<BlockProtection>::index_type>(protection.size(), - blocks); - ++i) { - protection[i].setStatusByte( - (buf[i * ds28e22_25_pagesPerBlock] & 0xF0) | // Upper nibble - ((buf[i * ds28e22_25_pagesPerBlock] & 0x0F) / - ds28e22_25_pagesPerBlock)); // Lower nibble - } - } - } else { // DS28E15 - uint_least8_t buf[DS28E15::protectionBlocks]; - result = readDataWithCrc(*master, buf); - if (!result) { - for (span<BlockProtection>::index_type i = 0; - i < std::min<span<BlockProtection>::index_type>( - protection.size(), DS28E15::protectionBlocks); - ++i) { - protection[i].setStatusByte(buf[i]); - } - } - } - } - return result; -} - -const error_category & DS28E15_22_25::errorCategory() { - static class : public error_category { - public: - virtual const char * name() const { return "DS28E15_22_25"; } - - virtual std::string message(int condition) const { - switch (condition) { - case CrcError: - return "CRC Error"; - - case OperationFailure: - return "Operation Failure"; - - default: - return defaultErrorMessage(condition); - } - } - } instance; - return instance; -} - -error_code DS28E15_22_25::loadSecret(bool lock) { - // Use worst-case low power timing if the device type is not known. - return doLoadSecret(lock, true); -} - -error_code DS28E15_22_25::computeSecret(int pageNum, bool lock) { - // Use worst-case low power timing if the device type is not known. - return doComputeSecret(pageNum, lock, true); -} - -error_code DS28E15_22_25::readPersonality(Personality & personality) const { - error_code result = writeCommandWithCrc(ReadStatus, 0xE0); - if (!result) { - uint_least8_t data[4]; - result = readDataWithCrc(*master, data); - if (!result) { - personality.PB1 = data[0]; - personality.PB2 = data[1]; - personality.manId[0] = data[2]; - personality.manId[1] = data[3]; - } - } - return result; -} - -const int DS28EL15::memoryPages; -const int DS28EL15::protectionBlocks; - -error_code DS28EL15::writeScratchpad(Scratchpad::const_span data) { - return doWriteScratchpad(data, DS28E15); -} - -error_code DS28EL15::readScratchpad(Scratchpad::span data) const { - return doReadScratchpad(data, DS28E15); -} - -error_code DS28EL15::readBlockProtection(int blockNum, - BlockProtection & protection) const { - return doReadBlockProtection(blockNum, protection, DS28E15); -} - -error_code DS28EL15::writeAuthSegment(int pageNum, int segmentNum, - Segment::const_span newData, - Hash::const_span mac) { - return doWriteAuthSegment(pageNum, segmentNum, newData, mac, DS28E15); -} - -error_code DS28EL15::continueWriteAuthSegment(Segment::const_span newData, - Hash::const_span mac) { - return doContinueWriteAuthSegment(newData, mac, DS28E15); -} - -error_code DS28EL15::readAllBlockProtection( - span<BlockProtection, protectionBlocks> protection) const { - return doReadAllBlockProtection(protection, DS28E15); -} - -error_code DS28E15::loadSecret(bool lock) { return doLoadSecret(lock, false); } - -error_code DS28E15::computeSecret(int pageNum, bool lock) { - return doComputeSecret(pageNum, lock, false); -} - -const int DS28EL22::memoryPages; -const int DS28EL22::protectionBlocks; - -error_code DS28EL22::writeScratchpad(Scratchpad::const_span data) { - return doWriteScratchpad(data, DS28E22); -} - -error_code DS28EL22::readScratchpad(Scratchpad::span data) const { - return doReadScratchpad(data, DS28E22); -} - -error_code DS28EL22::readBlockProtection(int blockNum, - BlockProtection & protection) const { - return doReadBlockProtection(blockNum, protection, DS28E22); -} - -error_code DS28EL22::writeAuthSegment(int pageNum, int segmentNum, - Segment::const_span newData, - Hash::const_span mac) { - return doWriteAuthSegment(pageNum, segmentNum, newData, mac, DS28E22); -} - -error_code DS28EL22::continueWriteAuthSegment(Segment::const_span newData, - Hash::const_span mac) { - return doContinueWriteAuthSegment(newData, mac, DS28E22); -} - -error_code DS28EL22::readAllBlockProtection( - span<BlockProtection, protectionBlocks> protection) const { - return doReadAllBlockProtection(protection, DS28E22); -} - -error_code DS28E22::loadSecret(bool lock) { return doLoadSecret(lock, false); } - -error_code DS28E22::computeSecret(int pageNum, bool lock) { - return doComputeSecret(pageNum, lock, false); -} - -const int DS28EL25::memoryPages; -const int DS28EL25::protectionBlocks; - -error_code DS28EL25::writeScratchpad(Scratchpad::const_span data) { - return doWriteScratchpad(data, DS28E25); -} - -error_code DS28EL25::readScratchpad(Scratchpad::span data) const { - return doReadScratchpad(data, DS28E25); -} - -error_code DS28EL25::readBlockProtection(int blockNum, - BlockProtection & protection) const { - return doReadBlockProtection(blockNum, protection, DS28E25); -} - -error_code DS28EL25::writeAuthSegment(int pageNum, int segmentNum, - Segment::const_span newData, - Hash::const_span mac) { - return doWriteAuthSegment(pageNum, segmentNum, newData, mac, DS28E25); -} - -error_code DS28EL25::continueWriteAuthSegment(Segment::const_span newData, - Hash::const_span mac) { - return doContinueWriteAuthSegment(newData, mac, DS28E25); -} - -error_code DS28EL25::readAllBlockProtection( - span<BlockProtection, protectionBlocks> protection) const { - return doReadAllBlockProtection(protection, DS28E25); -} - -error_code DS28E25::loadSecret(bool lock) { return doLoadSecret(lock, false); } - -error_code DS28E25::computeSecret(int pageNum, bool lock) { - return doComputeSecret(pageNum, lock, false); -} - -} // namespace MaximInterface
--- a/Devices/DS28E15_22_25.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,885 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_DS28E15_22_25 -#define MaximInterface_DS28E15_22_25 - -#include <stdint.h> -#include <MaximInterface/Links/OneWireMaster.hpp> -#include <MaximInterface/Links/SelectRom.hpp> -#include <MaximInterface/Links/Sleep.hpp> -#include <MaximInterface/Utilities/array_span.hpp> -#include <MaximInterface/Utilities/Export.h> -#include <MaximInterface/Utilities/ManId.hpp> -#include <MaximInterface/Utilities/Sha256.hpp> - -namespace MaximInterface { - -/// @brief -/// Interface to the DS28E15/22/25 series of authenticators -/// including low power variants. -class DS28E15_22_25 { -public: - enum ErrorValue { CrcError = 1, OperationFailure }; - - /// Holds the contents of a device memory segment. - typedef array_span<uint_least8_t, 4> Segment; - - /// Holds the contents of a device memory page. - typedef array_span<uint_least8_t, 32> Page; - - /// Number of segments per page. - static const int segmentsPerPage = Page::size / Segment::size; - - /// Holds the contents of the device scratchpad. - typedef array_span<uint_least8_t, 32> Scratchpad; - - /// Container for the device personality. - struct Personality { - uint_least8_t PB1; - uint_least8_t PB2; - ManId::array manId; - - bool secretLocked() const { return PB2 & 0x01; } - }; - - // Represents the status of a memory protection block. - class BlockProtection; - - // Format data to hash for an Authenticated Write to a memory segment. - class SegmentWriteMacData; - - // Format data to hash for an Authenticated Write to a memory protection block. - class ProtectionWriteMacData; - - // Format data to hash for device authentication or computing the next secret - // from the existing secret. - class AuthenticationData; - - void setSleep(Sleep & sleep) { this->sleep = &sleep; } - - void setMaster(OneWireMaster & master) { this->master = &master; } - - void setSelectRom(const SelectRom & selectRom) { - this->selectRom = selectRom; - } - - // Const member functions should not affect the state of the memory, - // block protection, or secret on the device. - - /// @brief Read memory segment using the Read Memory command on the device. - /// @param pageNum Page number for read operation. - /// @param segmentNum Segment number within page for read operation. - /// @param[out] data Buffer to read data from the segment into. - MaximInterface_EXPORT error_code readSegment(int pageNum, int segmentNum, - Segment::span data) const; - - /// @brief Continue an in-progress readSegment operation. - /// @note A CRC16 will encountered after reading the last segment of a page. - /// @param[out] data Buffer to read data from the segment into. - MaximInterface_EXPORT error_code - continueReadSegment(Segment::span data) const; - - /// @brief Write memory segment using the Write Memory command. - /// @note 1-Wire ROM selection should have already occurred. - /// @param pageNum Page number for write operation. - /// @param segmentNum Segment number within page for write operation. - /// @param[in] data Data to write to the memory segment. - MaximInterface_EXPORT error_code writeSegment(int pageNum, int segmentNum, - Segment::const_span data); - - /// @brief Continue an in-progress Write Memory command. - /// @param[in] data Data to write to the memory segment. - MaximInterface_EXPORT error_code - continueWriteSegment(Segment::const_span data); - - /// @brief Read memory page using the Read Memory command on the device. - /// @param pageNum Page number for write operation. - /// @param[out] rdbuf Buffer to read data from the page into. - MaximInterface_EXPORT error_code readPage(int pageNum, - Page::span rdbuf) const; - - /// @brief Continue an in-progress readPageOperation. - /// @param[out] rdbuf Buffer to read data from the page into. - MaximInterface_EXPORT error_code continueReadPage(Page::span rdbuf) const; - - /// @brief - /// Perform a Compute Page MAC command on the device. - /// Read back the MAC and verify the CRC16. - /// @param pageNum Page number to use for the computation. - /// @param anon True to compute in anonymous mode where ROM ID is not used. - /// @param[out] mac The device computed MAC. - MaximInterface_EXPORT error_code - computeReadPageMac(int pageNum, bool anon, Sha256::Hash::span mac) const; - - /// @brief - /// Update the status of a memory protection block using the - /// Write Page Protection command. - /// @param protection - /// Desired protection status for the block. - /// It is not possible to disable existing protections. - MaximInterface_EXPORT error_code - writeBlockProtection(BlockProtection protection); - - /// @brief - /// Update the status of a memory protection block using the - /// Authenticated Write Page Protection command. - /// @param newProtection New protection status to write. - /// @param[in] mac Write MAC computed for this operation. - MaximInterface_EXPORT error_code writeAuthBlockProtection( - BlockProtection newProtection, Sha256::Hash::const_span mac); - - /// @brief Perform Load and Lock Secret command on the device. - /// @note The secret should already be stored in the scratchpad on the device. - /// @param lock - /// Prevent further changes to the secret on the device after loading. - MaximInterface_EXPORT error_code loadSecret(bool lock); - - /// @brief Perform a Compute and Lock Secret command on the device. - /// @param pageNum Page number to use as the binding data. - /// @param lock - /// Prevent further changes to the secret on the device after computing. - MaximInterface_EXPORT error_code computeSecret(int pageNum, bool lock); - - /// @brief Read the personality bytes using the Read Status command. - /// @param[out] personality Receives personality read from device. - MaximInterface_EXPORT error_code - readPersonality(Personality & personality) const; - - MaximInterface_EXPORT static const error_category & errorCategory(); - -protected: - enum Variant { DS28E15, DS28E22, DS28E25 }; - - DS28E15_22_25(Sleep & sleep, OneWireMaster & master, - const SelectRom & selectRom) - : selectRom(selectRom), master(&master), sleep(&sleep) {} - - ~DS28E15_22_25() {} - - error_code doWriteScratchpad(Scratchpad::const_span data, Variant variant); - - error_code doReadScratchpad(Scratchpad::span data, Variant variant) const; - - error_code doReadBlockProtection(int blockNum, BlockProtection & protection, - Variant variant) const; - - error_code doWriteAuthSegment(int pageNum, int segmentNum, - Segment::const_span newData, - Sha256::Hash::const_span mac, Variant variant); - - error_code doContinueWriteAuthSegment(Segment::const_span newData, - Sha256::Hash::const_span mac, - Variant variant); - - error_code doReadAllBlockProtection(span<BlockProtection> protection, - Variant variant) const; - - error_code doLoadSecret(bool lock, bool lowPower); - - error_code doComputeSecret(int pageNum, bool lock, bool lowPower); - -private: - enum Command { - WriteMemory = 0x55, - ReadMemory = 0xF0, - LoadAndLockSecret = 0x33, - ComputeAndLockSecret = 0x3C, - ReadWriteScratchpad = 0x0F, - ComputePageMac = 0xA5, - ReadStatus = 0xAA, - WriteBlockProtection = 0xC3, - AuthWriteMemory = 0x5A, - AuthWriteBlockProtection = 0xCC, - }; - - error_code doWriteAuthSegment(Segment::const_span newData, - Sha256::Hash::const_span mac, Variant variant, - bool continuing); - - error_code writeCommandWithCrc( - Command command, uint_least8_t parameter, - OneWireMaster::Level level = OneWireMaster::NormalLevel) const; - - SelectRom selectRom; - OneWireMaster * master; - Sleep * sleep; -}; - -inline error_code make_error_code(DS28E15_22_25::ErrorValue e) { - return error_code(e, DS28E15_22_25::errorCategory()); -} - -/// Interface to the DS28EL15 (low power) authenticator. -class DS28EL15 : public DS28E15_22_25 { -public: - // DS28E15_22_25 traits - static const int memoryPages = 2; - static const int protectionBlocks = 4; - - DS28EL15(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom) - : DS28E15_22_25(sleep, master, selectRom) {} - - /// @brief Perform Write Scratchpad operation on the device. - /// @param[in] data Data to write to the scratchpad. - MaximInterface_EXPORT error_code writeScratchpad(Scratchpad::const_span data); - - /// @brief Perform a Read Scratchpad operation on the device. - /// @param[out] data Buffer to read data from the scratchpad into. - MaximInterface_EXPORT error_code readScratchpad(Scratchpad::span data) const; - - /// @brief - /// Read the status of a memory protection block using the Read Status command. - /// @param blockNum Block number to to read status of. - /// @param[out] protection Receives protection status read from device. - MaximInterface_EXPORT error_code - readBlockProtection(int blockNum, BlockProtection & protection) const; - - /// @brief Write memory segment using the Authenticated Write Memory command. - /// @param pageNum Page number for write operation. - /// @param segmentNum Segment number within page for write operation. - /// @param[in] newData New data to write to the segment. - /// @param[in] mac Write MAC computed for this operation. - MaximInterface_EXPORT error_code - writeAuthSegment(int pageNum, int segmentNum, Segment::const_span newData, - Sha256::Hash::const_span mac); - - /// @brief Continue an in-progress Authenticated Write Memory command. - /// @param[in] newData New data to write to the segment. - /// @param[in] mac Write MAC computed for this operation. - MaximInterface_EXPORT error_code continueWriteAuthSegment( - Segment::const_span newData, Sha256::Hash::const_span mac); - - /// @brief - /// Read the status of all memory protection blocks using the Read Status command. - /// @param[out] protection Receives protection statuses read from device. - MaximInterface_EXPORT error_code readAllBlockProtection( - span<BlockProtection, protectionBlocks> protection) const; -}; - -/// Interface to the DS28E15 authenticator. -class DS28E15 : public DS28EL15 { -public: - DS28E15(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom) - : DS28EL15(sleep, master, selectRom) {} - - /// @brief Perform Load and Lock Secret command on the device. - /// @note The secret should already be stored in the scratchpad on the device. - /// @param lock - /// Prevent further changes to the secret on the device after loading. - MaximInterface_EXPORT error_code loadSecret(bool lock); - - /// @brief Perform a Compute and Lock Secret command on the device. - /// @param pageNum Page number to use as the binding data. - /// @param lock - /// Prevent further changes to the secret on the device after computing. - MaximInterface_EXPORT error_code computeSecret(int pageNum, bool lock); -}; - -/// Interface to the DS28EL22 (low power) authenticator. -class DS28EL22 : public DS28E15_22_25 { -public: - // DS28E15_22_25 traits - static const int memoryPages = 8; - static const int protectionBlocks = 4; - - DS28EL22(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom) - : DS28E15_22_25(sleep, master, selectRom) {} - - /// @brief Perform Write Scratchpad operation on the device. - /// @param[in] data Data to write to the scratchpad. - MaximInterface_EXPORT error_code writeScratchpad(Scratchpad::const_span data); - - /// @brief Perform a Read Scratchpad operation on the device. - /// @param[out] data Buffer to read data from the scratchpad into. - MaximInterface_EXPORT error_code readScratchpad(Scratchpad::span data) const; - - /// @brief - /// Read the status of a memory protection block using the Read Status command. - /// @param blockNum Block number to to read status of. - /// @param[out] protection Receives protection status read from device. - MaximInterface_EXPORT error_code - readBlockProtection(int blockNum, BlockProtection & protection) const; - - /// @brief Write memory segment using the Authenticated Write Memory command. - /// @param pageNum Page number for write operation. - /// @param segmentNum Segment number within page for write operation. - /// @param[in] newData New data to write to the segment. - /// @param[in] mac Write MAC computed for this operation. - MaximInterface_EXPORT error_code - writeAuthSegment(int pageNum, int segmentNum, Segment::const_span newData, - Sha256::Hash::const_span mac); - - /// @brief Continue an in-progress Authenticated Write Memory command. - /// @param[in] newData New data to write to the segment. - /// @param[in] mac Write MAC computed for this operation. - MaximInterface_EXPORT error_code continueWriteAuthSegment( - Segment::const_span newData, Sha256::Hash::const_span mac); - - /// @brief - /// Read the status of all memory protection blocks using the Read Status command. - /// @param[out] protection Receives protection statuses read from device. - MaximInterface_EXPORT error_code readAllBlockProtection( - span<BlockProtection, protectionBlocks> protection) const; -}; - -/// Interface to the DS28E22 authenticator. -class DS28E22 : public DS28EL22 { -public: - DS28E22(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom) - : DS28EL22(sleep, master, selectRom) {} - - /// @brief Perform Load and Lock Secret command on the device. - /// @note The secret should already be stored in the scratchpad on the device. - /// @param lock - /// Prevent further changes to the secret on the device after loading. - MaximInterface_EXPORT error_code loadSecret(bool lock); - - /// @brief Perform a Compute and Lock Secret command on the device. - /// @param pageNum Page number to use as the binding data. - /// @param lock - /// Prevent further changes to the secret on the device after computing. - MaximInterface_EXPORT error_code computeSecret(int pageNum, bool lock); -}; - -/// Interface to the DS28EL25 (low power) authenticator. -class DS28EL25 : public DS28E15_22_25 { -public: - // DS28E15_22_25 traits - static const int memoryPages = 16; - static const int protectionBlocks = 8; - - DS28EL25(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom) - : DS28E15_22_25(sleep, master, selectRom) {} - - /// @brief Perform Write Scratchpad operation on the device. - /// @param[in] data Data to write to the scratchpad. - MaximInterface_EXPORT error_code writeScratchpad(Scratchpad::const_span data); - - /// @brief Perform a Read Scratchpad operation on the device. - /// @param[out] data Buffer to read data from the scratchpad into. - MaximInterface_EXPORT error_code readScratchpad(Scratchpad::span data) const; - - /// @brief - /// Read the status of a memory protection block using the Read Status command. - /// @param blockNum Block number to to read status of. - /// @param[out] protection Receives protection status read from device. - MaximInterface_EXPORT error_code - readBlockProtection(int blockNum, BlockProtection & protection) const; - - /// Write memory segment using the Authenticated Write Memory command. - /// @param pageNum Page number for write operation. - /// @param segmentNum Segment number within page for write operation. - /// @param[in] newData New data to write to the segment. - /// @param[in] mac Write MAC computed for this operation. - MaximInterface_EXPORT error_code - writeAuthSegment(int pageNum, int segmentNum, Segment::const_span newData, - Sha256::Hash::const_span mac); - - /// @brief Continue an in-progress Authenticated Write Memory command. - /// @param[in] newData New data to write to the segment. - /// @param[in] mac Write MAC computed for this operation. - MaximInterface_EXPORT error_code continueWriteAuthSegment( - Segment::const_span newData, Sha256::Hash::const_span mac); - - /// @brief - /// Read the status of all memory protection blocks using the Read Status command. - /// @param[out] protection Receives protection statuses read from device. - MaximInterface_EXPORT error_code readAllBlockProtection( - span<BlockProtection, protectionBlocks> protection) const; -}; - -/// Interface to the DS28E25 authenticator. -class DS28E25 : public DS28EL25 { -public: - DS28E25(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom) - : DS28EL25(sleep, master, selectRom) {} - - /// @brief Perform Load and Lock Secret command on the device. - /// @note The secret should already be stored in the scratchpad on the device. - /// @param lock Prevent further changes to the secret on the device after loading. - MaximInterface_EXPORT error_code loadSecret(bool lock); - - /// @brief Perform a Compute and Lock Secret command on the device. - /// @param pageNum Page number to use as the binding data. - /// @param lock - /// Prevent further changes to the secret on the device after computing. - MaximInterface_EXPORT error_code computeSecret(int pageNum, bool lock); -}; - -/// Represents the status of a memory protection block. -class DS28E15_22_25::BlockProtection { -public: - explicit BlockProtection(uint_least8_t status = 0x00) : status(status) {} - - /// Get the byte representation used by the device. - uint_least8_t statusByte() const { return status; } - - /// Set the byte representation used by the device. - BlockProtection & setStatusByte(uint_least8_t status) { - this->status = status; - return *this; - } - - /// Get the Block Number which is indexed from zero. - int blockNum() const { return (status & blockNumMask); } - - /// Set the Block Number which is indexed from zero. - MaximInterface_EXPORT BlockProtection & setBlockNum(int blockNum); - - /// @brief Get the Read Protection status. - /// @returns True if Read Protection is enabled. - bool readProtection() const { - return ((status & readProtectionMask) == readProtectionMask); - } - - /// Set the Read Protection status. - MaximInterface_EXPORT BlockProtection & - setReadProtection(bool readProtection); - - /// @brief Get the Write Protection status. - /// @returns True if Write Protection is enabled. - bool writeProtection() const { - return ((status & writeProtectionMask) == writeProtectionMask); - } - - /// Set the Write Protection status. - MaximInterface_EXPORT BlockProtection & - setWriteProtection(bool writeProtection); - - /// @brief Get the EEPROM Emulation Mode status. - /// @returns True if EEPROM Emulation Mode is enabled. - bool eepromEmulation() const { - return ((status & eepromEmulationMask) == eepromEmulationMask); - } - - /// Set the EEPROM Emulation Mode status. - MaximInterface_EXPORT BlockProtection & - setEepromEmulation(bool eepromEmulation); - - /// @brief Get the Authentication Protection status. - /// @returns True if Authentication Protection is enabled. - bool authProtection() const { - return ((status & authProtectionMask) == authProtectionMask); - } - - /// Set the Authentication Protection status. - MaximInterface_EXPORT BlockProtection & - setAuthProtection(bool authProtection); - - /// @brief Check if no protection options are enabled. - /// @returns True if no protection options are enabled. - MaximInterface_EXPORT bool noProtection() const; - -private: - static const unsigned int readProtectionMask = 0x80, - writeProtectionMask = 0x40, - eepromEmulationMask = 0x20, - authProtectionMask = 0x10, - blockNumMask = 0x0F; - uint_least8_t status; -}; - -inline bool operator==(DS28E15_22_25::BlockProtection lhs, - DS28E15_22_25::BlockProtection rhs) { - return lhs.statusByte() == rhs.statusByte(); -} - -inline bool operator!=(DS28E15_22_25::BlockProtection lhs, - DS28E15_22_25::BlockProtection rhs) { - return !operator==(lhs, rhs); -} - -/// Format data to hash for an Authenticated Write to a memory segment. -class DS28E15_22_25::SegmentWriteMacData { -public: - SegmentWriteMacData() : result_() {} - - /// Formatted data result. - Sha256::WriteMacData::const_span result() const { return result_; } - - /// @name ROM ID - /// @brief 1-Wire ROM ID of the device. - /// @{ - - /// Get mutable ROM ID. - RomId::span romId() { - return make_span(result_).subspan<romIdIdx, RomId::size>(); - } - - /// Get immutable ROM ID. - RomId::const_span romId() const { - return const_cast<SegmentWriteMacData &>(*this).romId(); - } - - /// Set ROM ID. - SegmentWriteMacData & setRomId(RomId::const_span romId) { - copy(romId, this->romId()); - return *this; - } - - /// @} - - /// @name MAN ID - /// @brief Manufacturer ID of the device. - /// @{ - - /// Get mutable MAN ID. - ManId::span manId() { - return make_span(result_).subspan<manIdIdx, ManId::size>(); - } - - /// Get immutable MAN ID. - ManId::const_span manId() const { - return const_cast<SegmentWriteMacData &>(*this).manId(); - } - - /// Set MAN ID. - SegmentWriteMacData & setManId(ManId::const_span manId) { - copy(manId, this->manId()); - return *this; - } - - /// @} - - /// @name Page number - /// @brief Page number for write operation. - /// @{ - - /// Get page number. - int pageNum() const { return result_[pageNumIdx]; } - - /// Set page number. - SegmentWriteMacData & setPageNum(int pageNum) { - result_[pageNumIdx] = pageNum; - return *this; - } - - /// @} - - /// @name Segment number - /// @brief Segment number within page for write operation. - /// @{ - - /// Get segment number. - int segmentNum() const { return result_[segmentNumIdx]; } - - /// Set segment number. - SegmentWriteMacData & setSegmentNum(int segmentNum) { - result_[segmentNumIdx] = segmentNum; - return *this; - } - - /// @} - - /// @name Old data - /// @brief Existing data contained in the segment. - /// @{ - - /// Get mutable old data. - Segment::span oldData() { - return make_span(result_).subspan<oldDataIdx, Segment::size>(); - } - - /// Get immutable old data. - Segment::const_span oldData() const { - return const_cast<SegmentWriteMacData &>(*this).oldData(); - } - - /// Set old data. - SegmentWriteMacData & setOldData(Segment::const_span oldData) { - copy(oldData, this->oldData()); - return *this; - } - - /// @} - - /// @name New data - /// @brief New data to write to the segment. - /// @{ - - /// Get mutable new data. - Segment::span newData() { - return make_span(result_).subspan<newDataIdx, Segment::size>(); - } - - /// Get immutable new data. - Segment::const_span newData() const { - return const_cast<SegmentWriteMacData &>(*this).newData(); - } - - /// Set new data. - SegmentWriteMacData & setNewData(Segment::const_span newData) { - copy(newData, this->newData()); - return *this; - } - - /// @} - -private: - typedef Sha256::WriteMacData::span::index_type index; - - static const index romIdIdx = 0; - static const index manIdIdx = romIdIdx + RomId::size; - static const index pageNumIdx = manIdIdx + ManId::size; - static const index segmentNumIdx = pageNumIdx + 1; - static const index oldDataIdx = segmentNumIdx + 1; - static const index newDataIdx = oldDataIdx + Segment::size; - - Sha256::WriteMacData::array result_; -}; - -/// Format data to hash for an Authenticated Write to a memory protection block. -class DS28E15_22_25::ProtectionWriteMacData { -public: - MaximInterface_EXPORT ProtectionWriteMacData(); - - /// Formatted data result. - Sha256::WriteMacData::const_span result() const { return result_; } - - /// @name ROM ID - /// @brief 1-Wire ROM ID of the device. - /// @{ - - /// Get mutable ROM ID. - RomId::span romId() { - return make_span(result_).subspan<romIdIdx, RomId::size>(); - } - - /// Get immutable ROM ID. - RomId::const_span romId() const { - return const_cast<ProtectionWriteMacData &>(*this).romId(); - } - - /// Set ROM ID. - ProtectionWriteMacData & setRomId(RomId::const_span romId) { - copy(romId, this->romId()); - return *this; - } - - /// @} - - /// @name MAN ID - /// @brief Manufacturer ID of the device. - /// @{ - - /// Get mutable MAN ID. - ManId::span manId() { - return make_span(result_).subspan<manIdIdx, ManId::size>(); - } - - /// Get immutable MAN ID. - ManId::const_span manId() const { - return const_cast<ProtectionWriteMacData &>(*this).manId(); - } - - /// Set MAN ID. - ProtectionWriteMacData & setManId(ManId::const_span manId) { - copy(manId, this->manId()); - return *this; - } - - /// @} - - /// @name Old protection - /// @brief Existing protection status in device. - /// @{ - - /// Get old protection. - BlockProtection oldProtection() const { return oldProtection_; } - - /// Set old protection. - MaximInterface_EXPORT ProtectionWriteMacData & - setOldProtection(BlockProtection oldProtection); - - /// @} - - /// @name New protection - /// @brief New protection status to write. - /// @{ - - /// Get new protection. - BlockProtection newProtection() const { return newProtection_; } - - /// Set new protection. - MaximInterface_EXPORT ProtectionWriteMacData & - setNewProtection(BlockProtection newProtection); - - /// @} - -private: - typedef Sha256::WriteMacData::span::index_type index; - - static const index romIdIdx = 0; - static const index manIdIdx = romIdIdx + RomId::size; - static const index blockNumIdx = manIdIdx + ManId::size; - static const index oldProtectionIdx = blockNumIdx + 2; - static const index newProtectionIdx = oldProtectionIdx + 4; - - Sha256::WriteMacData::array result_; - BlockProtection oldProtection_; - BlockProtection newProtection_; -}; - -/// @brief -/// Format data to hash for device authentication or computing the next secret -/// from the existing secret. -class DS28E15_22_25::AuthenticationData { -public: - AuthenticationData() : result_() {} - - /// Formatted data result. - Sha256::AuthenticationData::const_span result() const { return result_; } - - /// @name Page - /// @brief Data from a device memory page. - /// @{ - - /// Get mutable page. - Page::span page() { - return make_span(result_).subspan<pageIdx, Page::size>(); - } - - /// Get immutable page. - Page::const_span page() const { - return const_cast<AuthenticationData &>(*this).page(); - } - - /// Set page. - AuthenticationData & setPage(Page::const_span page) { - copy(page, this->page()); - return *this; - } - - /// @} - - /// @name Scratchpad - /// @brief - /// Data from device scratchpad used as a random challenge in device - /// authentication and a partial secret in secret computation. - /// @{ - - /// Get mutable scratchpad. - Scratchpad::span scratchpad() { - return make_span(result_).subspan<scratchpadIdx, Scratchpad::size>(); - } - - /// Get immutable scratchpad. - Scratchpad::const_span scratchpad() const { - return const_cast<AuthenticationData &>(*this).scratchpad(); - } - - /// Set scratchpad. - AuthenticationData & setScratchpad(Scratchpad::const_span scratchpad) { - copy(scratchpad, this->scratchpad()); - return *this; - } - - /// @} - - /// @name ROM ID - /// @brief 1-Wire ROM ID of the device. - /// @{ - - /// Get mutable ROM ID. - RomId::span romId() { - return make_span(result_).subspan<romIdIdx, RomId::size>(); - } - - /// Get immutable ROM ID. - RomId::const_span romId() const { - return const_cast<AuthenticationData &>(*this).romId(); - } - - /// Set ROM ID. - AuthenticationData & setRomId(RomId::const_span romId) { - copy(romId, this->romId()); - return *this; - } - - /// Set ROM ID for use in anonymous mode. - MaximInterface_EXPORT AuthenticationData & setAnonymousRomId(); - - /// @} - - /// @name MAN ID - /// @brief Manufacturer ID of the device. - /// @{ - - /// Get mutable MAN ID. - ManId::span manId() { - return make_span(result_).subspan<manIdIdx, ManId::size>(); - } - - /// Get immutable MAN ID. - ManId::const_span manId() const { - return const_cast<AuthenticationData &>(*this).manId(); - } - - /// Set MAN ID. - AuthenticationData & setManId(ManId::const_span manId) { - copy(manId, this->manId()); - return *this; - } - - /// @} - - /// @name Page number - /// @brief Number of the page to use data from. - /// @{ - - /// Get page number. - int pageNum() const { return result_[pageNumIdx]; } - - /// Set page number. - AuthenticationData & setPageNum(int pageNum) { - result_[pageNumIdx] = pageNum; - return *this; - } - - /// @} - -private: - typedef Sha256::AuthenticationData::span::index_type index; - - static const index pageIdx = 0; - static const index scratchpadIdx = pageIdx + Page::size; - static const index romIdIdx = scratchpadIdx + Scratchpad::size; - static const index manIdIdx = romIdIdx + RomId::size; - static const index pageNumIdx = manIdIdx + ManId::size; - - Sha256::AuthenticationData::array result_; -}; - -} // namespace MaximInterface - -#endif
--- a/Devices/DS28E17.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,270 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include <stddef.h> -#include <MaximInterface/Links/OneWireMaster.hpp> -#include <MaximInterface/Utilities/crc.hpp> -#include <MaximInterface/Utilities/Error.hpp> -#include "DS28E17.hpp" - -namespace MaximInterface { - -error_code DS28E17::writeDataWithStop(uint_least8_t I2C_addr, - span<const uint_least8_t> data, - uint_least8_t * wr_status) { - return sendPacket(WriteDataWithStopCmd, &I2C_addr, data, - span<uint_least8_t>(), wr_status); -} - -error_code DS28E17::writeDataNoStop(uint_least8_t I2C_addr, - span<const uint_least8_t> data, - uint_least8_t * wr_status) { - return sendPacket(WriteDataNoStopCmd, &I2C_addr, data, span<uint_least8_t>(), - wr_status); -} - -error_code DS28E17::writeDataOnly(span<const uint_least8_t> data, - uint_least8_t * wr_status) { - return sendPacket(WriteDataOnlyCmd, NULL, data, span<uint_least8_t>(), - wr_status); -} - -error_code DS28E17::writeDataOnlyWithStop(span<const uint_least8_t> data, - uint_least8_t * wr_status) { - return sendPacket(WriteDataOnlyWithStopCmd, NULL, data, span<uint_least8_t>(), - wr_status); -} - -error_code DS28E17::writeReadDataWithStop(uint_least8_t I2C_addr, - span<const uint_least8_t> write_data, - span<uint_least8_t> read_data, - uint_least8_t * wr_status) { - return sendPacket(WriteReadDataWithStopCmd, &I2C_addr, write_data, read_data, - wr_status); -} - -error_code DS28E17::readDataWithStop(uint_least8_t I2C_addr, - span<uint_least8_t> data) { - return sendPacket(ReadDataWithStopCmd, &I2C_addr, span<const uint_least8_t>(), - data, NULL); -} - -error_code DS28E17::writeConfigReg(I2CSpeed speed) { - error_code result = selectRom(*master); - if (!result) { - // Send CMD and Data - const uint_least8_t send_block[] = {WriteConfigurationCmd, - static_cast<uint_least8_t>(speed)}; - result = master->writeBlock(send_block); - } - return result; -} - -error_code DS28E17::readConfigReg(I2CSpeed & speed) { - error_code result = selectRom(*master); - if (!result) { - // Send CMD and receive Data - result = master->writeByte(ReadConfigurationCmd); - if (!result) { - uint_least8_t config; - result = master->readByte(config); - if (!result) { - switch (config) { - case Speed100kHz: - case Speed400kHz: - case Speed900kHz: - speed = static_cast<I2CSpeed>(config); - break; - - default: - result = make_error_code(OutOfRangeError); - break; - } - } - } - } - return result; -} - -error_code DS28E17::enableSleepMode() { - error_code result = selectRom(*master); - if (!result) { - // Send CMD - result = master->writeByte(EnableSleepModeCmd); - } - return result; -} - -error_code DS28E17::readDeviceRevision(uint_least8_t & rev) { - error_code result = selectRom(*master); - if (!result) { - // Send CMD and receive Data - result = master->writeByte(ReadDeviceRevisionCmd); - if (!result) { - result = master->readByte(rev); - } - } - return result; -} - -error_code DS28E17::sendPacket(Command command, const uint_least8_t * I2C_addr, - span<const uint_least8_t> write_data, - span<uint_least8_t> read_data, - uint_least8_t * wr_status) { - const int pollLimit = 10000; - const span<const uint_least8_t>::index_type maxDataLen = 255; - - if ((!write_data.empty() && write_data.size() > maxDataLen) || - (!read_data.empty() && read_data.size() > maxDataLen)) { - return make_error_code(OutOfRangeError); - } - - error_code result = selectRom(*master); - if (result) { - return result; - } - uint_fast16_t crc16 = calculateCrc16(command); - result = master->writeByte(command); - if (result) { - return result; - } - if (I2C_addr) { - crc16 = calculateCrc16(*I2C_addr, crc16); - result = master->writeByte(*I2C_addr); - if (result) { - return result; - } - } - if (!write_data.empty()) { - crc16 = calculateCrc16(static_cast<uint_fast8_t>(write_data.size()), crc16); - result = master->writeByte(static_cast<uint_least8_t>(write_data.size())); - if (result) { - return result; - } - crc16 = calculateCrc16(write_data, crc16); - result = master->writeBlock(write_data); - if (result) { - return result; - } - } - if (!read_data.empty()) { - crc16 = calculateCrc16(static_cast<uint_fast8_t>(read_data.size()), crc16); - result = master->writeByte(static_cast<uint_least8_t>(read_data.size())); - if (result) { - return result; - } - } - crc16 ^= 0xFFFFU; - const uint_least8_t crc16Bytes[] = {static_cast<uint_least8_t>(crc16), - static_cast<uint_least8_t>(crc16 >> 8)}; - result = master->writeBlock(crc16Bytes); - if (result) { - return result; - } - // Poll for Zero 1-Wire bit and return if an error occurs - int poll_count = 0; - bool recvbit; - do { - if (poll_count++ < pollLimit) { - return make_error_code(TimeoutError); - } - result = master->readBit(recvbit); - if (result) { - return result; - } - } while (recvbit); - uint_least8_t status; - result = master->readByte(status); - if (result) { - return result; - } - if ((status & 0x1) == 0x1) { - return make_error_code(InvalidCrc16Error); - } - if ((status & 0x2) == 0x2) { - return make_error_code(AddressNackError); - } - if ((status & 0x8) == 0x8) { - return make_error_code(InvalidStartError); - } - if (!write_data.empty()) { - result = master->readByte(status); - if (result) { - return result; - } - if (wr_status) { - *wr_status = status; - } - if (status != 0) { - return make_error_code(WriteNackError); - } - } - if (!read_data.empty()) { - result = master->readBlock(read_data); - } - return result; -} - -const error_category & DS28E17::errorCategory() { - static class : public error_category { - public: - virtual const char * name() const { return "DS28E17"; } - - virtual std::string message(int condition) const { - switch (condition) { - case TimeoutError: - return "Timeout Error"; - - case OutOfRangeError: - return "Out of Range Error"; - - case InvalidCrc16Error: - return "Invalid CRC16 Error"; - - case AddressNackError: - return "Address Nack Error"; - - case InvalidStartError: - return "Invalid Start Error"; - - case WriteNackError: - return "Write Nack Error"; - - default: - return defaultErrorMessage(condition); - } - } - } instance; - return instance; -} - -} // namespace MaximInterface
--- a/Devices/DS28E17.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,205 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_DS28E17 -#define MaximInterface_DS28E17 - -#include <stdint.h> -#include <MaximInterface/Links/SelectRom.hpp> -#include <MaximInterface/Utilities/Export.h> -#include <MaximInterface/Utilities/span.hpp> - -namespace MaximInterface { - -/// @brief DS28E17 1-Wire®-to-I2C Master Bridge -/// @details The DS28E17 is a 1-Wire slave to I2C master bridge -/// device that interfaces directly to I2C slaves at standard -/// (100kHz max) or fast (400kHz max). Data transfers serially by -/// means of the 1-Wire® protocol, which requires only a single data -/// lead and a ground return. Every DS28E17 is guaranteed to have a -/// unique 64-bit ROM registration number that serves as a node -/// address in the 1-Wire network. Multiple DS28E17 devices can -/// coexist with other devices in the 1-Wire network and be accessed -/// individually without affecting other devices. The DS28E17 allows -/// using complex I2C devices such as display controllers, ADCs, DACs, -/// I2C sensors, etc. in a 1-Wire environment. Each self-timed DS28E17 -/// provides 1-Wire access for a single I2C interface. -class DS28E17 { -public: - enum ErrorValue { - TimeoutError = 1, - OutOfRangeError, - InvalidCrc16Error, - AddressNackError, - InvalidStartError, - WriteNackError - }; - - enum I2CSpeed { Speed100kHz, Speed400kHz, Speed900kHz }; - - DS28E17(OneWireMaster & master, const SelectRom & selectRom) - : selectRom(selectRom), master(&master) {} - - void setMaster(OneWireMaster & master) { this->master = &master; } - - void setSelectRom(const SelectRom & selectRom) { - this->selectRom = selectRom; - } - - /// @brief Write Data With Stop command. - /// @details Output on I2C: S, Address + Write, Write Data [1-255], P - /// @param[in] I2C_addr - /// I2C slave address. The least significant bit of the I2C - /// address is automatically cleared by the command. - /// @param[in] data I2C data to write with length 1-255. - /// @param[out] wr_status - /// Indicates which write byte NACK’d. A value of 00h indicates all bytes - /// were acknowledged by the slave. A non-zero value indicates the byte number - /// that NACK’d. May be set to NULL. - MaximInterface_EXPORT error_code - writeDataWithStop(uint_least8_t I2C_addr, span<const uint_least8_t> data, - uint_least8_t * wr_status = NULL); - - /// @brief Write Data No Stop command. - /// @details Output on I2C: S, Address + Write, Write Data [1-255] - /// @param[in] I2C_addr - /// I2C slave address. The least significant bit of the I2C address - /// is automatically cleared by the command. - /// @param[in] data I2C data to write with length 1-255. - /// @param[out] wr_status - /// Indicates which write byte NACK’d. A value of 00h indicates all bytes - /// were acknowledged by the slave. A non-zero value indicates the byte number - /// that NACK’d. May be set to NULL. - MaximInterface_EXPORT error_code - writeDataNoStop(uint_least8_t I2C_addr, span<const uint_least8_t> data, - uint_least8_t * wr_status = NULL); - - /// @brief Write Data Only command. - /// @details Output on I2C: Write Data [1-255] - /// @param[in] data I2C data to write with length 1-255. - /// @param[out] wr_status - /// Indicates which write byte NACK’d. A value of 00h indicates all bytes - /// were acknowledged by the slave. A non-zero value indicates the byte number - /// that NACK’d. May be set to NULL. - MaximInterface_EXPORT error_code - writeDataOnly(span<const uint_least8_t> data, - uint_least8_t * wr_status = NULL); - - /// @brief Write Data Only With Stop command. - /// @details Output on I2C: Write Data [1-255], P - /// @param[in] data I2C data to write with length 1-255. - /// @param[out] wr_status - /// Indicates which write byte NACK’d. A value of 00h indicates all bytes - /// were acknowledged by the slave. A non-zero value indicates the byte number - /// that NACK’d. May be set to NULL. - MaximInterface_EXPORT error_code - writeDataOnlyWithStop(span<const uint_least8_t> data, - uint_least8_t * wr_status = NULL); - - /// @brief Write, Read Data With Stop command. - /// @details Output on I2C: - /// S, Slave Address + Write, Write Data [1-255], - /// Sr, Address + Read, Read Data [1-255], P (NACK last read byte) - /// @param[in] I2C_addr - /// I2C slave address. The least significant bit of the I2C address - /// is automatically cleared and set by the command. - /// @param[in] write_data I2C data to write with length 1-255. - /// @param[out] read_data I2C data that was read with length 1-255. - /// @param[out] wr_status - /// Indicates which write byte NACK’d. A value of 00h indicates all bytes - /// were acknowledged by the slave. A non-zero value indicates the byte number - /// that NACK’d. May be set to NULL. - MaximInterface_EXPORT error_code writeReadDataWithStop( - uint_least8_t I2C_addr, span<const uint_least8_t> write_data, - span<uint_least8_t> read_data, uint_least8_t * wr_status = NULL); - - /// @brief Read Data With Stop command. - /// @details Output on I2C: - /// S, Slave Address + Read, Read Data [1-255], P (NACK last read byte) - /// @param[in] I2C_addr - /// I2C slave address. The least significant bit of the I2C address - /// is automatically set by the command. - /// @param[out] data I2C data that was read with length 1-255. - MaximInterface_EXPORT error_code readDataWithStop(uint_least8_t I2C_addr, - span<uint_least8_t> data); - - /// Write to Configuration Register of DS28E17. - MaximInterface_EXPORT error_code writeConfigReg(I2CSpeed speed); - - /// @brief Read the Configuration Register of DS28E17. - /// @param[out] speed Speed read from configuration register. - MaximInterface_EXPORT error_code readConfigReg(I2CSpeed & speed); - - /// @brief Put the device into a low current mode. - /// @details All 1-Wire communication is ignored until woken up. Immediately - /// after the command, the device monitors the WAKEUP input pin and exits - /// sleep mode on a rising edge. - MaximInterface_EXPORT error_code enableSleepMode(); - - /// @brief Read the Device Revision of DS28E17. - /// @details The upper nibble is the major revision, - /// and the lower nibble is the minor revision. - /// @param[out] rev Device Revision. - MaximInterface_EXPORT error_code readDeviceRevision(uint_least8_t & rev); - - MaximInterface_EXPORT static const error_category & errorCategory(); - -private: - enum Command { - WriteDataWithStopCmd = 0x4B, - WriteDataNoStopCmd = 0x5A, - WriteDataOnlyCmd = 0x69, - WriteDataOnlyWithStopCmd = 0x78, - ReadDataWithStopCmd = 0x87, - WriteReadDataWithStopCmd = 0x2D, - WriteConfigurationCmd = 0xD2, - ReadConfigurationCmd = 0xE1, - EnableSleepModeCmd = 0x1E, - ReadDeviceRevisionCmd = 0xC3 - }; - - error_code sendPacket(Command command, const uint_least8_t * I2C_addr, - span<const uint_least8_t> write_data, - span<uint_least8_t> read_data, - uint_least8_t * wr_status); - - SelectRom selectRom; - OneWireMaster * master; -}; - -inline error_code make_error_code(DS28E17::ErrorValue e) { - return error_code(e, DS28E17::errorCategory()); -} - -} // namespace MaximInterface - -#endif
--- a/Devices/DS28E38.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,302 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include <stddef.h> -#include <algorithm> -#include <MaximInterface/Utilities/Algorithm.hpp> -#include <MaximInterface/Utilities/Error.hpp> -#include "DS28E38.hpp" - -namespace MaximInterface { - -using std::copy; - -static const int readMemoryTimeMs = 30; -static const int writeMemoryTimeMs = 65; -static const int writeStateTimeMs = 15; -static const int generateEccKeyPairTimeMs = 200; -static const int generateEcdsaSignatureTimeMs = 130; -static const int trngOnDemandCheckTimeMs = 20; -static const int trngGenerationTimeMs = 10; - -const int DS28E38::decrementCounterPage; -const int DS28E38::publicKeyXPage; -const int DS28E38::publicKeyYPage; -const int DS28E38::privateKeyPage; -const int DS28E38::memoryPages; - -error_code DS28E38::writeMemory(int pageNum, Page::const_span page) { - if (pageNum < 0 || pageNum >= memoryPages) { - return make_error_code(InvalidParameterError); - } - - uint_least8_t command[2 + Page::size]; - command[0] = 0x96; - command[1] = pageNum; - copy(page.begin(), page.end(), command + 2); - return runCommand(command, writeMemoryTimeMs); -} - -error_code DS28E38::readMemory(int pageNum, Page::span page) { - if (pageNum < 0 || pageNum >= memoryPages) { - return make_error_code(InvalidParameterError); - } - - uint_least8_t buffer[1 + Page::size]; - buffer[0] = 0x44; - buffer[1] = pageNum; - span<uint_least8_t> response(buffer); - const error_code result = - runCommand(make_span(buffer, 2), readMemoryTimeMs, response); - if (!result) { - copy(response.begin(), response.end(), page.begin()); - } - return result; -} - -error_code DS28E38::readStatus(bool entropyHealthTest, Status & status) { - int delay = readMemoryTimeMs; - if (entropyHealthTest) { - delay += trngOnDemandCheckTimeMs; - } - uint_least8_t buffer[Status::PageProtectionList::csize + ManId::size + - Status::RomVersion::csize + 2]; - buffer[0] = 0xAA; - buffer[1] = entropyHealthTest ? 0x01 : 0x00; - span<uint_least8_t> response(buffer); - error_code result = runCommand(make_span(buffer, 2), delay, response); - if (!result) { - span<uint_least8_t>::const_iterator responseIt = response.begin(); - for (Status::PageProtectionList::iterator it = - status.pageProtection.begin(); - it != status.pageProtection.end(); ++it) { - *it = *responseIt; - ++responseIt; - } - span<uint_least8_t>::const_iterator responseItEnd = - responseIt + status.manId.size(); - copy(responseIt, responseItEnd, status.manId.begin()); - responseIt = responseItEnd; - responseItEnd = responseIt + status.romVersion.size(); - copy(responseIt, responseItEnd, status.romVersion.begin()); - responseIt = responseItEnd; - switch (*responseIt) { - case Status::TestNotPerformed: - case Status::EntropyHealthy: - case Status::EntropyNotHealthy: - status.entropyHealthTestStatus = - static_cast<Status::EntropyHealthTestStatus>(*responseIt); - break; - - default: - result = make_error_code(InvalidResponseError); - break; - } - } - return result; -} - -error_code DS28E38::setPageProtection(int pageNum, - const PageProtection & protection) { - if (pageNum < 0 || pageNum >= memoryPages) { - return make_error_code(InvalidParameterError); - } - - int delay = writeStateTimeMs; - if (pageNum == decrementCounterPage) { - delay += writeMemoryTimeMs; - } - const uint_least8_t command[] = { - 0xC3, static_cast<uint_least8_t>(pageNum), - static_cast<uint_least8_t>(protection.to_ulong())}; - return runCommand(command, delay); -} - -error_code -DS28E38::computeAndReadPageAuthentication(int pageNum, bool anonymous, - Page::const_span challenge, - Ecc256::Signature::span signature) { - if (pageNum < 0 || pageNum >= memoryPages) { - return make_error_code(InvalidParameterError); - } - - const size_t commandSize = 2 + Page::size; - const size_t responseSize = 1 + 2 * Ecc256::Scalar::size; - uint_least8_t buffer[MaximInterface_MAX(commandSize, responseSize)]; - buffer[0] = 0xA5; - buffer[1] = pageNum | (anonymous ? 0xE0 : 0x00); - copy(challenge.begin(), challenge.end(), buffer + 2); - span<uint_least8_t> response(buffer, responseSize); - const error_code result = runCommand(make_span(buffer, commandSize), - generateEcdsaSignatureTimeMs, response); - if (!result) { - span<uint_least8_t>::const_iterator begin = response.begin(); - span<uint_least8_t>::const_iterator end = begin + signature.s.size(); - copy(begin, end, signature.s.begin()); - begin = end; - end = begin + signature.r.size(); - copy(begin, end, signature.r.begin()); - } - return result; -} - -error_code DS28E38::decrementCounter() { - const uint_least8_t command = 0xC9; - return runCommand(make_span(&command, 1), writeMemoryTimeMs); -} - -error_code DS28E38::disableDevice() { - const uint_least8_t command[] = {0x33, 0x9E, 0xA7, 0x49, 0xFB, - 0x10, 0x62, 0x0A, 0x26}; - return runCommand(command, writeStateTimeMs); -} - -error_code DS28E38::generateEcc256KeyPair(bool privateKeyPuf, - bool writeProtectEnable) { - int delay = generateEccKeyPairTimeMs; - if (writeProtectEnable) { - delay += writeStateTimeMs; - } - uint_least8_t command[] = {0xCB, 0x00}; - if (privateKeyPuf) { - command[1] |= 0x01; - } - if (writeProtectEnable) { - command[1] |= 0x80; - } - return runCommand(command, delay); -} - -error_code DS28E38::readRng(span<uint_least8_t> data) { - const span<uint_least8_t>::index_type maxDataSize = 64; - if ((data.size() < 1) || (data.size() > maxDataSize)) { - return make_error_code(InvalidParameterError); - } - - uint_least8_t buffer[1 + maxDataSize]; - buffer[0] = 0xD2; - buffer[1] = data.size() - 1; - span<uint_least8_t> response(buffer, 1 + data.size()); - const error_code result = - runCommand(make_span(buffer, 2), trngGenerationTimeMs, response); - if (!result) { - copy(response.begin(), response.end(), data.begin()); - } - return result; -} - -error_code DS28E38::runCommand(span<const uint_least8_t> command, int delayTime, - span<uint_least8_t> & response) { - const span<const uint_least8_t>::index_type responseInputSize = - response.size(); - error_code result = doRunCommand(command, delayTime, response); - if (result) { - return result; - } - if (response.empty()) { - return make_error_code(InvalidResponseError); - } - // Parse command result byte. - switch (response[0]) { - case 0xAA: - // Success response. - if (response.size() != responseInputSize) { - result = make_error_code(InvalidResponseError); - } - break; - - case 0x00: - result = make_error_code(InvalidResponseError); - break; - - default: - result.assign(response[0], errorCategory()); - break; - } - response = response.subspan(1); - return result; -} - -error_code DS28E38::runCommand(span<const uint_least8_t> command, - int delayTime) { - uint_least8_t buffer; - span<uint_least8_t> response(&buffer, 1); - return runCommand(command, delayTime, response); -} - -const error_category & DS28E38::errorCategory() { - static class : public error_category { - public: - virtual const char * name() const { return "DS28E38"; } - - virtual std::string message(int condition) const { - switch (condition) { - case InvalidOperationError: - return "Invalid Operation Error"; - - case InvalidParameterError: - return "Invalid Parameter Error"; - - case InvalidSequenceError: - return "Invalid Sequence Error"; - - case InternalError: - return "Internal Error"; - - case DeviceDisabledError: - return "Device Disabled Error"; - - case InvalidResponseError: - return "Invalid Response Error"; - } - return defaultErrorMessage(condition); - } - } instance; - return instance; -} - -error_code readManId(DS28E38 & ds28e38, ManId::span manId) { - DS28E38::Status status; - const error_code result = ds28e38.readStatus(false, status); - if (!result) { - copy(make_span(status.manId), manId); - } - return result; -} - -DS28E38::PageAuthenticationData & -DS28E38::PageAuthenticationData::setAnonymousRomId() { - std::fill(romId().begin(), romId().end(), 0xFF); - return *this; -} - -} // namespace MaximInterface
--- a/Devices/DS28E38.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,316 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_DS28E38 -#define MaximInterface_DS28E38 - -#include <stdint.h> -#include <MaximInterface/Links/RunCommand.hpp> -#include <MaximInterface/Utilities/array_span.hpp> -#include <MaximInterface/Utilities/Ecc256.hpp> -#include <MaximInterface/Utilities/Export.h> -#include <MaximInterface/Utilities/FlagSet.hpp> -#include <MaximInterface/Utilities/ManId.hpp> -#include <MaximInterface/Utilities/system_error.hpp> - -namespace MaximInterface { - -class DS28E38 { -public: - /// Device command results. - enum ErrorValue { - InvalidOperationError = 0x55, - InvalidParameterError = 0x77, - InvalidSequenceError = 0x33, - InternalError = 0x22, - DeviceDisabledError = 0x88, - InvalidResponseError = - 0x100 ///< Command response does not match expected format. - }; - - /// @name Device memory pages - /// @{ - - static const int decrementCounterPage = 3; - static const int publicKeyXPage = 4; - static const int publicKeyYPage = 5; - static const int privateKeyPage = 6; - - /// @} - - static const int memoryPages = 7; - - /// Holds a device memory page. - typedef array_span<uint_least8_t, 32> Page; - - // Format page authentication input data. - class PageAuthenticationData; - - /// Page protection types. - enum PageProtectionType { - RP = 0x01, ///< Read protection. - WP = 0x02, ///< Write protection. - EM = 0x04, ///< EPROM emulation mode. - DC = 0x08, ///< Decrement counter. - PF = 0x10 ///< PUF used as private key. - }; - typedef FlagSet<PageProtectionType, 5> PageProtection; - - struct Status { - enum EntropyHealthTestStatus { - TestNotPerformed = 0xFF, - EntropyHealthy = 0xAA, - EntropyNotHealthy = 0xDD - }; - - typedef array<PageProtection, memoryPages> PageProtectionList; - typedef array<uint_least8_t, 2> RomVersion; - - PageProtectionList pageProtection; - ManId::array manId; - RomVersion romVersion; - EntropyHealthTestStatus entropyHealthTestStatus; - }; - - explicit DS28E38(const RunCommand & runCommand) : doRunCommand(runCommand) {} - - void setRunCommand(const RunCommand & runCommand) { - doRunCommand = runCommand; - } - - /// @brief Write memory with no protection. - /// @param pageNum Number of page to write. - /// @param page Data to write. - MaximInterface_EXPORT error_code writeMemory(int pageNum, - Page::const_span page); - - /// @brief Read memory with no protection. - /// @param pageNum Number of page to read. - /// @param[out] page Data that was read. - MaximInterface_EXPORT error_code readMemory(int pageNum, Page::span page); - - /// @brief - /// Reads the current status of the device and optionally performs an - /// entropy health test. - /// @param entropyHealthTest True to perform an entropy health test. - /// @param[out] status Status that was read. - MaximInterface_EXPORT error_code readStatus(bool entropyHealthTest, - Status & status); - - /// @brief Set the protection settings of a page. - /// @param pageNum Number of page to write. - /// @param protection Protection to write. - MaximInterface_EXPORT error_code - setPageProtection(int pageNum, const PageProtection & protection); - - /// @brief Compute and read page authentication with ECDSA. - /// @param pageNum Number of page to authenticate. - /// @param anonymous True to disable use of ROM ID in computation. - /// @param challenge Random challenge used to prevent replay attacks. - /// @param[out] signature Computed page signature. - MaximInterface_EXPORT error_code computeAndReadPageAuthentication( - int pageNum, bool anonymous, Page::const_span challenge, - Ecc256::Signature::span signature); - - /// Decrement the decrement-only counter. - MaximInterface_EXPORT error_code decrementCounter(); - - /// Permanently disable the device. - MaximInterface_EXPORT error_code disableDevice(); - - /// @brief Generate a new ECDSA public key from an existing private key. - /// @param privateKeyPuf True if PUF is used as the private key. - /// @param writeProtectEnable True to lock the key against further writes. - MaximInterface_EXPORT error_code - generateEcc256KeyPair(bool privateKeyPuf, bool writeProtectEnable); - - /// @brief Read a block of random data from the RNG. - /// @param[out] data Random data from RNG with length from 1 to 64. - MaximInterface_EXPORT error_code readRng(span<uint_least8_t> data); - - MaximInterface_EXPORT static const error_category & errorCategory(); - -protected: - MaximInterface_EXPORT error_code runCommand(span<const uint_least8_t> command, - int delayTime, - span<uint_least8_t> & response); - - MaximInterface_EXPORT error_code runCommand(span<const uint_least8_t> command, - int delayTime); - -private: - RunCommand doRunCommand; -}; - -inline error_code make_error_code(DS28E38::ErrorValue e) { - return error_code(e, DS28E38::errorCategory()); -} - -/// @brief Read the device MAN ID using the Read Status command. -/// @param ds28e38 Device to read. -/// @param[out] manId Read MAN ID valid when operation is successful. -MaximInterface_EXPORT error_code readManId(DS28E38 & ds28e38, - ManId::span manId); - -/// Format page authentication input data. -class DS28E38::PageAuthenticationData { -public: - typedef array_span<uint_least8_t, - RomId::size + 2 * Page::size + 1 + ManId::size> - Result; - - PageAuthenticationData() : result_() {} - - /// Formatted data result. - Result::const_span result() const { return result_; } - - /// @name ROM ID - /// @brief 1-Wire ROM ID of the device. - /// @{ - - /// Get mutable ROM ID. - RomId::span romId() { - return make_span(result_).subspan<romIdIdx, RomId::size>(); - } - - /// Get immutable ROM ID. - RomId::const_span romId() const { - return const_cast<PageAuthenticationData &>(*this).romId(); - } - - /// Set ROM ID. - PageAuthenticationData & setRomId(RomId::const_span romId) { - copy(romId, this->romId()); - return *this; - } - - /// Set ROM ID for use in anonymous mode. - MaximInterface_EXPORT PageAuthenticationData & setAnonymousRomId(); - - /// @} - - /// @name Page - /// @brief Data from a device memory page. - /// @{ - - /// Get mutable page. - Page::span page() { - return make_span(result_).subspan<pageIdx, Page::size>(); - } - - /// Get immutable page. - Page::const_span page() const { - return const_cast<PageAuthenticationData &>(*this).page(); - } - - /// Set page. - PageAuthenticationData & setPage(Page::const_span page) { - copy(page, this->page()); - return *this; - } - - /// @} - - /// @name Challenge - /// @brief Random challenge used to prevent replay attacks. - /// @{ - - /// Get mutable Challenge. - Page::span challenge() { - return make_span(result_).subspan<challengeIdx, Page::size>(); - } - - /// Get immutable Challenge. - Page::const_span challenge() const { - return const_cast<PageAuthenticationData &>(*this).challenge(); - } - - /// Set Challenge. - PageAuthenticationData & setChallenge(Page::const_span challenge) { - copy(challenge, this->challenge()); - return *this; - } - - /// @} - - /// @name Page number - /// @brief Number of the page to use data from. - /// @{ - - /// Get page number. - int pageNum() const { return result_[pageNumIdx]; } - - /// Set page number. - PageAuthenticationData & setPageNum(int pageNum) { - result_[pageNumIdx] = pageNum; - return *this; - } - - /// @} - - /// @name MAN ID - /// @brief Manufacturer ID of the device. - /// @{ - - /// Get mutable MAN ID. - ManId::span manId() { - return make_span(result_).subspan<manIdIdx, ManId::size>(); - } - - /// Get immutable MAN ID. - ManId::const_span manId() const { - return const_cast<PageAuthenticationData &>(*this).manId(); - } - - /// Set MAN ID. - PageAuthenticationData & setManId(ManId::const_span manId) { - copy(manId, this->manId()); - return *this; - } - - /// @} - -private: - typedef Result::span::index_type index; - - static const index romIdIdx = 0; - static const index pageIdx = romIdIdx + RomId::size; - static const index challengeIdx = pageIdx + Page::size; - static const index pageNumIdx = challengeIdx + Page::size; - static const index manIdIdx = pageNumIdx + 1; - - Result::array result_; -}; - -} // namespace MaximInterface - -#endif
--- a/Devices/DS9400.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include "DS9400.hpp" - -namespace MaximInterface { - -error_code DS9400::waitAwake() { - error_code result; - uint_least8_t data; - do { - result = uart->readByte(data); - } while (!result && data != 0xA5); - return result; -} - -error_code DS9400::start() { return uart->writeByte('S'); } - -error_code DS9400::start(uint_least8_t address) { - error_code result = start(); - if (!result) { - result = writeByte(address); - } - return result; -} - -error_code DS9400::stop() { return uart->writeByte('P'); } - -error_code DS9400::writeByte(uint_least8_t data) { - const uint_least8_t packet[] = {'Q', data}; - error_code result = uart->clearReadBuffer(); - if (!result) { - result = uart->writeBlock(packet); - if (!result) { - result = uart->readByte(data); - if (!result && data != 0) { - result = make_error_code(I2CMaster::NackError); - } - } - } - return result; -} - -error_code DS9400::readByte(AckStatus status, uint_least8_t & data) { - error_code result = uart->clearReadBuffer(); - if (!result) { - result = uart->writeByte(status == Ack ? 'R' : 'N'); - if (!result) { - result = uart->readByte(data); - } - } - return result; -} - -error_code DS9400::configure(uint_least8_t config) { - const uint_least8_t packet[] = {'C', config}; - return uart->writeBlock(packet); -} - -} // namespace MaximInterface
--- a/Devices/DS9400.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_DS9400 -#define MaximInterface_DS9400 - -#include <MaximInterface/Links/I2CMaster.hpp> -#include <MaximInterface/Links/Uart.hpp> -#include <MaximInterface/Utilities/Export.h> - -namespace MaximInterface { - -class DS9400 : public I2CMaster { -public: - explicit DS9400(Uart & uart) : uart(&uart) {} - - void setUart(Uart & uart) { this->uart = &uart; } - - MaximInterface_EXPORT error_code waitAwake(); - - MaximInterface_EXPORT error_code start(); - - MaximInterface_EXPORT virtual error_code start(uint_least8_t address); - - MaximInterface_EXPORT virtual error_code stop(); - - MaximInterface_EXPORT virtual error_code writeByte(uint_least8_t data); - - MaximInterface_EXPORT virtual error_code readByte(AckStatus status, - uint_least8_t & data); - -protected: - MaximInterface_EXPORT error_code configure(uint_least8_t config); - -private: - Uart * uart; -}; - -} // namespace MaximInterface - -#endif
--- a/Devices/DS9481P_300.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,257 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include <MaximInterface/Utilities/Error.hpp> -#include "DS9481P_300.hpp" - -namespace MaximInterface { - -DS9481P_300::DS9481P_300(Sleep & sleep, SerialPort & serialPort) - : serialPort(&serialPort), currentBus(OneWire), ds2480b(sleep, serialPort), - oneWireMaster_(*this), ds9400(serialPort), i2cMaster_(*this) {} - -error_code DS9481P_300::connect(const std::string & portName) { - error_code result = serialPort->connect(portName); - if (!result) { - result = selectOneWire(); - if (result) { - serialPort->disconnect(); - } else { - currentBus = OneWire; - } - } - return result; -} - -error_code DS9481P_300::disconnect() { - return serialPort->disconnect(); -} - -bool DS9481P_300::connected() const { - return serialPort->connected(); -} - -std::string DS9481P_300::portName() const { - return serialPort->portName(); -} - -error_code DS9481P_300::selectOneWire() { - // Escape DS9400 mode. - error_code result = ds9400.escape(); - if (!result) { - result = ds2480b.initialize(); - } - return result; -} - -error_code DS9481P_300::selectBus(Bus newBus) { - error_code result; - if (currentBus != newBus) { - switch (currentBus) { - case OneWire: // Next bus I2C. - // Escape DS2480 Mode. - result = ds2480b.escape(); - if (!result) { - // Wait for awake notification. - result = ds9400.waitAwake(); - } - break; - - case I2C: // Next bus OneWire. - result = selectOneWire(); - break; - } - if (!result) { - currentBus = newBus; - } - } - return result; -} - -error_code DS9481P_300::OneWireMasterImpl::reset() { - error_code result = parent->selectBus(OneWire); - if (!result) { - result = OneWireMasterDecorator::reset(); - } - return result; -} - -error_code DS9481P_300::OneWireMasterImpl::touchBitSetLevel(bool & sendRecvBit, - Level afterLevel) { - error_code result = parent->selectBus(OneWire); - if (!result) { - result = OneWireMasterDecorator::touchBitSetLevel(sendRecvBit, afterLevel); - } - return result; -} - -error_code -DS9481P_300::OneWireMasterImpl::writeByteSetLevel(uint_least8_t sendByte, - Level afterLevel) { - error_code result = parent->selectBus(OneWire); - if (!result) { - result = OneWireMasterDecorator::writeByteSetLevel(sendByte, afterLevel); - } - return result; -} - -error_code -DS9481P_300::OneWireMasterImpl::readByteSetLevel(uint_least8_t & recvByte, - Level afterLevel) { - error_code result = parent->selectBus(OneWire); - if (!result) { - result = OneWireMasterDecorator::readByteSetLevel(recvByte, afterLevel); - } - return result; -} - -error_code -DS9481P_300::OneWireMasterImpl::writeBlock(span<const uint_least8_t> sendBuf) { - error_code result = parent->selectBus(OneWire); - if (!result) { - result = OneWireMasterDecorator::writeBlock(sendBuf); - } - return result; -} - -error_code -DS9481P_300::OneWireMasterImpl::readBlock(span<uint_least8_t> recvBuf) { - error_code result = parent->selectBus(OneWire); - if (!result) { - result = OneWireMasterDecorator::readBlock(recvBuf); - } - return result; -} - -error_code DS9481P_300::OneWireMasterImpl::setSpeed(Speed newSpeed) { - error_code result = parent->selectBus(OneWire); - if (!result) { - result = OneWireMasterDecorator::setSpeed(newSpeed); - } - return result; -} - -error_code DS9481P_300::OneWireMasterImpl::setLevel(Level newLevel) { - error_code result = parent->selectBus(OneWire); - if (!result) { - result = OneWireMasterDecorator::setLevel(newLevel); - } - return result; -} - -error_code DS9481P_300::OneWireMasterImpl::triplet(TripletData & data) { - error_code result = parent->selectBus(OneWire); - if (!result) { - result = OneWireMasterDecorator::triplet(data); - } - return result; -} - -error_code DS9481P_300::I2CMasterImpl::start(uint_least8_t address) { - error_code result = parent->selectBus(I2C); - if (!result) { - result = I2CMasterDecorator::start(address); - } - return result; -} - -error_code DS9481P_300::I2CMasterImpl::stop() { - error_code result = parent->selectBus(I2C); - if (!result) { - result = I2CMasterDecorator::stop(); - } - return result; -} - -error_code DS9481P_300::I2CMasterImpl::writeByte(uint_least8_t data) { - error_code result = parent->selectBus(I2C); - if (!result) { - result = I2CMasterDecorator::writeByte(data); - } - return result; -} - -error_code -DS9481P_300::I2CMasterImpl::writeBlock(span<const uint_least8_t> data) { - error_code result = parent->selectBus(I2C); - if (!result) { - result = I2CMasterDecorator::writeBlock(data); - } - return result; -} - -error_code DS9481P_300::I2CMasterImpl::writePacketImpl( - uint_least8_t address, span<const uint_least8_t> data, bool sendStop) { - error_code result = parent->selectBus(I2C); - if (!result) { - result = I2CMasterDecorator::writePacketImpl(address, data, sendStop); - } - return result; -} - -error_code DS9481P_300::I2CMasterImpl::readByte(AckStatus status, - uint_least8_t & data) { - error_code result = parent->selectBus(I2C); - if (!result) { - result = I2CMasterDecorator::readByte(status, data); - } - return result; -} - -error_code DS9481P_300::I2CMasterImpl::readBlock(AckStatus status, - span<uint_least8_t> data) { - error_code result = parent->selectBus(I2C); - if (!result) { - result = I2CMasterDecorator::readBlock(status, data); - } - return result; -} - -error_code DS9481P_300::I2CMasterImpl::readPacketImpl(uint_least8_t address, - span<uint_least8_t> data, - bool sendStop) { - error_code result = parent->selectBus(I2C); - if (!result) { - result = I2CMasterDecorator::readPacketImpl(address, data, sendStop); - } - return result; -} - -error_code DS9481P_300::DS2480BWithEscape::escape() { - return sendCommand(0xE5); -} - -error_code DS9481P_300::DS9400WithEscape::escape() { - return configure('O'); -} - -} // namespace MaximInterface
--- a/Devices/DS9481P_300.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,170 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_DS9481P_300 -#define MaximInterface_DS9481P_300 - -#include <MaximInterface/Devices/DS2480B.hpp> -#include <MaximInterface/Devices/DS9400.hpp> -#include <MaximInterface/Links/I2CMasterDecorator.hpp> -#include <MaximInterface/Links/OneWireMasterDecorator.hpp> -#include <MaximInterface/Links/SerialPort.hpp> -#include <MaximInterface/Links/Sleep.hpp> -#include <MaximInterface/Utilities/Export.h> - -namespace MaximInterface { - -/// DS9481P-300 USB to 1-Wire and I2C adapter. -class DS9481P_300 { -public: - MaximInterface_EXPORT DS9481P_300(Sleep & sleep, SerialPort & serialPort); - - void setSleep(Sleep & sleep) { ds2480b.setSleep(sleep); } - - void setSerialPort(SerialPort & serialPort) { - this->serialPort = &serialPort; - ds2480b.setUart(serialPort); - ds9400.setUart(serialPort); - } - - MaximInterface_EXPORT error_code connect(const std::string & portName); - - MaximInterface_EXPORT error_code disconnect(); - - MaximInterface_EXPORT bool connected() const; - - MaximInterface_EXPORT std::string portName() const; - - /// Access the 1-Wire master when connected to an adapter. - OneWireMaster & oneWireMaster() { return oneWireMaster_; } - - /// Access the I2C master when connected to an adapter. - I2CMaster & i2cMaster() { return i2cMaster_; } - -private: - class OneWireMasterImpl : public OneWireMasterDecorator { - public: - explicit OneWireMasterImpl(DS9481P_300 & parent) - : OneWireMasterDecorator(parent.ds2480b), parent(&parent) {} - - MaximInterface_EXPORT virtual error_code reset(); - - MaximInterface_EXPORT virtual error_code - touchBitSetLevel(bool & sendRecvBit, Level afterLevel); - - MaximInterface_EXPORT virtual error_code - writeByteSetLevel(uint_least8_t sendByte, Level afterLevel); - - MaximInterface_EXPORT virtual error_code - readByteSetLevel(uint_least8_t & recvByte, Level afterLevel); - - MaximInterface_EXPORT virtual error_code - writeBlock(span<const uint_least8_t> sendBuf); - - MaximInterface_EXPORT virtual error_code - readBlock(span<uint_least8_t> recvBuf); - - MaximInterface_EXPORT virtual error_code setSpeed(Speed newSpeed); - - MaximInterface_EXPORT virtual error_code setLevel(Level newLevel); - - MaximInterface_EXPORT virtual error_code triplet(TripletData & data); - - private: - DS9481P_300 * parent; - }; - - class I2CMasterImpl : public I2CMasterDecorator { - public: - explicit I2CMasterImpl(DS9481P_300 & parent) - : I2CMasterDecorator(parent.ds9400), parent(&parent) {} - - MaximInterface_EXPORT virtual error_code start(uint_least8_t address); - - MaximInterface_EXPORT virtual error_code stop(); - - MaximInterface_EXPORT virtual error_code writeByte(uint_least8_t data); - - MaximInterface_EXPORT virtual error_code - writeBlock(span<const uint_least8_t> data); - - MaximInterface_EXPORT virtual error_code readByte(AckStatus status, - uint_least8_t & data); - MaximInterface_EXPORT virtual error_code - readBlock(AckStatus status, span<uint_least8_t> data); - - protected: - MaximInterface_EXPORT virtual error_code - writePacketImpl(uint_least8_t address, span<const uint_least8_t> data, - bool sendStop); - - MaximInterface_EXPORT virtual error_code - readPacketImpl(uint_least8_t address, span<uint_least8_t> data, - bool sendStop); - - private: - DS9481P_300 * parent; - }; - - class DS2480BWithEscape : public DS2480B { - public: - DS2480BWithEscape(Sleep & sleep, Uart & uart) : DS2480B(sleep, uart) {} - - error_code escape(); - }; - - class DS9400WithEscape : public DS9400 { - public: - explicit DS9400WithEscape(Uart & uart) : DS9400(uart) {} - - error_code escape(); - }; - - enum Bus { OneWire, I2C }; - - SerialPort * serialPort; - Bus currentBus; - DS2480BWithEscape ds2480b; - OneWireMasterImpl oneWireMaster_; - DS9400WithEscape ds9400; - I2CMasterImpl i2cMaster_; - - error_code selectOneWire(); - error_code selectBus(Bus newBus); - - friend class OneWireMasterImpl; - friend class I2CMasterImpl; -}; - -} // namespace MaximInterface - -#endif
--- a/Links/I2CMaster.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include <MaximInterface/Utilities/Error.hpp> -#include "I2CMaster.hpp" - -namespace MaximInterface { - -error_code I2CMaster::writeBlock(span<const uint_least8_t> data) { - error_code result; - for (span<const uint_least8_t>::index_type i = 0; - i < data.size() && !result; ++i) { - result = writeByte(data[i]); - } - return result; -} - -error_code I2CMaster::writePacketImpl(uint_least8_t address, - span<const uint_least8_t> data, - bool sendStop) { - error_code result = start(address & 0xFE); - if (!result) { - result = writeBlock(data); - } - if (sendStop) { - error_code stopResult = stop(); - if (!result) { - result = stopResult; - } - } - return result; -} - -error_code I2CMaster::readBlock(AckStatus status, span<uint_least8_t> data) { - error_code result; - for (span<uint_least8_t>::index_type i = 0; i < data.size() && !result; ++i) { - result = readByte(i == (data.size() - 1) ? status : Ack, data[i]); - } - return result; -} - -error_code I2CMaster::readPacketImpl(uint_least8_t address, - span<uint_least8_t> data, bool sendStop) { - error_code result = start(address | 0x01); - if (!result) { - result = readBlock(Nack, data); - } - if (sendStop) { - error_code stopResult = stop(); - if (!result) { - result = stopResult; - } - } - return result; -} - -const error_category & I2CMaster::errorCategory() { - static class : public error_category { - public: - virtual const char * name() const { return "I2CMaster"; } - - virtual std::string message(int condition) const { - switch (condition) { - case NackError: - return "Nack Error"; - - default: - return defaultErrorMessage(condition); - } - } - } instance; - return instance; -} - -} // namespace MaximInterface
--- a/Links/I2CMaster.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,125 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_I2CMaster -#define MaximInterface_I2CMaster - -#include <stdint.h> -#include <MaximInterface/Utilities/Export.h> -#include <MaximInterface/Utilities/span.hpp> -#include <MaximInterface/Utilities/system_error.hpp> - -namespace MaximInterface { - -/// I2C master interface. -class I2CMaster { -public: - enum ErrorValue { - NackError = 1 ///< Transaction stopped due to a NACK from the slave device. - }; - - enum AckStatus { Nack, Ack }; - - virtual ~I2CMaster() {} - - /// @brief Send start condition and address on the bus. - /// @param address Address with R/W bit. - virtual error_code start(uint_least8_t address) = 0; - - /// Send stop condition on the bus. - virtual error_code stop() = 0; - - /// Write data byte to the bus. - virtual error_code writeByte(uint_least8_t data) = 0; - - /// Write data block to the bus. - MaximInterface_EXPORT virtual error_code - writeBlock(span<const uint_least8_t> data); - - /// @brief - /// Perform a complete write transaction on the bus with optional stop - /// condition. - /// @param address Address in 8-bit format. - /// @param data Data to write to the bus. - /// @param sendStop - /// True to send a stop condition or false to set up a repeated start. - error_code writePacket(uint_least8_t address, span<const uint_least8_t> data, - bool sendStop = true) { - return writePacketImpl(address, data, sendStop); - } - - /// @brief Read data byte from the bus. - /// @param status Determines whether an ACK or NACK is sent after reading. - /// @param[out] data Data read from the bus if successful. - virtual error_code readByte(AckStatus status, uint_least8_t & data) = 0; - - /// @brief Read data block from the bus. - /// @param status Determines whether an ACK or NACK is sent after reading. - /// @param[out] data Data read from the bus if successful. - MaximInterface_EXPORT virtual error_code - readBlock(AckStatus status, span<uint_least8_t> data); - - /// @brief - /// Perform a complete read transaction on the bus with optional stop - /// condition. - /// @param address Address in 8-bit format. - /// @param[out] data Data read from the bus if successful. - /// @param sendStop - /// True to send a stop condition or false to set up a repeated start. - error_code readPacket(uint_least8_t address, span<uint_least8_t> data, - bool sendStop = true) { - return readPacketImpl(address, data, sendStop); - } - - MaximInterface_EXPORT static const error_category & errorCategory(); - -protected: - MaximInterface_EXPORT virtual error_code - writePacketImpl(uint_least8_t address, span<const uint_least8_t> data, - bool sendStop); - - MaximInterface_EXPORT virtual error_code - readPacketImpl(uint_least8_t address, span<uint_least8_t> data, - bool sendStop); -}; - -inline error_code make_error_code(I2CMaster::ErrorValue e) { - return error_code(e, I2CMaster::errorCategory()); -} - -inline error_condition make_error_condition(I2CMaster::ErrorValue e) { - return error_condition(e, I2CMaster::errorCategory()); -} - -} // namespace MaximInterface - -#endif
--- a/Links/I2CMasterDecorator.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include "I2CMasterDecorator.hpp" - -namespace MaximInterface { - -error_code I2CMasterDecorator::start(uint_least8_t address) { - return master->start(address); -} - -error_code I2CMasterDecorator::stop() { return master->stop(); } - -error_code I2CMasterDecorator::writeByte(uint_least8_t data) { - return master->writeByte(data); -} - -error_code I2CMasterDecorator::writeBlock(span<const uint_least8_t> data) { - return master->writeBlock(data); -} - -error_code I2CMasterDecorator::writePacketImpl(uint_least8_t address, - span<const uint_least8_t> data, - bool sendStop) { - return master->writePacket(address, data, sendStop); -} - -error_code I2CMasterDecorator::readByte(AckStatus status, - uint_least8_t & data) { - return master->readByte(status, data); -} - -error_code I2CMasterDecorator::readBlock(AckStatus status, - span<uint_least8_t> data) { - return master->readBlock(status, data); -} - -error_code I2CMasterDecorator::readPacketImpl(uint_least8_t address, - span<uint_least8_t> data, - bool sendStop) { - return master->readPacket(address, data, sendStop); -} - -} // namespace MaximInterface
--- a/Links/I2CMasterDecorator.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_I2CMasterDecorator -#define MaximInterface_I2CMasterDecorator - -#include <MaximInterface/Utilities/Export.h> -#include "I2CMaster.hpp" - -namespace MaximInterface { - -class I2CMasterDecorator : public I2CMaster { -protected: - explicit I2CMasterDecorator(I2CMaster & master) : master(&master) {} - -public: - void setMaster(I2CMaster & master) { this->master = &master; } - - MaximInterface_EXPORT virtual error_code start(uint_least8_t address); - - MaximInterface_EXPORT virtual error_code stop(); - - MaximInterface_EXPORT virtual error_code writeByte(uint_least8_t data); - - MaximInterface_EXPORT virtual error_code - writeBlock(span<const uint_least8_t> data); - - MaximInterface_EXPORT virtual error_code readByte(AckStatus status, - uint_least8_t & data); - - MaximInterface_EXPORT virtual error_code - readBlock(AckStatus status, span<uint_least8_t> data); - -protected: - MaximInterface_EXPORT virtual error_code - writePacketImpl(uint_least8_t address, span<const uint_least8_t> data, - bool sendStop); - - MaximInterface_EXPORT virtual error_code - readPacketImpl(uint_least8_t address, span<uint_least8_t> data, - bool sendStop); - -private: - I2CMaster * master; -}; - -} // namespace MaximInterface - -#endif
--- a/Links/LoggingI2CMaster.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include <utility> -#include <MaximInterface/Utilities/HexConversions.hpp> -#include "LoggingI2CMaster.hpp" - -using std::string; - -namespace MaximInterface { - -static const char startString[] = "S "; -static const char stopString[] = "P"; - -static string formatDataString(span<const uint_least8_t> data, bool read) { - string dataBuilder; - for (span<const uint_least8_t>::index_type i = 0; i < data.size(); ++i) { - if (read) { - dataBuilder.append(1, '['); - } - dataBuilder.append(byteArrayToHexString(data.subspan(i, 1))); - if (read) { - dataBuilder.append(1, ']'); - } - dataBuilder.append(1, ' '); - } - return dataBuilder; -} - -void LoggingI2CMaster::tryWriteMessage() { - if (writeMessage) { - writeMessage(messageBuilder); - } - messageBuilder.clear(); -} - -error_code LoggingI2CMaster::start(uint_least8_t address) { - messageBuilder.append(startString); - messageBuilder.append(formatDataString(make_span(&address, 1), false)); - return I2CMasterDecorator::start(address); -} - -error_code LoggingI2CMaster::stop() { - messageBuilder.append(stopString); - tryWriteMessage(); - return I2CMasterDecorator::stop(); -} - -error_code LoggingI2CMaster::writeByte(uint_least8_t data) { - messageBuilder.append(formatDataString(make_span(&data, 1), false)); - return I2CMasterDecorator::writeByte(data); -} - -error_code LoggingI2CMaster::writeBlock(span<const uint_least8_t> data) { - messageBuilder.append(formatDataString(data, false)); - return I2CMasterDecorator::writeBlock(data); -} - -error_code LoggingI2CMaster::writePacketImpl(uint_least8_t address, - span<const uint_least8_t> data, - bool sendStop) { - messageBuilder.append(startString); - messageBuilder.append(formatDataString(make_span(&address, 1), false)); - error_code result = - I2CMasterDecorator::writePacketImpl(address, data, sendStop); - if (!result) { - messageBuilder.append(formatDataString(data, false)); - } - if (sendStop || result) { - messageBuilder.append(stopString); - tryWriteMessage(); - } - return result; -} - -error_code LoggingI2CMaster::readByte(AckStatus status, uint_least8_t & data) { - error_code result = I2CMasterDecorator::readByte(status, data); - if (!result) { - messageBuilder.append(formatDataString(make_span(&data, 1), true)); - } - return result; -} - -error_code LoggingI2CMaster::readBlock(AckStatus status, - span<uint_least8_t> data) { - error_code result = I2CMasterDecorator::readBlock(status, data); - if (!result) { - messageBuilder.append(formatDataString(data, true)); - } - return result; -} - -error_code LoggingI2CMaster::readPacketImpl(uint_least8_t address, - span<uint_least8_t> data, - bool sendStop) { - messageBuilder.append(startString); - messageBuilder.append(formatDataString(make_span(&address, 1), false)); - error_code result = - I2CMasterDecorator::readPacketImpl(address, data, sendStop); - if (!result) { - messageBuilder.append(formatDataString(data, true)); - } - if (sendStop || result) { - messageBuilder.append(stopString); - tryWriteMessage(); - } - return result; -} - -} // namespace MaximInterface
--- a/Links/LoggingI2CMaster.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_LoggingI2CMaster -#define MaximInterface_LoggingI2CMaster - -#include <string> -#include <MaximInterface/Links/I2CMasterDecorator.hpp> -#include <MaximInterface/Utilities/Export.h> -#include <MaximInterface/Utilities/WriteMessage.hpp> - -namespace MaximInterface { - -class LoggingI2CMaster : public I2CMasterDecorator { -public: - explicit LoggingI2CMaster( - I2CMaster & i2c, const WriteMessage & writeMessage = WriteMessage()) - : I2CMasterDecorator(i2c), writeMessage(writeMessage), messageBuilder() {} - - void setWriteMessage(const WriteMessage & writeMessage) { - this->writeMessage = writeMessage; - } - - MaximInterface_EXPORT virtual error_code start(uint_least8_t address); - - MaximInterface_EXPORT virtual error_code stop(); - - MaximInterface_EXPORT virtual error_code writeByte(uint_least8_t data); - - MaximInterface_EXPORT virtual error_code - writeBlock(span<const uint_least8_t> data); - - MaximInterface_EXPORT virtual error_code readByte(AckStatus status, - uint_least8_t & data); - MaximInterface_EXPORT virtual error_code - readBlock(AckStatus status, span<uint_least8_t> data); - -protected: - MaximInterface_EXPORT virtual error_code - writePacketImpl(uint_least8_t address, span<const uint_least8_t> data, - bool sendStop); - - MaximInterface_EXPORT virtual error_code - readPacketImpl(uint_least8_t address, span<uint_least8_t> data, - bool sendStop); - -private: - void tryWriteMessage(); - - WriteMessage writeMessage; - std::string messageBuilder; -}; - -} // namespace MaximInterface - -#endif
--- a/Links/LoggingOneWireMaster.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,144 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include <MaximInterface/Utilities/HexConversions.hpp> -#include "LoggingOneWireMaster.hpp" - -using std::string; - -namespace MaximInterface { - -static const char strongLevelString[] = "<SP_ON>"; - -static string formatDataString(span<const uint_least8_t> data, bool read) { - string dataBuilder; - for (span<const uint_least8_t>::index_type i = 0; i < data.size(); ++i) { - if (read) { - dataBuilder.append(1, '['); - } - dataBuilder.append(byteArrayToHexString(data.subspan(i, 1))); - if (read) { - dataBuilder.append(1, ']'); - } - dataBuilder.append(1, ' '); - } - return dataBuilder; -} - -void LoggingOneWireMaster::tryWriteMessage(const std::string & message) { - if (writeMessage) { - writeMessage(message); - } -} - -error_code LoggingOneWireMaster::reset() { - error_code result = OneWireMasterDecorator::reset(); - tryWriteMessage(!result ? "RP" : "RN"); - return result; -} - -error_code LoggingOneWireMaster::writeByteSetLevel(uint_least8_t sendByte, - Level afterLevel) { - tryWriteMessage(formatDataString(make_span(&sendByte, 1), false)); - if (afterLevel == StrongLevel) { - tryWriteMessage(strongLevelString); - } - return OneWireMasterDecorator::writeByteSetLevel(sendByte, afterLevel); -} - -error_code LoggingOneWireMaster::readByteSetLevel(uint_least8_t & recvByte, - Level afterLevel) { - error_code result = - OneWireMasterDecorator::readByteSetLevel(recvByte, afterLevel); - if (!result) { - tryWriteMessage(formatDataString(make_span(&recvByte, 1), true)); - if (afterLevel == StrongLevel) { - tryWriteMessage(strongLevelString); - } - } - return result; -} - -error_code LoggingOneWireMaster::writeBlock(span<const uint_least8_t> sendBuf) { - tryWriteMessage(formatDataString(sendBuf, false)); - return OneWireMasterDecorator::writeBlock(sendBuf); -} - -error_code LoggingOneWireMaster::readBlock(span<uint_least8_t> recvBuf) { - error_code result = OneWireMasterDecorator::readBlock(recvBuf); - if (!result) { - tryWriteMessage(formatDataString(recvBuf, true)); - } - return result; -} - -error_code LoggingOneWireMaster::setSpeed(Speed newSpeed) { - error_code result = OneWireMasterDecorator::setSpeed(newSpeed); - if (!result) { - string newSpeedString; - switch (newSpeed) { - case StandardSpeed: - newSpeedString = "<STD>"; - break; - - case OverdriveSpeed: - newSpeedString = "<OVR>"; - break; - } - if (!newSpeedString.empty()) { - tryWriteMessage(newSpeedString); - } - } - return result; -} - -error_code LoggingOneWireMaster::setLevel(Level newLevel) { - error_code result = OneWireMasterDecorator::setLevel(newLevel); - if (!result) { - string newLevelString; - switch (newLevel) { - case NormalLevel: - newLevelString = "<SP_OFF>"; - break; - - case StrongLevel: - newLevelString = strongLevelString; - break; - } - if (!newLevelString.empty()) { - tryWriteMessage(newLevelString); - } - } - return result; -} - -} // namespace MaximInterface
--- a/Links/LoggingOneWireMaster.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_LoggingOneWireMaster -#define MaximInterface_LoggingOneWireMaster - -#include <string> -#include <MaximInterface/Links/OneWireMasterDecorator.hpp> -#include <MaximInterface/Utilities/Export.h> -#include <MaximInterface/Utilities/WriteMessage.hpp> - -namespace MaximInterface { - -class LoggingOneWireMaster : public OneWireMasterDecorator { -public: - explicit LoggingOneWireMaster( - OneWireMaster & master, - const WriteMessage & writeMessage = WriteMessage()) - : OneWireMasterDecorator(master), writeMessage(writeMessage) {} - - void setWriteMessage(const WriteMessage & writeMessage) { - this->writeMessage = writeMessage; - } - - MaximInterface_EXPORT virtual error_code reset(); - - MaximInterface_EXPORT virtual error_code - writeByteSetLevel(uint_least8_t sendByte, Level afterLevel); - - MaximInterface_EXPORT virtual error_code - readByteSetLevel(uint_least8_t & recvByte, Level afterLevel); - - MaximInterface_EXPORT virtual error_code - writeBlock(span<const uint_least8_t> sendBuf); - - MaximInterface_EXPORT virtual error_code - readBlock(span<uint_least8_t> recvBuf); - - MaximInterface_EXPORT virtual error_code setSpeed(Speed newSpeed); - - MaximInterface_EXPORT virtual error_code setLevel(Level newLevel); - -private: - void tryWriteMessage(const std::string & message); - - WriteMessage writeMessage; -}; - -} // namespace MaximInterface - -#endif
--- a/Links/LoggingSleep.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include <sstream> -#include "LoggingSleep.hpp" - -namespace MaximInterface { - -void LoggingSleep::invoke(int ms) const { - if (writeMessage) { - std::ostringstream message; - message << "<DELAY" << ms << '>'; - writeMessage(message.str()); - } - SleepDecorator::invoke(ms); -} - -} // namespace MaximInterface
--- a/Links/LoggingSleep.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_LoggingSleep -#define MaximInterface_LoggingSleep - -#include <MaximInterface/Utilities/Export.h> -#include <MaximInterface/Utilities/WriteMessage.hpp> -#include "SleepDecorator.hpp" - -namespace MaximInterface { - -class LoggingSleep : public SleepDecorator { -public: - LoggingSleep(Sleep & sleep, - const WriteMessage & writeMessage = WriteMessage()) - : SleepDecorator(sleep), writeMessage(writeMessage) {} - - void setWriteMessage(const WriteMessage & writeMessage) { - this->writeMessage = writeMessage; - } - - MaximInterface_EXPORT virtual void invoke(int ms) const; - -private: - WriteMessage writeMessage; -}; - -} // namespace MaximInterface - -#endif
--- a/Links/OneWireMaster.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,130 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include <MaximInterface/Utilities/Error.hpp> -#include "OneWireMaster.hpp" - -namespace MaximInterface { - -static const int maxBitNum = 7; - -error_code OneWireMaster::writeByteSetLevel(uint_least8_t sendByte, - Level afterLevel) { - error_code result; - for (int bitNum = 0; (bitNum <= maxBitNum) && !result; ++bitNum) { - result = writeBitSetLevel(((sendByte >> bitNum) & 1) == 1, - (bitNum == maxBitNum) ? afterLevel : NormalLevel); - } - return result; -} - -error_code OneWireMaster::readByteSetLevel(uint_least8_t & recvByte, - Level afterLevel) { - recvByte = 0; - error_code result; - for (int bitNum = 0; bitNum <= maxBitNum; ++bitNum) { - bool recvBit; - result = readBitSetLevel(recvBit, - (bitNum == maxBitNum) ? afterLevel : NormalLevel); - if (result) { - break; - } - if (recvBit) { - recvByte |= (1 << bitNum); - } - } - return result; -} - -error_code OneWireMaster::writeBlock(span<const uint_least8_t> sendBuf) { - error_code result; - for (span<const uint_least8_t>::index_type i = 0; - i < sendBuf.size() && !result; ++i) { - result = writeByte(sendBuf[i]); - } - return result; -} - -error_code OneWireMaster::readBlock(span<uint_least8_t> recvBuf) { - error_code result; - for (span<uint_least8_t>::index_type i = 0; i < recvBuf.size() && !result; - ++i) { - result = readByte(recvBuf[i]); - } - return result; -} - -error_code OneWireMaster::triplet(TripletData & data) { - error_code result = readBit(data.readBit); - if (!result) { - result = readBit(data.readBitComplement); - } - if (!result) { - if (data.readBit) { - data.writeBit = 1; - } else if (data.readBitComplement) { - data.writeBit = 0; - } - // else: use data.writeBit parameter - result = writeBit(data.writeBit); - } - return result; -} - -const error_category & OneWireMaster::errorCategory() { - static class : public error_category { - public: - virtual const char * name() const { return "OneWireMaster"; } - - virtual std::string message(int condition) const { - switch (condition) { - case NoSlaveError: - return "No Slave Error"; - - case ShortDetectedError: - return "Short Detected Error"; - - case InvalidSpeedError: - return "Invalid Speed Error"; - - case InvalidLevelError: - return "Invalid Level Error"; - - default: - return defaultErrorMessage(condition); - } - } - } instance; - return instance; -} - -} // namespace MaximInterface
--- a/Links/OneWireMaster.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,190 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_OneWireMaster -#define MaximInterface_OneWireMaster - -#include <stdint.h> -#include <MaximInterface/Utilities/Export.h> -#include <MaximInterface/Utilities/span.hpp> -#include <MaximInterface/Utilities/system_error.hpp> - -namespace MaximInterface { - -/// 1-Wire master interface. -class OneWireMaster { -public: - /// Speed of the 1-Wire bus. - enum Speed { StandardSpeed = 0x00, OverdriveSpeed = 0x01 }; - - /// Level of the 1-Wire bus. - enum Level { NormalLevel = 0x00, StrongLevel = 0x02 }; - - /// Result of all 1-Wire commands. - enum ErrorValue { - NoSlaveError = 1, ///< Slave not detected, typically due to no presence pulse. - ShortDetectedError, - InvalidSpeedError, - InvalidLevelError - }; - - struct TripletData { - bool writeBit; - bool readBit; - bool readBitComplement; - }; - - virtual ~OneWireMaster() {} - - /// @brief - /// Reset all of the devices on the 1-Wire bus and check for a presence pulse. - /// @returns - /// NoSlaveError if reset was performed but no presence pulse was detected. - virtual error_code reset() = 0; - - /// @brief - /// Send and receive one bit of communication and set a new level on the - /// 1-Wire bus. - /// @param[in,out] sendRecvBit - /// Input containing the bit to send and output containing the received bit. - /// @param afterLevel Level to set the 1-Wire bus to after communication. - virtual error_code touchBitSetLevel(bool & sendRecvBit, Level afterLevel) = 0; - - /// @brief - /// Send one byte of communication and set a new level on the 1-Wire bus. - /// @param sendByte Byte to send on the 1-Wire bus. - /// @param afterLevel Level to set the 1-Wire bus to after communication. - MaximInterface_EXPORT virtual error_code - writeByteSetLevel(uint_least8_t sendByte, Level afterLevel); - - /// @brief - /// Receive one byte of communication and set a new level on the 1-Wire bus. - /// @param recvByte Buffer to receive the data from the 1-Wire bus. - /// @param afterLevel Level to set the 1-Wire bus to after communication. - MaximInterface_EXPORT virtual error_code - readByteSetLevel(uint_least8_t & recvByte, Level afterLevel); - - /// @brief Send a block of communication on the 1-Wire bus. - /// @param[in] sendBuf Buffer to send on the 1-Wire bus. - MaximInterface_EXPORT virtual error_code - writeBlock(span<const uint_least8_t> sendBuf); - - /// @brief Receive a block of communication on the 1-Wire bus. - /// @param[out] recvBuf Buffer to receive the data from the 1-Wire bus. - MaximInterface_EXPORT virtual error_code - readBlock(span<uint_least8_t> recvBuf); - - /// Set the 1-Wire bus communication speed. - virtual error_code setSpeed(Speed newSpeed) = 0; - - /// Set the 1-Wire bus level. - virtual error_code setLevel(Level newLevel) = 0; - - /// @brief 1-Wire Triplet operation. - /// @details Perform one bit of a 1-Wire search. This command - /// does two read bits and one write bit. The write bit is either - /// the default direction (all devices have same bit) or in case - /// of a discrepancy, the data.writeBit parameter is used. - /// @param[in,out] data - /// Input with desired writeBit in case both read bits are zero. - /// Output with all data fields set. - MaximInterface_EXPORT virtual error_code triplet(TripletData & data); - - /// @brief - /// Send one bit of communication and set a new level on the 1-Wire bus. - /// @param sendBit Bit to send on the 1-Wire bus. - /// @param afterLevel Level to set the 1-Wire bus to after communication. - error_code writeBitSetLevel(bool sendBit, Level afterLevel) { - return touchBitSetLevel(sendBit, afterLevel); - } - - /// @brief - /// Receive one bit of communication and set a new level on the 1-Wire bus. - /// @param[out] recvBit Received data from the 1-Wire bus. - /// @param afterLevel Level to set the 1-Wire bus to after communication. - error_code readBitSetLevel(bool & recvBit, Level afterLevel) { - recvBit = 1; - return touchBitSetLevel(recvBit, afterLevel); - } - - // Alternate forms of the read and write functions. - - error_code touchBit(bool & sendRecvBit) { - return touchBitSetLevel(sendRecvBit, NormalLevel); - } - - error_code writeBit(bool sendBit) { - return writeBitSetLevel(sendBit, NormalLevel); - } - - error_code readBit(bool & recvBit) { - return readBitSetLevel(recvBit, NormalLevel); - } - - error_code writeBitPower(bool sendBit) { - return writeBitSetLevel(sendBit, StrongLevel); - } - - error_code readBitPower(bool & recvBit) { - return readBitSetLevel(recvBit, StrongLevel); - } - - error_code writeByte(uint_least8_t sendByte) { - return writeByteSetLevel(sendByte, NormalLevel); - } - - error_code readByte(uint_least8_t & recvByte) { - return readByteSetLevel(recvByte, NormalLevel); - } - - error_code writeBytePower(uint_least8_t sendByte) { - return writeByteSetLevel(sendByte, StrongLevel); - } - - error_code readBytePower(uint_least8_t & recvByte) { - return readByteSetLevel(recvByte, StrongLevel); - } - - MaximInterface_EXPORT static const error_category & errorCategory(); -}; - -inline error_code make_error_code(OneWireMaster::ErrorValue e) { - return error_code(e, OneWireMaster::errorCategory()); -} - -inline error_condition make_error_condition(OneWireMaster::ErrorValue e) { - return error_condition(e, OneWireMaster::errorCategory()); -} - -} // namespace MaximInterface - -#endif
--- a/Links/OneWireMasterDecorator.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include "OneWireMasterDecorator.hpp" - -namespace MaximInterface { - -error_code OneWireMasterDecorator::reset() { return master->reset(); } - -error_code OneWireMasterDecorator::touchBitSetLevel(bool & sendRecvBit, - Level afterLevel) { - return master->touchBitSetLevel(sendRecvBit, afterLevel); -} - -error_code OneWireMasterDecorator::writeByteSetLevel(uint_least8_t sendByte, - Level afterLevel) { - return master->writeByteSetLevel(sendByte, afterLevel); -} - -error_code OneWireMasterDecorator::readByteSetLevel(uint_least8_t & recvByte, - Level afterLevel) { - return master->readByteSetLevel(recvByte, afterLevel); -} - -error_code -OneWireMasterDecorator::writeBlock(span<const uint_least8_t> sendBuf) { - return master->writeBlock(sendBuf); -} - -error_code OneWireMasterDecorator::readBlock(span<uint_least8_t> recvBuf) { - return master->readBlock(recvBuf); -} - -error_code OneWireMasterDecorator::setSpeed(Speed newSpeed) { - return master->setSpeed(newSpeed); -} - -error_code OneWireMasterDecorator::setLevel(Level newLevel) { - return master->setLevel(newLevel); -} - -error_code OneWireMasterDecorator::triplet(TripletData & data) { - return master->triplet(data); -} - -} // namespace MaximInterface
--- a/Links/OneWireMasterDecorator.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_OneWireMasterDecorator -#define MaximInterface_OneWireMasterDecorator - -#include <MaximInterface/Utilities/Export.h> -#include "OneWireMaster.hpp" - -namespace MaximInterface { - -class OneWireMasterDecorator : public OneWireMaster { -protected: - explicit OneWireMasterDecorator(OneWireMaster & master) : master(&master) {} - -public: - void setMaster(OneWireMaster & master) { this->master = &master; } - - MaximInterface_EXPORT virtual error_code reset(); - - MaximInterface_EXPORT virtual error_code touchBitSetLevel(bool & sendRecvBit, - Level afterLevel); - - MaximInterface_EXPORT virtual error_code - writeByteSetLevel(uint_least8_t sendByte, Level afterLevel); - - MaximInterface_EXPORT virtual error_code - readByteSetLevel(uint_least8_t & recvByte, Level afterLevel); - - MaximInterface_EXPORT virtual error_code - writeBlock(span<const uint_least8_t> sendBuf); - - MaximInterface_EXPORT virtual error_code - readBlock(span<uint_least8_t> recvBuf); - - MaximInterface_EXPORT virtual error_code setSpeed(Speed newSpeed); - - MaximInterface_EXPORT virtual error_code setLevel(Level newLevel); - - MaximInterface_EXPORT virtual error_code triplet(TripletData & data); - -private: - OneWireMaster * master; -}; - -} // namespace MaximInterface - -#endif
--- a/Links/RomCommands.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,210 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include "RomCommands.hpp" - -namespace MaximInterface { - -enum RomCmd { - ReadRomCmd = 0x33, - MatchRomCmd = 0x55, - SearchRomCmd = 0xF0, - SkipRomCmd = 0xCC, - ResumeRomCmd = 0xA5, - OverdriveSkipRomCmd = 0x3C, - OverdriveMatchRomCmd = 0x69 -}; - -void skipCurrentFamily(SearchRomState & searchState) { - // Set the last discrepancy to last family discrepancy. - searchState.lastDiscrepancy = searchState.lastFamilyDiscrepancy; - // Clear the last family discrepancy. - searchState.lastFamilyDiscrepancy = 0; - // Check for end of list. - if (searchState.lastDiscrepancy == 0) { - searchState.lastDevice = true; - } -} - -error_code verifyRom(OneWireMaster & master, RomId::const_span romId) { - SearchRomState searchState(romId); - error_code result = searchRom(master, searchState); - if (result) { - return result; - } - // Check if same device found. - if (romId != make_span(searchState.romId)) { - result = make_error_code(OneWireMaster::NoSlaveError); - } - return result; -} - -error_code readRom(OneWireMaster & master, RomId::span romId) { - error_code result = master.reset(); - if (result) { - return result; - } - result = master.writeByte(ReadRomCmd); - if (result) { - return result; - } - result = master.readBlock(romId); - if (result) { - return result; - } - if (!valid(romId)) { - result = make_error_code(OneWireMaster::NoSlaveError); - } - return result; -} - -error_code skipRom(OneWireMaster & master) { - error_code result = master.reset(); - if (result) { - return result; - } - result = master.writeByte(SkipRomCmd); - return result; -} - -error_code matchRom(OneWireMaster & master, RomId::const_span romId) { - error_code result = master.reset(); - if (result) { - return result; - } - result = master.writeByte(MatchRomCmd); - if (result) { - return result; - } - result = master.writeBlock(romId); - return result; -} - -error_code overdriveSkipRom(OneWireMaster & master) { - error_code result = master.reset(); - if (result) { - return result; - } - result = master.writeByte(OverdriveSkipRomCmd); - if (result) { - return result; - } - result = master.setSpeed(OneWireMaster::OverdriveSpeed); - return result; -} - -error_code overdriveMatchRom(OneWireMaster & master, RomId::const_span romId) { - error_code result = master.reset(); - if (result) { - return result; - } - result = master.writeByte(OverdriveMatchRomCmd); - if (result) { - return result; - } - result = master.setSpeed(OneWireMaster::OverdriveSpeed); - if (result) { - return result; - } - result = master.writeBlock(romId); - return result; -} - -error_code resumeRom(OneWireMaster & master) { - error_code result = master.reset(); - if (result) { - return result; - } - result = master.writeByte(ResumeRomCmd); - return result; -} - -error_code searchRom(OneWireMaster & master, SearchRomState & searchState) { - if (searchState.lastDevice) { - searchState = SearchRomState(); - } - - error_code result = master.reset(); - if (result) { - return result; - } - result = master.writeByte(SearchRomCmd); - if (result) { - return result; - } - - SearchRomState newSearchState; - newSearchState.lastFamilyDiscrepancy = searchState.lastFamilyDiscrepancy; - for (int idBitNumber = 1; idBitNumber <= 64; ++idBitNumber) { - const int idByteNumber = (idBitNumber - 1) / 8; - const unsigned int idBitMask = 1 << ((idBitNumber - 1) % 8); - - OneWireMaster::TripletData tripletData; - if (idBitNumber == searchState.lastDiscrepancy) { - tripletData.writeBit = 1; - } else if (idBitNumber > searchState.lastDiscrepancy) { - tripletData.writeBit = 0; - } else { // idBitNumber < searchState.lastDiscrepancy - tripletData.writeBit = - (searchState.romId[idByteNumber] & idBitMask) == idBitMask; - } - - result = master.triplet(tripletData); - if (result) { - return result; - } - if (tripletData.readBit && tripletData.readBitComplement) { - return make_error_code(OneWireMaster::NoSlaveError); - } - - if (tripletData.writeBit) { - newSearchState.romId[idByteNumber] |= idBitMask; - } else if (!tripletData.readBit && !tripletData.readBitComplement) { - newSearchState.lastDiscrepancy = idBitNumber; - if (idBitNumber <= 8) { - newSearchState.lastFamilyDiscrepancy = idBitNumber; - } - } - } - - if (valid(newSearchState.romId)) { - if (newSearchState.lastDiscrepancy == 0) { - newSearchState.lastDevice = true; - } - searchState = newSearchState; - } else { - result = make_error_code(OneWireMaster::NoSlaveError); - } - return result; -} - -} // namespace MaximInterface
--- a/Links/RomCommands.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,135 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -/// @file -/// @brief ROM Commands for enumerating and selecting 1-Wire devices. - -#ifndef MaximInterface_RomCommands -#define MaximInterface_RomCommands - -#include <stdint.h> -#include <MaximInterface/Utilities/Export.h> -#include <MaximInterface/Utilities/RomId.hpp> -#include "OneWireMaster.hpp" - -namespace MaximInterface { - -/// State used by Search ROM command. -struct SearchRomState { - RomId::array romId; - int_least8_t lastDiscrepancy; - int_least8_t lastFamilyDiscrepancy; - bool lastDevice; - - SearchRomState() - : romId(), lastDiscrepancy(0), lastFamilyDiscrepancy(0), - lastDevice(false) {} - - explicit SearchRomState(RomId::const_span romId) - : lastDiscrepancy(64), lastFamilyDiscrepancy(0), lastDevice(false) { - copy(romId, make_span(this->romId)); - } - - explicit SearchRomState(RomId::element familyCode) - : romId(), lastDiscrepancy(64), lastFamilyDiscrepancy(0), - lastDevice(false) { - setFamilyCode(romId, familyCode); - } -}; - -/// @brief -/// Set the search state to skip the current device family on the next -/// Search ROM command. -MaximInterface_EXPORT void skipCurrentFamily(SearchRomState & searchState); - -/// Verify that the device with the specified ROM ID is present. -MaximInterface_EXPORT error_code verifyRom(OneWireMaster & master, - RomId::const_span romId); - -/// @brief Use Read ROM command to read ROM ID from device on bus. -/// @note -/// Only use this command with a single-drop bus. -/// Data collisions will occur if there is more than one device on the bus. -/// @param master 1-Wire master for operation. -/// @param[out] romId ROM ID read from device. -MaximInterface_EXPORT error_code readRom(OneWireMaster & master, - RomId::span romId); - -/// @brief Issue Skip ROM command on bus. -/// @note -/// Only use this command with a single-drop bus. -/// Data collisions will occur if there is more than one device on the bus. -MaximInterface_EXPORT error_code skipRom(OneWireMaster & master); - -/// @brief Use the Match ROM command to select the device by its known ID. -/// @note -/// This command causes all devices supporting Overdrive mode to switch to -/// Overdrive timing. -/// @param master 1-Wire master for operation. -/// @param[in] romId ROM ID of device to select. -MaximInterface_EXPORT error_code matchRom(OneWireMaster & master, - RomId::const_span romId); - -/// @brief Issue Overdrive Skip ROM command on bus. -/// @note -/// This command causes all devices supporting Overdrive mode to switch to -/// Overdrive timing. -/// @note -/// Only use this command with a single-drop bus. -/// Data collisions will occur if there is more than one device on the bus. -MaximInterface_EXPORT error_code overdriveSkipRom(OneWireMaster & master); - -/// @brief -/// Use the Overdrive Match ROM command to select the device by its known ID. -/// @param master 1-Wire master for operation. -/// @param[in] romId ROM ID of device to select. -MaximInterface_EXPORT error_code overdriveMatchRom(OneWireMaster & master, - RomId::const_span romId); - -/// @brief Perform a Resume ROM command on bus. -/// @details -/// Resumes communication with the last device selected through a Match ROM or -/// Search ROM operation. -MaximInterface_EXPORT error_code resumeRom(OneWireMaster & master); - -/// @brief Find device on the 1-Wire bus. -/// @details -/// This command uses the Search ROM command to enumerate all 1-Wire devices in -/// sequence. Begin with a new search state and continue using the same search -/// state until the last device flag is set which indicates that all devices -/// have been discovered. -MaximInterface_EXPORT error_code searchRom(OneWireMaster & master, - SearchRomState & searchState); - -} // namespace MaximInterface - -#endif
--- a/Links/RunCommand.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,210 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include <MaximInterface/Utilities/crc.hpp> -#include <MaximInterface/Utilities/Error.hpp> -#include "I2CMaster.hpp" -#include "OneWireMaster.hpp" -#include "Sleep.hpp" -#include "RunCommand.hpp" - -namespace MaximInterface { - -const error_category & RunCommandWithOneWireMaster::errorCategory() { - static class : public error_category { - public: - virtual const char * name() const { return "RunCommandWithOneWireMaster"; } - - virtual std::string message(int condition) const { - switch (condition) { - case CrcError: - return "CRC Error"; - - case InvalidResponseError: - return "Invalid Response Error"; - } - return defaultErrorMessage(condition); - } - } instance; - return instance; -} - -error_code RunCommandWithOneWireMaster:: -operator()(span<const uint_least8_t> command, int delayTime, - span<uint_least8_t> & response) const { - // Write command. - error_code result = selectRom(*master); - if (result) { - return result; - } - uint_least8_t xpcBuffer[2] = {0x66, - static_cast<uint_least8_t>(command.size())}; - result = master->writeBlock(xpcBuffer); - if (result) { - return result; - } - result = master->writeBlock(command); - if (result) { - return result; - } - uint_fast16_t expectedCrc = - calculateCrc16(command, calculateCrc16(xpcBuffer)) ^ 0xFFFFU; - result = master->readBlock(xpcBuffer); - if (result) { - return result; - } - if (expectedCrc != - ((static_cast<uint_fast16_t>(xpcBuffer[1]) << 8) | xpcBuffer[0])) { - return make_error_code(CrcError); - } - result = master->writeBytePower(0xAA); - if (result) { - return result; - } - - // Wait for device to process. - sleep->invoke(delayTime); - - // Read response. - result = master->setLevel(OneWireMaster::NormalLevel); - if (result) { - return result; - } - result = master->readBlock(xpcBuffer); - if (result) { - return result; - } - if (xpcBuffer[1] > response.size()) { - return make_error_code(InvalidResponseError); - } - response = response.first(xpcBuffer[1]); - result = master->readBlock(response); - if (result) { - return result; - } - expectedCrc = - calculateCrc16(response, calculateCrc16(make_span(xpcBuffer + 1, 1))) ^ - 0xFFFFU; - result = master->readBlock(xpcBuffer); - if (result) { - return result; - } - if (expectedCrc != - ((static_cast<uint_fast16_t>(xpcBuffer[1]) << 8) | xpcBuffer[0])) { - return make_error_code(CrcError); - } - return result; -} - -const error_category & RunCommandWithI2CMaster::errorCategory() { - static class : public error_category { - public: - virtual const char * name() const { return "RunCommandWithI2CMaster"; } - - virtual std::string message(int condition) const { - switch (condition) { - case InvalidResponseError: - return "Invalid Response Error"; - } - return defaultErrorMessage(condition); - } - } instance; - return instance; -} - -error_code RunCommandWithI2CMaster:: -operator()(span<const uint_least8_t> command, int delayTime, - span<uint_least8_t> & response) const { - // Write command. - error_code result = master->start(address_); - if (result == make_error_condition(I2CMaster::NackError) && address_ != 0) { - result = master->start(0); - } - if (result) { - master->stop(); - return result; - } - if (!command.empty()) { - result = master->writeByte(command[0]); - if (result) { - master->stop(); - return result; - } - command = command.subspan(1); - if (!command.empty()) { - result = master->writeByte(command.size()); - if (result) { - master->stop(); - return result; - } - result = master->writeBlock(command); - if (result) { - master->stop(); - return result; - } - } - } - result = master->stop(); - if (result) { - return result; - } - - // Wait for device to process. - sleep->invoke(delayTime); - - // Read response. - result = master->start(address_ | 1); - if (result) { - master->stop(); - return result; - } - uint_least8_t length; - result = master->readByte(I2CMaster::Ack, length); - if (result) { - master->stop(); - return result; - } - if (length > response.size()) { - master->stop(); - return make_error_code(InvalidResponseError); - } - response = response.first(length); - result = master->readBlock(I2CMaster::Nack, response); - if (result) { - master->stop(); - return result; - } - result = master->stop(); - return result; -} - -} // namespace MaximInterface
--- a/Links/RunCommand.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_RunCommand -#define MaximInterface_RunCommand - -#include <MaximInterface/Utilities/Export.h> -#include <MaximInterface/Utilities/Function.hpp> -#include <MaximInterface/Utilities/span.hpp> -#include <MaximInterface/Utilities/system_error.hpp> -#include "SelectRom.hpp" - -namespace MaximInterface { - -class I2CMaster; -class OneWireMaster; -class Sleep; - -typedef Function<error_code(span<const uint_least8_t>, int, - span<uint_least8_t> &)> - RunCommand; - -class RunCommandWithOneWireMaster { -public: - typedef RunCommand::result_type result_type; - - enum ErrorValue { CrcError = 1, InvalidResponseError }; - MaximInterface_EXPORT static const error_category & errorCategory(); - - RunCommandWithOneWireMaster(Sleep & sleep, OneWireMaster & master, - const SelectRom & selectRom) - : selectRom(selectRom), master(&master), sleep(&sleep) {} - - void setSleep(Sleep & sleep) { this->sleep = &sleep; } - - void setMaster(OneWireMaster & master) { this->master = &master; } - - void setSelectRom(const SelectRom & selectRom) { - this->selectRom = selectRom; - } - - MaximInterface_EXPORT error_code - operator()(span<const uint_least8_t> command, int delayTime, - span<uint_least8_t> & response) const; - -private: - SelectRom selectRom; - OneWireMaster * master; - const Sleep * sleep; -}; - -inline error_code make_error_code(RunCommandWithOneWireMaster::ErrorValue e) { - return error_code(e, RunCommandWithOneWireMaster::errorCategory()); -} - -class RunCommandWithI2CMaster { -public: - typedef RunCommand::result_type result_type; - - enum ErrorValue { InvalidResponseError = 1 }; - MaximInterface_EXPORT static const error_category & errorCategory(); - - RunCommandWithI2CMaster(Sleep & sleep, I2CMaster & master, - uint_least8_t address) - : sleep(&sleep), master(&master), address_(address & 0xFE) {} - - void setSleep(Sleep & sleep) { this->sleep = &sleep; } - - void setMaster(I2CMaster & master) { this->master = &master; } - - uint_least8_t address() const { return address_; } - - void setAddress(uint_least8_t address) { address_ = address & 0xFE; } - - MaximInterface_EXPORT error_code - operator()(span<const uint_least8_t> command, int delayTime, - span<uint_least8_t> & response) const; - -private: - const Sleep * sleep; - I2CMaster * master; - uint_least8_t address_; -}; - -inline error_code make_error_code(RunCommandWithI2CMaster::ErrorValue e) { - return error_code(e, RunCommandWithI2CMaster::errorCategory()); -} - -} // namespace MaximInterface - -#endif
--- a/Links/SelectRom.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include "SelectRom.hpp" - -namespace MaximInterface { - -error_code SelectMatchRom::operator()(OneWireMaster & master) const { - return matchRom(master, romId_); -} - -error_code SelectMatchRomWithResume::operator()(OneWireMaster & master) const { - error_code result; - if (romId_ == data->lastRomId) { - result = resumeRom(master); - } else { - result = matchRom(master, romId_); - data->lastRomId = romId_; - } - return result; -} - -} // namespace MaximInterface
--- a/Links/SelectRom.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_SelectRom -#define MaximInterface_SelectRom - -#include <MaximInterface/Utilities/Export.h> -#include <MaximInterface/Utilities/Function.hpp> -#include <MaximInterface/Utilities/RomId.hpp> -#include <MaximInterface/Utilities/system_error.hpp> -#include "RomCommands.hpp" - -namespace MaximInterface { - -class OneWireMaster; - -/// Selects a 1-Wire device on the bus for communication. -typedef Function<error_code(OneWireMaster &)> SelectRom; - -/// Selector for a multidrop 1-Wire bus. -class SelectMatchRom { -public: - typedef SelectRom::argument_type argument_type; - typedef SelectRom::result_type result_type; - - explicit SelectMatchRom(RomId::const_span romId) { setRomId(romId); } - - RomId::const_span romId() const { return romId_; } - - void setRomId(RomId::const_span romId) { copy(romId, make_span(romId_)); } - - MaximInterface_EXPORT error_code operator()(OneWireMaster & master) const; - -private: - RomId::array romId_; -}; - -/// @brief -/// Selector for a multidrop 1-Wire bus where slaves support the Resume ROM -/// command. -class SelectMatchRomWithResume { -public: - typedef SelectRom::argument_type argument_type; - typedef SelectRom::result_type result_type; - - struct SharedData { - SharedData() : lastRomId() {} - RomId::array lastRomId; - }; - - SelectMatchRomWithResume(SharedData & data, RomId::const_span romId) - : data(&data) { - setRomId(romId); - } - - void setSharedData(SharedData & data) { this->data = &data; } - - RomId::const_span romId() const { return romId_; } - - void setRomId(RomId::const_span romId) { copy(romId, make_span(romId_)); } - - MaximInterface_EXPORT error_code operator()(OneWireMaster & master) const; - -private: - SharedData * data; - RomId::array romId_; -}; - -} // namespace MaximInterface - -#endif
--- a/Links/SerialPort.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_SerialPort -#define MaximInterface_SerialPort - -#include <string> -#include "Uart.hpp" - -namespace MaximInterface { - -class SerialPort : public Uart { -public: - /// Connect a specified COM port. - virtual error_code connect(const std::string & portName) = 0; - - /// Disconnect from the current port. - virtual error_code disconnect() = 0; - - /// @brief Check if currently connected to a port. - /// @returns True if connected. - virtual bool connected() const = 0; - - /// Get the currently connected port name. - virtual std::string portName() const = 0; -}; - -} - -#endif
--- a/Links/Sleep.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_Sleep -#define MaximInterface_Sleep - -namespace MaximInterface { - -class Sleep { -public: - virtual ~Sleep() {} - virtual void invoke(int ms) const = 0; - void operator()(int ms) const { invoke(ms); } -}; - -} // namespace MaximInterface - -#endif
--- a/Links/SleepDecorator.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include "SleepDecorator.hpp" - -namespace MaximInterface { - -void SleepDecorator::invoke(int ms) const { sleep->invoke(ms); } - -}
--- a/Links/SleepDecorator.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_SleepDecorator -#define MaximInterface_SleepDecorator - -#include <MaximInterface/Utilities/Export.h> -#include "Sleep.hpp" - -namespace MaximInterface { - -class SleepDecorator : public Sleep { -protected: - explicit SleepDecorator(Sleep & sleep) : sleep(&sleep) {} - -public: - void setSleep(Sleep & sleep) { this->sleep = &sleep; } - MaximInterface_EXPORT virtual void invoke(int ms) const; - -private: - const Sleep * sleep; -}; - -} // namespace MaximInterface - -#endif
--- a/Links/Uart.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include <MaximInterface/Utilities/Error.hpp> -#include "Uart.hpp" - -namespace MaximInterface { - -error_code Uart::writeBlock(span<const uint_least8_t> data) { - error_code result; - for (span<const uint_least8_t>::index_type i = 0; - i < data.size() && !result; ++i) { - result = writeByte(data[i]); - } - return result; -} - -error_code Uart::readBlock(span<uint_least8_t> data) { - error_code result; - for (span<uint_least8_t>::index_type i = 0; i < data.size() && !result; ++i) { - result = readByte(data[i]); - } - return result; -} - -const error_category & Uart::errorCategory() { - static class : public error_category { - public: - virtual const char * name() const { return "UART"; } - - virtual std::string message(int condition) const { - switch (condition) { - case TimeoutError: - return "Timeout Error"; - - case OverrunError: - return "Overrun Error"; - - default: - return defaultErrorMessage(condition); - } - } - } instance; - return instance; -} - -} // namespace MaximInterface
--- a/Links/Uart.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_Uart -#define MaximInterface_Uart - -#include <stdint.h> -#include <MaximInterface/Utilities/Export.h> -#include <MaximInterface/Utilities/span.hpp> -#include <MaximInterface/Utilities/system_error.hpp> - -namespace MaximInterface { - -/// Universal asynchronous receiver-transmitter interface. -class Uart { -public: - enum ErrorValue { - TimeoutError = 1, ///< Read operation aborted due to timeout. - OverrunError ///< Received data lost due to read buffer overrun. - }; - - virtual ~Uart() {} - - /// Set the baud rate of the port in Hz. - virtual error_code setBaudRate(int_least32_t baudRate) = 0; - - /// Generate a break condition on the port for a small amount of time. - virtual error_code sendBreak() = 0; - - /// Clear all received data that was buffered. - virtual error_code clearReadBuffer() = 0; - - /// Writes a byte of data to the port. - virtual error_code writeByte(uint_least8_t data) = 0; - - /// Writes a block of data to the port. - MaximInterface_EXPORT virtual error_code - writeBlock(span<const uint_least8_t> data); - - /// @brief - /// Reads a byte of data from the port. Block until data is received or a - /// timeout is reached. - /// @param[out] data Data read from the port if successful. - virtual error_code readByte(uint_least8_t & data) = 0; - - /// @brief - /// Read a block of data from the port. Block until data is received or a - /// timeout is reached. - /// @param[out] data Data read from the port if successful. - MaximInterface_EXPORT virtual error_code readBlock(span<uint_least8_t> data); - - MaximInterface_EXPORT static const error_category & errorCategory(); -}; - -inline error_code make_error_code(Uart::ErrorValue e) { - return error_code(e, Uart::errorCategory()); -} - -inline error_condition make_error_condition(Uart::ErrorValue e) { - return error_condition(e, Uart::errorCategory()); -} - -} // namespace MaximInterface - -#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/Algorithm.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,64 @@ +/******************************************************************************* +* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_Algorithm +#define MaximInterfaceCore_Algorithm + +#include <algorithm> +#include "span.hpp" +#include "type_traits.hpp" + +/// Alternative to std::max when a constant expression is required. +#define MaximInterfaceCore_MAX(a, b) ((a) < (b) ? (b) : (a)) + +/// Alternative to std::min when a constant expression is required. +#define MaximInterfaceCore_MIN(a, b) ((b) < (a) ? (b) : (a)) + +namespace MaximInterfaceCore { + +/// Deep copy between static extent spans of the same size. +template <typename T, size_t Extent, typename U> +typename enable_if<Extent != dynamic_extent>::type copy(span<T, Extent> src, + span<U, Extent> dst) { + std::copy(src.begin(), src.end(), dst.begin()); +} + +/// Deep equality between static extent spans of the same size. +template <typename T, size_t Extent, typename U> +typename enable_if<Extent != dynamic_extent, bool>::type +equal(span<T, Extent> lhs, span<U, Extent> rhs) { + return std::equal(lhs.begin(), lhs.end(), rhs.begin()); +} + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/ChangeSizeType.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,76 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_ChangeSizeType +#define MaximInterfaceCore_ChangeSizeType + +#include <stdint.h> +#include <algorithm> +#include <limits> +#include "span.hpp" +#include "system_error.hpp" + +namespace MaximInterfaceCore { + +/// @brief +/// Adapts functions taking an array pointer and size where the size type is +/// nonstandard. +/// @tparam NewSize Nonstandard size type. +/// @tparam Func Must be callable as func(Data *, NewSize). +/// @tparam Data Array element type. +/// @param func Callback for processing chunks of data. +/// @param data Data to process with callback. +template <typename NewSize, typename Func, typename Data> +error_code changeSizeType(Func func, span<Data> data) { + typedef typename span<Data>::index_type DataSize; + + error_code result; + // Check if NewSize can represent the maximum value of DataSize. + if (static_cast<uintmax_t>(std::numeric_limits<DataSize>::max()) > + static_cast<uintmax_t>(std::numeric_limits<NewSize>::max())) { + DataSize dataIdx = 0; + do { + const span<Data> chunk = data.subspan( + dataIdx, std::min<DataSize>(data.size() - dataIdx, + std::numeric_limits<NewSize>::max())); + result = func(chunk.data(), static_cast<NewSize>(chunk.size())); + dataIdx += chunk.size(); + } while (dataIdx < data.size() && !result); + } else { + result = func(data.data(), static_cast<NewSize>(data.size())); + } + return result; +} + +} // namespace MaximInterfaceCore + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/Config.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,35 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_EXPORT + #define MaximInterfaceCore_EXPORT +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/Ecc256.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,61 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include "Ecc256.hpp" + +namespace MaximInterfaceCore { +namespace Ecc256 { + +void copy(Point::const_span src, Point::span dst) { + copy(src.x, dst.x); + copy(src.y, dst.y); +} + +void copy(KeyPair::const_span src, KeyPair::span dst) { + copy(src.privateKey, dst.privateKey); + copy(src.publicKey, dst.publicKey); +} + +void copy(Signature::const_span src, Signature::span dst) { + copy(src.r, dst.r); + copy(src.s, dst.s); +} + +PublicKey::span CertificateData::publicKey() { + const PublicKey::span span = { + make_span(result_).subspan<publicKeyIdx, Scalar::size>(), + make_span(result_).subspan<publicKeyIdx + Scalar::size, Scalar::size>()}; + return span; +} + +} // namespace Ecc256 +} // namespace MaximInterfaceCore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/Ecc256.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,244 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_Ecc256 +#define MaximInterfaceCore_Ecc256 + +#include <stdint.h> +#include "Algorithm.hpp" +#include "array_span.hpp" +#include "Config.hpp" +#include "ManId.hpp" +#include "RomId.hpp" +#include "Unconstructible.hpp" + +namespace MaximInterfaceCore { +namespace Ecc256 { + +typedef array_span<uint_least8_t, 32> Scalar; + +struct Point : Unconstructible { + struct const_span { + Scalar::const_span x; + Scalar::const_span y; + }; + + struct span { + Scalar::span x; + Scalar::span y; + + operator const_span() const { + const const_span sp = {x, y}; + return sp; + } + }; + + struct array { + Scalar::array x; + Scalar::array y; + + operator span() { + const span sp = {x, y}; + return sp; + } + + operator const_span() const { + const const_span sp = {x, y}; + return sp; + } + }; +}; + +MaximInterfaceCore_EXPORT void copy(Point::const_span src, Point::span dst); + +typedef Scalar PrivateKey; +typedef Point PublicKey; + +struct KeyPair : Unconstructible { + struct const_span { + PrivateKey::const_span privateKey; + PublicKey::const_span publicKey; + }; + + struct span { + PrivateKey::span privateKey; + PublicKey::span publicKey; + + operator const_span() const { + const const_span sp = {privateKey, publicKey}; + return sp; + } + }; + + struct array { + PrivateKey::array privateKey; + PublicKey::array publicKey; + + operator span() { + const span sp = {privateKey, publicKey}; + return sp; + } + + operator const_span() const { + const const_span sp = {privateKey, publicKey}; + return sp; + } + }; +}; + +MaximInterfaceCore_EXPORT void copy(KeyPair::const_span src, KeyPair::span dst); + +struct Signature : Unconstructible { + struct const_span { + Scalar::const_span r; + Scalar::const_span s; + }; + + struct span { + Scalar::span r; + Scalar::span s; + + operator const_span() const { + const const_span sp = {r, s}; + return sp; + } + }; + + struct array { + Scalar::array r; + Scalar::array s; + + operator span() { + const span sp = {r, s}; + return sp; + } + + operator const_span() const { + const const_span sp = {r, s}; + return sp; + } + }; +}; + +MaximInterfaceCore_EXPORT void copy(Signature::const_span src, + Signature::span dst); + +/// Data used to create a device key certificate for ECC-256 authenticators. +class CertificateData { +public: + typedef array_span<uint_least8_t, + 2 * Scalar::size + RomId::size + ManId::size> + Result; + + CertificateData() : result_() {} + + /// Formatted data result. + Result::const_span result() const { return result_; } + + /// @name Public Key + /// @brief Public key of the device. + /// @{ + + /// Get mutable Public Key. + MaximInterfaceCore_EXPORT PublicKey::span publicKey(); + + /// Get immutable Public Key. + PublicKey::const_span publicKey() const { + return const_cast<CertificateData &>(*this).publicKey(); + } + + /// Set Public Key. + CertificateData & setPublicKey(PublicKey::const_span publicKey) { + copy(publicKey, this->publicKey()); + return *this; + } + + /// @} + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + RomId::span romId() { + return make_span(result_).subspan<romIdIdx, RomId::size>(); + } + + /// Get immutable ROM ID. + RomId::const_span romId() const { + return const_cast<CertificateData &>(*this).romId(); + } + + /// Set ROM ID. + CertificateData & setRomId(RomId::const_span romId) { + copy(romId, this->romId()); + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get mutable MAN ID. + ManId::span manId() { + return make_span(result_).subspan<manIdIdx, ManId::size>(); + } + + /// Get immutable MAN ID. + ManId::const_span manId() const { + return const_cast<CertificateData &>(*this).manId(); + } + + /// Set MAN ID. + CertificateData & setManId(ManId::const_span manId) { + copy(manId, this->manId()); + return *this; + } + + /// @} + +private: + typedef Result::span::index_type index; + + static const index publicKeyIdx = 0; + static const index romIdIdx = publicKeyIdx + 2 * Scalar::size; + static const index manIdIdx = romIdIdx + RomId::size; + + Result::array result_; +}; + +} // namespace Ecc256 +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/Error.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,41 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include "Error.hpp" + +namespace MaximInterfaceCore { + +const char * defaultErrorMessage(int condition) { + return (condition == 0) ? "Success" : "Unknown Error"; +} + +} // namespace MaximInterfaceCore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/Error.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,46 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_Error +#define MaximInterfaceCore_Error + +#include "Config.hpp" + +namespace MaximInterfaceCore { + +/// @brief Get the default error message associated with a condition. +/// @details Typically used by an error_category when the condition is unknown. +MaximInterfaceCore_EXPORT const char * defaultErrorMessage(int condition); + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/FlagSet.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,226 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_FlagSet +#define MaximInterfaceCore_FlagSet + +#include <stddef.h> +#include <bitset> + +namespace MaximInterfaceCore { + +/// @brief +/// Provides functionality similar to std::bitset except using a bit flag, +/// typically of an enum type, as the indexer. +template <typename Flag, size_t flagBits> class FlagSet { +public: + class reference { + public: + reference(FlagSet & flagSet, Flag flag) : flagSet(&flagSet), flag(flag) {} + + reference & operator=(bool x) { + flagSet->set(flag, x); + return *this; + } + + reference & operator=(const reference & x) { + return operator=(static_cast<bool>(x)); + } + + operator bool() const { return flagSet->test(flag); } + + bool operator~() const { return reference(*this).flip(); } + + reference & flip() { + *this = !*this; + return *this; + } + + private: + FlagSet * flagSet; + Flag flag; + }; + + FlagSet() : bits() {} + + FlagSet(unsigned long val) : bits(val) {} + + template <typename CharT, typename Traits, typename Alloc> + explicit FlagSet( + const std::basic_string<CharT, Traits, Alloc> & str, + typename std::basic_string<CharT, Traits, Alloc>::size_type pos = 0, + typename std::basic_string<CharT, Traits, Alloc>::size_type n = + std::basic_string<CharT, Traits, Alloc>::npos) + : bits(str, pos, n) {} + + bool operator==(const FlagSet & rhs) const { return bits == rhs.bits; } + + bool operator!=(const FlagSet & rhs) const { return bits != rhs.bits; } + + /// @name Element access + /// @{ + + bool operator[](Flag flag) const { return test(flag); } + + reference operator[](Flag flag) { return reference(*this, flag); } + + bool test(Flag flag) const { return (bits.to_ulong() & flag) == flag; } + + bool any() const { return bits.any(); } + + bool none() const { return bits.none(); } + + size_t count() const { return bits.count(); } + + /// @} + + /// @name Capacity + /// @{ + + size_t size() const { return bits.size(); } + + /// @} + + /// @name Modifiers + /// @{ + + FlagSet & operator&=(const FlagSet & other) { + bits &= other.bits; + return *this; + } + + FlagSet & operator|=(const FlagSet & other) { + bits |= other.bits; + return *this; + } + + FlagSet & operator^=(const FlagSet & other) { + bits ^= other.bits; + return *this; + } + + FlagSet operator~() const { return ~bits; } + + FlagSet & set() { + bits.set(); + return *this; + } + + FlagSet & set(Flag flag, bool value = true) { + if (value) { + bits |= flag; + } else { + bits &= ~std::bitset<flagBits>(flag); + } + return *this; + } + + FlagSet & reset() { + bits.reset(); + return *this; + } + + FlagSet & reset(Flag flag) { return set(flag, false); } + + FlagSet & flip() { + bits.flip(); + return *this; + } + + FlagSet & flip(Flag flag) { + bits ^= flag; + return *this; + } + + /// @} + + /// @name Conversions + /// @{ + + template <typename CharT, typename Traits, typename Allocator> + std::basic_string<CharT, Traits, Allocator> to_string() const { + return bits.template to_string<CharT, Traits, Allocator>(); + } + + unsigned long to_ulong() const { return bits.to_ulong(); } + + /// @} + +private: + std::bitset<flagBits> bits; + + template <typename CharT, typename Traits> + friend std::basic_ostream<CharT, Traits> & + operator<<(std::basic_ostream<CharT, Traits> & os, const FlagSet & x); + + template <typename CharT, class Traits> + friend std::basic_istream<CharT, Traits> & + operator>>(std::basic_istream<CharT, Traits> & is, FlagSet & x); +}; + +template <typename Flag, size_t flagBits> +FlagSet<Flag, flagBits> operator&(const FlagSet<Flag, flagBits> & lhs, + const FlagSet<Flag, flagBits> & rhs) { + return FlagSet<Flag, flagBits>(lhs) &= rhs; +} + +template <typename Flag, size_t flagBits> +FlagSet<Flag, flagBits> operator|(const FlagSet<Flag, flagBits> & lhs, + const FlagSet<Flag, flagBits> & rhs) { + return FlagSet<Flag, flagBits>(lhs) |= rhs; +} + +template <typename Flag, size_t flagBits> +FlagSet<Flag, flagBits> operator^(const FlagSet<Flag, flagBits> & lhs, + const FlagSet<Flag, flagBits> & rhs) { + return FlagSet<Flag, flagBits>(lhs) ^= rhs; +} + +template <typename CharT, typename Traits, typename Flag, size_t flagBits> +std::basic_ostream<CharT, Traits> & +operator<<(std::basic_ostream<CharT, Traits> & os, + const FlagSet<Flag, flagBits> & x) { + os << x.bits; + return os; +} + +template <typename CharT, class Traits, typename Flag, size_t flagBits> +std::basic_istream<CharT, Traits> & +operator>>(std::basic_istream<CharT, Traits> & is, + FlagSet<Flag, flagBits> & x) { + is >> x.bits; + return is; +} + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/Function.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,565 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_Function +#define MaximInterfaceCore_Function + +#include <stddef.h> +#include "SafeBool.hpp" +#include "type_traits.hpp" + +// Include for std::swap. +#include <algorithm> +#include <utility> + +namespace MaximInterfaceCore { +namespace detail { + +// Provides char buffer storage for a given type. +// Suitability of alignment for type should be verified with alignment_of. +template <typename Type, size_t TypeSize> union TypeStorage { +public: + operator const Type *() const { return reinterpret_cast<const Type *>(data); } + + operator Type *() { + return const_cast<Type *>( + static_cast<const Type *>(static_cast<const TypeStorage &>(*this))); + } + + const Type & operator*() const { return **this; } + + Type & operator*() { + return const_cast<Type &>( + static_cast<const TypeStorage &>(*this).operator*()); + } + + const Type * operator->() const { return *this; } + + Type * operator->() { + return const_cast<Type *>( + static_cast<const TypeStorage &>(*this).operator->()); + } + +private: + char data[TypeSize]; + long double aligner1; + long int aligner2; + void * aligner3; +}; + +// Computes the internal target size for TypeStorage based on a desired total +// size. No internal storage will be allocated if the requested size is smaller +// than the required data elements of TypeWrapper or if the requested size is +// smaller than minimum size of TypeStorage. +template <typename Target, size_t totalSize> class TypeWrapperTotalSize { +private: + typedef TypeStorage<Target, 1> MinSizeStorage; + + static const size_t otherDataSize = sizeof(Target *); + + // Round down to be a multiple of alignment_of<MinSizeTargetStorage>::value. + static const size_t internalTargetRawSize = + (totalSize - otherDataSize) / alignment_of<MinSizeStorage>::value * + alignment_of<MinSizeStorage>::value; + +public: + // Use internal storage if internalTargetRawSize is valid and at least as + // large as the minimum size of TypeStorage. + static const size_t internalTargetSize = + ((totalSize > otherDataSize) && + (internalTargetRawSize >= sizeof(MinSizeStorage))) + ? internalTargetRawSize + : 0; +}; + +// Basic type erasure implementation with small object optimization. +template <typename Target, template <typename> class TargetAdapter, + size_t internalTargetSize = + TypeWrapperTotalSize<Target, 32>::internalTargetSize> +class TypeWrapper { +private: + typedef TypeStorage<Target, internalTargetSize> TargetStorage; + +public: + TypeWrapper() : currentTarget(NULL) {} + + TypeWrapper(const TypeWrapper & other) { + if (other.currentTarget == other.internalTarget) { + other.currentTarget->clone(internalTarget); + currentTarget = internalTarget; + } else if (other.currentTarget) { + currentTarget = other.currentTarget->clone(); + } else { + currentTarget = NULL; + } + } + + template <typename Source> TypeWrapper(Source source) { + if (sizeof(TargetAdapter<Source>) <= internalTargetSize && + alignment_of<TargetAdapter<Source> >::value <= + alignment_of<TargetStorage>::value) { + new (internalTarget) TargetAdapter<Source>(source); + currentTarget = internalTarget; + } else { + currentTarget = new TargetAdapter<Source>(source); + } + } + + ~TypeWrapper() { + if (currentTarget == internalTarget) { + currentTarget->~Target(); + } else { + delete currentTarget; + } + } + + const TypeWrapper & operator=(const TypeWrapper & rhs) { + TypeWrapper(rhs).swap(*this); + return *this; + } + + template <typename Source> const TypeWrapper & operator=(Source source) { + TypeWrapper(source).swap(*this); + return *this; + } + + void clear() { TypeWrapper().swap(*this); } + + void swap(TypeWrapper & other) { + if (this == &other) { + return; + } + + if (currentTarget == internalTarget && + other.currentTarget == other.internalTarget) { + TargetStorage temp; + currentTarget->clone(temp); + currentTarget->~Target(); + currentTarget = NULL; + other.currentTarget->clone(internalTarget); + other.currentTarget->~Target(); + other.currentTarget = NULL; + currentTarget = internalTarget; + temp->clone(other.internalTarget); + temp->~Target(); + other.currentTarget = other.internalTarget; + } else if (currentTarget == internalTarget) { + currentTarget->clone(other.internalTarget); + currentTarget->~Target(); + currentTarget = other.currentTarget; + other.currentTarget = other.internalTarget; + } else if (other.currentTarget == other.internalTarget) { + other.currentTarget->clone(internalTarget); + other.currentTarget->~Target(); + other.currentTarget = currentTarget; + currentTarget = internalTarget; + } else { + using std::swap; + swap(currentTarget, other.currentTarget); + } + } + + const Target * target() const { return currentTarget; } + +private: + TargetStorage internalTarget; + Target * currentTarget; +}; + +// TypeWrapper specialization with no internal storage space. +template <typename Target, template <typename> class TargetAdapter> +class TypeWrapper<Target, TargetAdapter, 0> { +public: + TypeWrapper() : currentTarget(NULL) {} + + TypeWrapper(const TypeWrapper & other) { + if (other.currentTarget) { + currentTarget = other.currentTarget->clone(); + } else { + currentTarget = NULL; + } + } + + template <typename Source> + TypeWrapper(Source source) + : currentTarget(new TargetAdapter<Source>(source)) {} + + ~TypeWrapper() { delete currentTarget; } + + const TypeWrapper & operator=(const TypeWrapper & rhs) { + TypeWrapper(rhs).swap(*this); + return *this; + } + + template <typename Source> const TypeWrapper & operator=(Source source) { + TypeWrapper(source).swap(*this); + return *this; + } + + void clear() { TypeWrapper().swap(*this); } + + void swap(TypeWrapper & other) { + using std::swap; + swap(currentTarget, other.currentTarget); + } + + const Target * target() const { return currentTarget; } + +private: + Target * currentTarget; +}; + +} // namespace detail + +// Function wrapper similar to std::function for 0-3 argument functions. +template <typename> class Function; + +// Function implementation for zero argument functions. +template <typename ResultType> class Function<ResultType()> { +public: + typedef ResultType result_type; + + Function(ResultType (*func)() = NULL) : callableWrapper() { + if (func) { + callableWrapper = func; + } + } + + template <typename F> Function(F func) : callableWrapper(func) {} + + const Function & operator=(ResultType (*func)()) { + if (func) { + callableWrapper = func; + } else { + callableWrapper.clear(); + } + return *this; + } + + template <typename F> const Function & operator=(F func) { + callableWrapper = func; + return *this; + } + + void swap(Function & other) { callableWrapper.swap(other.callableWrapper); } + + operator SafeBool() const { + return makeSafeBool(callableWrapper.target() != NULL); + } + + ResultType operator()() const { + return callableWrapper.target() ? callableWrapper.target()->invoke() + : ResultType(); + } + +private: + class Callable { + public: + virtual ~Callable() {} + virtual ResultType invoke() const = 0; + virtual Callable * clone() const = 0; + virtual void clone(void * buffer) const = 0; + }; + + template <typename F> class CallableAdapter : public Callable { + public: + CallableAdapter(F func) : func(func) {} + + virtual ResultType invoke() const { return func(); } + + virtual Callable * clone() const { return new CallableAdapter(*this); } + + virtual void clone(void * buffer) const { + new (buffer) CallableAdapter(*this); + } + + private: + F func; + }; + + detail::TypeWrapper<Callable, CallableAdapter> callableWrapper; +}; + +template <typename ResultType> +inline void swap(Function<ResultType()> & lhs, Function<ResultType()> & rhs) { + lhs.swap(rhs); +} + +// Function implementation for one argument functions. +template <typename ArgumentType, typename ResultType> +class Function<ResultType(ArgumentType)> { +public: + typedef ArgumentType argument_type; + typedef ResultType result_type; + + Function(ResultType (*func)(ArgumentType) = NULL) : callableWrapper() { + if (func) { + callableWrapper = func; + } + } + + template <typename F> Function(F func) : callableWrapper(func) {} + + const Function & operator=(ResultType (*func)(ArgumentType)) { + if (func) { + callableWrapper = func; + } else { + callableWrapper.clear(); + } + return *this; + } + + template <typename F> const Function & operator=(F func) { + callableWrapper = func; + return *this; + } + + void swap(Function & other) { callableWrapper.swap(other.callableWrapper); } + + operator SafeBool() const { + return makeSafeBool(callableWrapper.target() != NULL); + } + + ResultType operator()(ArgumentType arg) const { + return callableWrapper.target() ? callableWrapper.target()->invoke(arg) + : ResultType(); + } + +private: + class Callable { + public: + virtual ~Callable() {} + virtual ResultType invoke(ArgumentType) const = 0; + virtual Callable * clone() const = 0; + virtual void clone(void * buffer) const = 0; + }; + + template <typename F> class CallableAdapter : public Callable { + public: + CallableAdapter(F func) : func(func) {} + + virtual ResultType invoke(ArgumentType arg) const { return func(arg); } + + virtual Callable * clone() const { return new CallableAdapter(*this); } + + virtual void clone(void * buffer) const { + new (buffer) CallableAdapter(*this); + } + + private: + F func; + }; + + detail::TypeWrapper<Callable, CallableAdapter> callableWrapper; +}; + +template <typename ArgumentType, typename ResultType> +inline void swap(Function<ResultType(ArgumentType)> & lhs, + Function<ResultType(ArgumentType)> & rhs) { + lhs.swap(rhs); +} + +// Function implementation for two argument functions. +template <typename FirstArgumentType, typename SecondArgumentType, + typename ResultType> +class Function<ResultType(FirstArgumentType, SecondArgumentType)> { +public: + typedef FirstArgumentType first_argument_type; + typedef SecondArgumentType second_argument_type; + typedef ResultType result_type; + + Function(ResultType (*func)(FirstArgumentType, SecondArgumentType) = NULL) + : callableWrapper() { + if (func) { + callableWrapper = func; + } + } + + template <typename F> Function(F func) : callableWrapper(func) {} + + const Function & operator=(ResultType (*func)(FirstArgumentType, + SecondArgumentType)) { + if (func) { + callableWrapper = func; + } else { + callableWrapper.clear(); + } + return *this; + } + + template <typename F> const Function & operator=(F func) { + callableWrapper = func; + return *this; + } + + void swap(Function & other) { callableWrapper.swap(other.callableWrapper); } + + operator SafeBool() const { + return makeSafeBool(callableWrapper.target() != NULL); + } + + ResultType operator()(FirstArgumentType arg1, SecondArgumentType arg2) const { + return callableWrapper.target() + ? callableWrapper.target()->invoke(arg1, arg2) + : ResultType(); + } + +private: + class Callable { + public: + virtual ~Callable() {} + virtual ResultType invoke(FirstArgumentType, SecondArgumentType) const = 0; + virtual Callable * clone() const = 0; + virtual void clone(void * buffer) const = 0; + }; + + template <typename F> class CallableAdapter : public Callable { + public: + CallableAdapter(F func) : func(func) {} + + virtual ResultType invoke(FirstArgumentType arg1, + SecondArgumentType arg2) const { + return func(arg1, arg2); + } + + virtual Callable * clone() const { return new CallableAdapter(*this); } + + virtual void clone(void * buffer) const { + new (buffer) CallableAdapter(*this); + } + + private: + F func; + }; + + detail::TypeWrapper<Callable, CallableAdapter> callableWrapper; +}; + +template <typename FirstArgumentType, typename SecondArgumentType, + typename ResultType> +inline void +swap(Function<ResultType(FirstArgumentType, SecondArgumentType)> & lhs, + Function<ResultType(FirstArgumentType, SecondArgumentType)> & rhs) { + lhs.swap(rhs); +} + +// Function implementation for three argument functions. +template <typename FirstArgumentType, typename SecondArgumentType, + typename ThirdArgumentType, typename ResultType> +class Function<ResultType(FirstArgumentType, SecondArgumentType, + ThirdArgumentType)> { +public: + typedef ResultType result_type; + + Function(ResultType (*func)(FirstArgumentType, SecondArgumentType, + ThirdArgumentType) = NULL) + : callableWrapper() { + if (func) { + callableWrapper = func; + } + } + + template <typename F> Function(F func) : callableWrapper(func) {} + + const Function & operator=(ResultType (*func)(FirstArgumentType, + SecondArgumentType, + ThirdArgumentType)) { + if (func) { + callableWrapper = func; + } else { + callableWrapper.clear(); + } + return *this; + } + + template <typename F> const Function & operator=(F func) { + callableWrapper = func; + return *this; + } + + void swap(Function & other) { callableWrapper.swap(other.callableWrapper); } + + operator SafeBool() const { + return makeSafeBool(callableWrapper.target() != NULL); + } + + ResultType operator()(FirstArgumentType arg1, SecondArgumentType arg2, + ThirdArgumentType arg3) const { + return callableWrapper.target() + ? callableWrapper.target()->invoke(arg1, arg2, arg3) + : ResultType(); + } + +private: + class Callable { + public: + virtual ~Callable() {} + virtual ResultType invoke(FirstArgumentType, SecondArgumentType, + ThirdArgumentType) const = 0; + virtual Callable * clone() const = 0; + virtual void clone(void * buffer) const = 0; + }; + + template <typename F> class CallableAdapter : public Callable { + public: + CallableAdapter(F func) : func(func) {} + + virtual ResultType invoke(FirstArgumentType arg1, SecondArgumentType arg2, + ThirdArgumentType arg3) const { + return func(arg1, arg2, arg3); + } + + virtual Callable * clone() const { return new CallableAdapter(*this); } + + virtual void clone(void * buffer) const { + new (buffer) CallableAdapter(*this); + } + + private: + F func; + }; + + detail::TypeWrapper<Callable, CallableAdapter> callableWrapper; +}; + +template <typename FirstArgumentType, typename SecondArgumentType, + typename ThirdArgumentType, typename ResultType> +inline void swap(Function<ResultType(FirstArgumentType, SecondArgumentType, + ThirdArgumentType)> & lhs, + Function<ResultType(FirstArgumentType, SecondArgumentType, + ThirdArgumentType)> & rhs) { + lhs.swap(rhs); +} + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/HexConversions.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,86 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include <cctype> +#include <cstdio> +#include <cstdlib> +#include "HexConversions.hpp" + +using std::string; +using std::vector; + +namespace MaximInterfaceCore { + +static const int charsPerByte = 2; + +string byteArrayToHexString(span<const uint_least8_t> byteArray) { + string hexString; + hexString.reserve(byteArray.size() * charsPerByte); + for (span<const uint_least8_t>::index_type i = 0; i < byteArray.size(); ++i) { + char hexBuf[charsPerByte + 1]; + std::sprintf(hexBuf, "%2.2X", byteArray[i] & 0xFF); + hexString.append(hexBuf, charsPerByte); + } + return hexString; +} + +Optional<vector<uint_least8_t> > +hexStringToByteArray(const string & hexString) { + Optional<vector<uint_least8_t> > byteArray = vector<uint_least8_t>(); + byteArray->reserve(hexString.size() / charsPerByte); + char hexBuf[charsPerByte + 1]; + char * const hexBufEnd = hexBuf + charsPerByte; + *hexBufEnd = '\0'; + char * hexBufIt = hexBuf; + for (string::const_iterator hexStringIt = hexString.begin(), + hexStringEnd = hexString.end(); + hexStringIt != hexStringEnd; ++hexStringIt) { + if (!std::isspace(*hexStringIt)) { + *hexBufIt = *hexStringIt; + if (++hexBufIt == hexBufEnd) { + char * hexBufParseEnd; + byteArray->push_back(static_cast<uint_least8_t>( + std::strtoul(hexBuf, &hexBufParseEnd, 16))); + if (hexBufParseEnd != hexBufEnd) { + break; + } + hexBufIt = hexBuf; + } + } + } + if (hexBufIt != hexBuf) { + byteArray.reset(); + } + return byteArray; +} + +} // namespace MaximInterfaceCore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/HexConversions.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,56 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_HexConversions +#define MaximInterfaceCore_HexConversions + +#include <stddef.h> +#include <stdint.h> +#include <string> +#include <vector> +#include "Config.hpp" +#include "Optional.hpp" +#include "span.hpp" + +namespace MaximInterfaceCore { + +/// Convert a byte array to a hex string. +MaximInterfaceCore_EXPORT std::string +byteArrayToHexString(span<const uint_least8_t> byteArray); + +/// Convert a hex string to a byte array. +MaximInterfaceCore_EXPORT Optional<std::vector<uint_least8_t> > +hexStringToByteArray(const std::string & hexString); + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/I2CMaster.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,104 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include "Error.hpp" +#include "I2CMaster.hpp" + +namespace MaximInterfaceCore { + +error_code I2CMaster::writeBlock(span<const uint_least8_t> data) { + error_code result; + for (span<const uint_least8_t>::index_type i = 0; + i < data.size() && !result; ++i) { + result = writeByte(data[i]); + } + return result; +} + +error_code I2CMaster::doWritePacket(uint_least8_t address, + span<const uint_least8_t> data, + bool sendStop) { + error_code result = start(address & 0xFE); + if (!result) { + result = writeBlock(data); + } + if (sendStop) { + error_code stopResult = stop(); + if (!result) { + result = stopResult; + } + } + return result; +} + +error_code I2CMaster::readBlock(AckStatus status, span<uint_least8_t> data) { + error_code result; + for (span<uint_least8_t>::index_type i = 0; i < data.size() && !result; ++i) { + result = readByte(i == (data.size() - 1) ? status : Ack, data[i]); + } + return result; +} + +error_code I2CMaster::doReadPacket(uint_least8_t address, + span<uint_least8_t> data, bool sendStop) { + error_code result = start(address | 0x01); + if (!result) { + result = readBlock(Nack, data); + } + if (sendStop) { + error_code stopResult = stop(); + if (!result) { + result = stopResult; + } + } + return result; +} + +const error_category & I2CMaster::errorCategory() { + static class : public error_category { + public: + virtual const char * name() const { return "I2CMaster"; } + + virtual std::string message(int condition) const { + switch (condition) { + case NackError: + return "Nack Error"; + + default: + return defaultErrorMessage(condition); + } + } + } instance; + return instance; +} + +} // namespace MaximInterfaceCore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/I2CMaster.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,124 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_I2CMaster +#define MaximInterfaceCore_I2CMaster + +#include <stdint.h> +#include "Config.hpp" +#include "span.hpp" +#include "system_error.hpp" + +namespace MaximInterfaceCore { + +/// I2C master interface. +class I2CMaster { +public: + enum ErrorValue { + NackError = 1 ///< Transaction stopped due to a NACK from the slave device. + }; + + enum AckStatus { Nack, Ack }; + + virtual ~I2CMaster() {} + + /// @brief Send start condition and address on the bus. + /// @param address Address with R/W bit. + virtual error_code start(uint_least8_t address) = 0; + + /// Send stop condition on the bus. + virtual error_code stop() = 0; + + /// Write data byte to the bus. + virtual error_code writeByte(uint_least8_t data) = 0; + + /// Write data block to the bus. + MaximInterfaceCore_EXPORT virtual error_code + writeBlock(span<const uint_least8_t> data); + + /// @brief + /// Perform a complete write transaction on the bus with optional stop + /// condition. + /// @param address Address in 8-bit format. + /// @param data Data to write to the bus. + /// @param sendStop + /// True to send a stop condition or false to set up a repeated start. + error_code writePacket(uint_least8_t address, span<const uint_least8_t> data, + bool sendStop = true) { + return doWritePacket(address, data, sendStop); + } + + /// @brief Read data byte from the bus. + /// @param status Determines whether an ACK or NACK is sent after reading. + /// @param[out] data Data read from the bus if successful. + virtual error_code readByte(AckStatus status, uint_least8_t & data) = 0; + + /// @brief Read data block from the bus. + /// @param status Determines whether an ACK or NACK is sent after reading. + /// @param[out] data Data read from the bus if successful. + MaximInterfaceCore_EXPORT virtual error_code + readBlock(AckStatus status, span<uint_least8_t> data); + + /// @brief + /// Perform a complete read transaction on the bus with optional stop + /// condition. + /// @param address Address in 8-bit format. + /// @param[out] data Data read from the bus if successful. + /// @param sendStop + /// True to send a stop condition or false to set up a repeated start. + error_code readPacket(uint_least8_t address, span<uint_least8_t> data, + bool sendStop = true) { + return doReadPacket(address, data, sendStop); + } + + MaximInterfaceCore_EXPORT static const error_category & errorCategory(); + +protected: + MaximInterfaceCore_EXPORT virtual error_code + doWritePacket(uint_least8_t address, span<const uint_least8_t> data, + bool sendStop); + + MaximInterfaceCore_EXPORT virtual error_code + doReadPacket(uint_least8_t address, span<uint_least8_t> data, bool sendStop); +}; + +inline error_code make_error_code(I2CMaster::ErrorValue e) { + return error_code(e, I2CMaster::errorCategory()); +} + +inline error_condition make_error_condition(I2CMaster::ErrorValue e) { + return error_condition(e, I2CMaster::errorCategory()); +} + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/I2CMasterDecorator.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,73 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include "I2CMasterDecorator.hpp" + +namespace MaximInterfaceCore { + +error_code I2CMasterDecorator::start(uint_least8_t address) { + return master->start(address); +} + +error_code I2CMasterDecorator::stop() { return master->stop(); } + +error_code I2CMasterDecorator::writeByte(uint_least8_t data) { + return master->writeByte(data); +} + +error_code I2CMasterDecorator::writeBlock(span<const uint_least8_t> data) { + return master->writeBlock(data); +} + +error_code I2CMasterDecorator::doWritePacket(uint_least8_t address, + span<const uint_least8_t> data, + bool sendStop) { + return master->writePacket(address, data, sendStop); +} + +error_code I2CMasterDecorator::readByte(AckStatus status, + uint_least8_t & data) { + return master->readByte(status, data); +} + +error_code I2CMasterDecorator::readBlock(AckStatus status, + span<uint_least8_t> data) { + return master->readBlock(status, data); +} + +error_code I2CMasterDecorator::doReadPacket(uint_least8_t address, + span<uint_least8_t> data, + bool sendStop) { + return master->readPacket(address, data, sendStop); +} + +} // namespace MaximInterfaceCore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/I2CMasterDecorator.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,77 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_I2CMasterDecorator +#define MaximInterfaceCore_I2CMasterDecorator + +#include "Config.hpp" +#include "I2CMaster.hpp" + +namespace MaximInterfaceCore { + +class I2CMasterDecorator : public I2CMaster { +protected: + explicit I2CMasterDecorator(I2CMaster & master) : master(&master) {} + +public: + void setMaster(I2CMaster & master) { this->master = &master; } + + MaximInterfaceCore_EXPORT virtual error_code start(uint_least8_t address); + + MaximInterfaceCore_EXPORT virtual error_code stop(); + + MaximInterfaceCore_EXPORT virtual error_code writeByte(uint_least8_t data); + + MaximInterfaceCore_EXPORT virtual error_code + writeBlock(span<const uint_least8_t> data); + + MaximInterfaceCore_EXPORT virtual error_code readByte(AckStatus status, + uint_least8_t & data); + + MaximInterfaceCore_EXPORT virtual error_code + readBlock(AckStatus status, span<uint_least8_t> data); + +protected: + MaximInterfaceCore_EXPORT virtual error_code + doWritePacket(uint_least8_t address, span<const uint_least8_t> data, + bool sendStop); + + MaximInterfaceCore_EXPORT virtual error_code + doReadPacket(uint_least8_t address, span<uint_least8_t> data, bool sendStop); + +private: + I2CMaster * master; +}; + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/LoggingI2CMaster.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,138 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include <utility> +#include "HexConversions.hpp" +#include "LoggingI2CMaster.hpp" + +using std::string; + +namespace MaximInterfaceCore { + +static const char startString[] = "S "; +static const char stopString[] = "P"; + +static string formatDataString(span<const uint_least8_t> data, bool read) { + string dataBuilder; + for (span<const uint_least8_t>::index_type i = 0; i < data.size(); ++i) { + if (read) { + dataBuilder.append(1, '['); + } + dataBuilder.append(byteArrayToHexString(data.subspan(i, 1))); + if (read) { + dataBuilder.append(1, ']'); + } + dataBuilder.append(1, ' '); + } + return dataBuilder; +} + +void LoggingI2CMaster::tryWriteMessage() { + if (writeMessage) { + writeMessage(messageBuilder); + } + messageBuilder.clear(); +} + +error_code LoggingI2CMaster::start(uint_least8_t address) { + messageBuilder.append(startString); + messageBuilder.append(formatDataString(make_span(&address, 1), false)); + return I2CMasterDecorator::start(address); +} + +error_code LoggingI2CMaster::stop() { + messageBuilder.append(stopString); + tryWriteMessage(); + return I2CMasterDecorator::stop(); +} + +error_code LoggingI2CMaster::writeByte(uint_least8_t data) { + messageBuilder.append(formatDataString(make_span(&data, 1), false)); + return I2CMasterDecorator::writeByte(data); +} + +error_code LoggingI2CMaster::writeBlock(span<const uint_least8_t> data) { + messageBuilder.append(formatDataString(data, false)); + return I2CMasterDecorator::writeBlock(data); +} + +error_code LoggingI2CMaster::doWritePacket(uint_least8_t address, + span<const uint_least8_t> data, + bool sendStop) { + messageBuilder.append(startString); + messageBuilder.append(formatDataString(make_span(&address, 1), false)); + error_code result = + I2CMasterDecorator::doWritePacket(address, data, sendStop); + if (!result) { + messageBuilder.append(formatDataString(data, false)); + } + if (sendStop || result) { + messageBuilder.append(stopString); + tryWriteMessage(); + } + return result; +} + +error_code LoggingI2CMaster::readByte(AckStatus status, uint_least8_t & data) { + error_code result = I2CMasterDecorator::readByte(status, data); + if (!result) { + messageBuilder.append(formatDataString(make_span(&data, 1), true)); + } + return result; +} + +error_code LoggingI2CMaster::readBlock(AckStatus status, + span<uint_least8_t> data) { + error_code result = I2CMasterDecorator::readBlock(status, data); + if (!result) { + messageBuilder.append(formatDataString(data, true)); + } + return result; +} + +error_code LoggingI2CMaster::doReadPacket(uint_least8_t address, + span<uint_least8_t> data, + bool sendStop) { + messageBuilder.append(startString); + messageBuilder.append(formatDataString(make_span(&address, 1), false)); + error_code result = I2CMasterDecorator::doReadPacket(address, data, sendStop); + if (!result) { + messageBuilder.append(formatDataString(data, true)); + } + if (sendStop || result) { + messageBuilder.append(stopString); + tryWriteMessage(); + } + return result; +} + +} // namespace MaximInterfaceCore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/LoggingI2CMaster.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,84 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_LoggingI2CMaster +#define MaximInterfaceCore_LoggingI2CMaster + +#include <string> +#include "Config.hpp" +#include "I2CMasterDecorator.hpp" +#include "WriteMessage.hpp" + +namespace MaximInterfaceCore { + +class LoggingI2CMaster : public I2CMasterDecorator { +public: + explicit LoggingI2CMaster(I2CMaster & i2c, + const WriteMessage & writeMessage = WriteMessage()) + : I2CMasterDecorator(i2c), writeMessage(writeMessage), messageBuilder() {} + + void setWriteMessage(const WriteMessage & writeMessage) { + this->writeMessage = writeMessage; + } + + MaximInterfaceCore_EXPORT virtual error_code start(uint_least8_t address); + + MaximInterfaceCore_EXPORT virtual error_code stop(); + + MaximInterfaceCore_EXPORT virtual error_code writeByte(uint_least8_t data); + + MaximInterfaceCore_EXPORT virtual error_code + writeBlock(span<const uint_least8_t> data); + + MaximInterfaceCore_EXPORT virtual error_code readByte(AckStatus status, + uint_least8_t & data); + MaximInterfaceCore_EXPORT virtual error_code + readBlock(AckStatus status, span<uint_least8_t> data); + +protected: + MaximInterfaceCore_EXPORT virtual error_code + doWritePacket(uint_least8_t address, span<const uint_least8_t> data, + bool sendStop); + + MaximInterfaceCore_EXPORT virtual error_code + doReadPacket(uint_least8_t address, span<uint_least8_t> data, bool sendStop); + +private: + void tryWriteMessage(); + + WriteMessage writeMessage; + std::string messageBuilder; +}; + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/LoggingOneWireMaster.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,144 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include "HexConversions.hpp" +#include "LoggingOneWireMaster.hpp" + +using std::string; + +namespace MaximInterfaceCore { + +static const char strongLevelString[] = "<SP_ON>"; + +static string formatDataString(span<const uint_least8_t> data, bool read) { + string dataBuilder; + for (span<const uint_least8_t>::index_type i = 0; i < data.size(); ++i) { + if (read) { + dataBuilder.append(1, '['); + } + dataBuilder.append(byteArrayToHexString(data.subspan(i, 1))); + if (read) { + dataBuilder.append(1, ']'); + } + dataBuilder.append(1, ' '); + } + return dataBuilder; +} + +void LoggingOneWireMaster::tryWriteMessage(const std::string & message) { + if (writeMessage) { + writeMessage(message); + } +} + +error_code LoggingOneWireMaster::reset() { + error_code result = OneWireMasterDecorator::reset(); + tryWriteMessage(!result ? "RP" : "RN"); + return result; +} + +error_code LoggingOneWireMaster::writeByteSetLevel(uint_least8_t sendByte, + Level afterLevel) { + tryWriteMessage(formatDataString(make_span(&sendByte, 1), false)); + if (afterLevel == StrongLevel) { + tryWriteMessage(strongLevelString); + } + return OneWireMasterDecorator::writeByteSetLevel(sendByte, afterLevel); +} + +error_code LoggingOneWireMaster::readByteSetLevel(uint_least8_t & recvByte, + Level afterLevel) { + error_code result = + OneWireMasterDecorator::readByteSetLevel(recvByte, afterLevel); + if (!result) { + tryWriteMessage(formatDataString(make_span(&recvByte, 1), true)); + if (afterLevel == StrongLevel) { + tryWriteMessage(strongLevelString); + } + } + return result; +} + +error_code LoggingOneWireMaster::writeBlock(span<const uint_least8_t> sendBuf) { + tryWriteMessage(formatDataString(sendBuf, false)); + return OneWireMasterDecorator::writeBlock(sendBuf); +} + +error_code LoggingOneWireMaster::readBlock(span<uint_least8_t> recvBuf) { + error_code result = OneWireMasterDecorator::readBlock(recvBuf); + if (!result) { + tryWriteMessage(formatDataString(recvBuf, true)); + } + return result; +} + +error_code LoggingOneWireMaster::setSpeed(Speed newSpeed) { + error_code result = OneWireMasterDecorator::setSpeed(newSpeed); + if (!result) { + string newSpeedString; + switch (newSpeed) { + case StandardSpeed: + newSpeedString = "<STD>"; + break; + + case OverdriveSpeed: + newSpeedString = "<OVR>"; + break; + } + if (!newSpeedString.empty()) { + tryWriteMessage(newSpeedString); + } + } + return result; +} + +error_code LoggingOneWireMaster::setLevel(Level newLevel) { + error_code result = OneWireMasterDecorator::setLevel(newLevel); + if (!result) { + string newLevelString; + switch (newLevel) { + case NormalLevel: + newLevelString = "<SP_OFF>"; + break; + + case StrongLevel: + newLevelString = strongLevelString; + break; + } + if (!newLevelString.empty()) { + tryWriteMessage(newLevelString); + } + } + return result; +} + +} // namespace MaximInterfaceCore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/LoggingOneWireMaster.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,80 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_LoggingOneWireMaster +#define MaximInterfaceCore_LoggingOneWireMaster + +#include <string> +#include "Config.hpp" +#include "OneWireMasterDecorator.hpp" +#include "WriteMessage.hpp" + +namespace MaximInterfaceCore { + +class LoggingOneWireMaster : public OneWireMasterDecorator { +public: + explicit LoggingOneWireMaster( + OneWireMaster & master, + const WriteMessage & writeMessage = WriteMessage()) + : OneWireMasterDecorator(master), writeMessage(writeMessage) {} + + void setWriteMessage(const WriteMessage & writeMessage) { + this->writeMessage = writeMessage; + } + + MaximInterfaceCore_EXPORT virtual error_code reset(); + + MaximInterfaceCore_EXPORT virtual error_code + writeByteSetLevel(uint_least8_t sendByte, Level afterLevel); + + MaximInterfaceCore_EXPORT virtual error_code + readByteSetLevel(uint_least8_t & recvByte, Level afterLevel); + + MaximInterfaceCore_EXPORT virtual error_code + writeBlock(span<const uint_least8_t> sendBuf); + + MaximInterfaceCore_EXPORT virtual error_code + readBlock(span<uint_least8_t> recvBuf); + + MaximInterfaceCore_EXPORT virtual error_code setSpeed(Speed newSpeed); + + MaximInterfaceCore_EXPORT virtual error_code setLevel(Level newLevel); + +private: + void tryWriteMessage(const std::string & message); + + WriteMessage writeMessage; +}; + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/LoggingSleep.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,47 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include <sstream> +#include "LoggingSleep.hpp" + +namespace MaximInterfaceCore { + +void LoggingSleep::invoke(int ms) const { + if (writeMessage) { + std::ostringstream message; + message << "<DELAY" << ms << '>'; + writeMessage(message.str()); + } + SleepDecorator::invoke(ms); +} + +} // namespace MaximInterfaceCore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/LoggingSleep.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,60 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_LoggingSleep +#define MaximInterfaceCore_LoggingSleep + +#include "Config.hpp" +#include "SleepDecorator.hpp" +#include "WriteMessage.hpp" + +namespace MaximInterfaceCore { + +class LoggingSleep : public SleepDecorator { +public: + LoggingSleep(Sleep & sleep, + const WriteMessage & writeMessage = WriteMessage()) + : SleepDecorator(sleep), writeMessage(writeMessage) {} + + void setWriteMessage(const WriteMessage & writeMessage) { + this->writeMessage = writeMessage; + } + + MaximInterfaceCore_EXPORT virtual void invoke(int ms) const; + +private: + WriteMessage writeMessage; +}; + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/ManId.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,45 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_ManId +#define MaximInterfaceCore_ManId + +#include "array_span.hpp" + +namespace MaximInterfaceCore { + +/// Standard container for a manufacturer ID. +typedef array_span<uint_least8_t, 2> ManId; + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/None.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,48 @@ +/******************************************************************************* +* Copyright (C) 2019 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_None +#define MaximInterfaceCore_None + +namespace MaximInterfaceCore { + +struct None { + // Disable default constructor. + explicit None(int) {} +}; + +/// Empty tag for use with Optional and similar types. +static const None none(0); + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/OneWireMaster.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,130 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include "Error.hpp" +#include "OneWireMaster.hpp" + +namespace MaximInterfaceCore { + +static const int maxBitNum = 7; + +error_code OneWireMaster::writeByteSetLevel(uint_least8_t sendByte, + Level afterLevel) { + error_code result; + for (int bitNum = 0; (bitNum <= maxBitNum) && !result; ++bitNum) { + result = writeBitSetLevel(((sendByte >> bitNum) & 1) == 1, + (bitNum == maxBitNum) ? afterLevel : NormalLevel); + } + return result; +} + +error_code OneWireMaster::readByteSetLevel(uint_least8_t & recvByte, + Level afterLevel) { + recvByte = 0; + error_code result; + for (int bitNum = 0; bitNum <= maxBitNum; ++bitNum) { + bool recvBit; + result = readBitSetLevel(recvBit, + (bitNum == maxBitNum) ? afterLevel : NormalLevel); + if (result) { + break; + } + if (recvBit) { + recvByte |= (1 << bitNum); + } + } + return result; +} + +error_code OneWireMaster::writeBlock(span<const uint_least8_t> sendBuf) { + error_code result; + for (span<const uint_least8_t>::index_type i = 0; + i < sendBuf.size() && !result; ++i) { + result = writeByte(sendBuf[i]); + } + return result; +} + +error_code OneWireMaster::readBlock(span<uint_least8_t> recvBuf) { + error_code result; + for (span<uint_least8_t>::index_type i = 0; i < recvBuf.size() && !result; + ++i) { + result = readByte(recvBuf[i]); + } + return result; +} + +error_code OneWireMaster::triplet(TripletData & data) { + error_code result = readBit(data.readBit); + if (!result) { + result = readBit(data.readBitComplement); + } + if (!result) { + if (data.readBit) { + data.writeBit = 1; + } else if (data.readBitComplement) { + data.writeBit = 0; + } + // else: use data.writeBit parameter + result = writeBit(data.writeBit); + } + return result; +} + +const error_category & OneWireMaster::errorCategory() { + static class : public error_category { + public: + virtual const char * name() const { return "OneWireMaster"; } + + virtual std::string message(int condition) const { + switch (condition) { + case NoSlaveError: + return "No Slave Error"; + + case ShortDetectedError: + return "Short Detected Error"; + + case InvalidSpeedError: + return "Invalid Speed Error"; + + case InvalidLevelError: + return "Invalid Level Error"; + + default: + return defaultErrorMessage(condition); + } + } + } instance; + return instance; +} + +} // namespace MaximInterfaceCore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/OneWireMaster.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,190 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_OneWireMaster +#define MaximInterfaceCore_OneWireMaster + +#include <stdint.h> +#include "Config.hpp" +#include "span.hpp" +#include "system_error.hpp" + +namespace MaximInterfaceCore { + +/// 1-Wire master interface. +class OneWireMaster { +public: + /// Speed of the 1-Wire bus. + enum Speed { StandardSpeed = 0x00, OverdriveSpeed = 0x01 }; + + /// Level of the 1-Wire bus. + enum Level { NormalLevel = 0x00, StrongLevel = 0x02 }; + + /// Result of all 1-Wire commands. + enum ErrorValue { + NoSlaveError = 1, ///< Slave not detected, typically due to no presence pulse. + ShortDetectedError, + InvalidSpeedError, + InvalidLevelError + }; + + struct TripletData { + bool writeBit; + bool readBit; + bool readBitComplement; + }; + + virtual ~OneWireMaster() {} + + /// @brief + /// Reset all of the devices on the 1-Wire bus and check for a presence pulse. + /// @returns + /// NoSlaveError if reset was performed but no presence pulse was detected. + virtual error_code reset() = 0; + + /// @brief + /// Send and receive one bit of communication and set a new level on the + /// 1-Wire bus. + /// @param[in,out] sendRecvBit + /// Input containing the bit to send and output containing the received bit. + /// @param afterLevel Level to set the 1-Wire bus to after communication. + virtual error_code touchBitSetLevel(bool & sendRecvBit, Level afterLevel) = 0; + + /// @brief + /// Send one byte of communication and set a new level on the 1-Wire bus. + /// @param sendByte Byte to send on the 1-Wire bus. + /// @param afterLevel Level to set the 1-Wire bus to after communication. + MaximInterfaceCore_EXPORT virtual error_code + writeByteSetLevel(uint_least8_t sendByte, Level afterLevel); + + /// @brief + /// Receive one byte of communication and set a new level on the 1-Wire bus. + /// @param recvByte Buffer to receive the data from the 1-Wire bus. + /// @param afterLevel Level to set the 1-Wire bus to after communication. + MaximInterfaceCore_EXPORT virtual error_code + readByteSetLevel(uint_least8_t & recvByte, Level afterLevel); + + /// @brief Send a block of communication on the 1-Wire bus. + /// @param[in] sendBuf Buffer to send on the 1-Wire bus. + MaximInterfaceCore_EXPORT virtual error_code + writeBlock(span<const uint_least8_t> sendBuf); + + /// @brief Receive a block of communication on the 1-Wire bus. + /// @param[out] recvBuf Buffer to receive the data from the 1-Wire bus. + MaximInterfaceCore_EXPORT virtual error_code + readBlock(span<uint_least8_t> recvBuf); + + /// Set the 1-Wire bus communication speed. + virtual error_code setSpeed(Speed newSpeed) = 0; + + /// Set the 1-Wire bus level. + virtual error_code setLevel(Level newLevel) = 0; + + /// @brief 1-Wire Triplet operation. + /// @details Perform one bit of a 1-Wire search. This command + /// does two read bits and one write bit. The write bit is either + /// the default direction (all devices have same bit) or in case + /// of a discrepancy, the data.writeBit parameter is used. + /// @param[in,out] data + /// Input with desired writeBit in case both read bits are zero. + /// Output with all data fields set. + MaximInterfaceCore_EXPORT virtual error_code triplet(TripletData & data); + + /// @brief + /// Send one bit of communication and set a new level on the 1-Wire bus. + /// @param sendBit Bit to send on the 1-Wire bus. + /// @param afterLevel Level to set the 1-Wire bus to after communication. + error_code writeBitSetLevel(bool sendBit, Level afterLevel) { + return touchBitSetLevel(sendBit, afterLevel); + } + + /// @brief + /// Receive one bit of communication and set a new level on the 1-Wire bus. + /// @param[out] recvBit Received data from the 1-Wire bus. + /// @param afterLevel Level to set the 1-Wire bus to after communication. + error_code readBitSetLevel(bool & recvBit, Level afterLevel) { + recvBit = 1; + return touchBitSetLevel(recvBit, afterLevel); + } + + // Alternate forms of the read and write functions. + + error_code touchBit(bool & sendRecvBit) { + return touchBitSetLevel(sendRecvBit, NormalLevel); + } + + error_code writeBit(bool sendBit) { + return writeBitSetLevel(sendBit, NormalLevel); + } + + error_code readBit(bool & recvBit) { + return readBitSetLevel(recvBit, NormalLevel); + } + + error_code writeBitPower(bool sendBit) { + return writeBitSetLevel(sendBit, StrongLevel); + } + + error_code readBitPower(bool & recvBit) { + return readBitSetLevel(recvBit, StrongLevel); + } + + error_code writeByte(uint_least8_t sendByte) { + return writeByteSetLevel(sendByte, NormalLevel); + } + + error_code readByte(uint_least8_t & recvByte) { + return readByteSetLevel(recvByte, NormalLevel); + } + + error_code writeBytePower(uint_least8_t sendByte) { + return writeByteSetLevel(sendByte, StrongLevel); + } + + error_code readBytePower(uint_least8_t & recvByte) { + return readByteSetLevel(recvByte, StrongLevel); + } + + MaximInterfaceCore_EXPORT static const error_category & errorCategory(); +}; + +inline error_code make_error_code(OneWireMaster::ErrorValue e) { + return error_code(e, OneWireMaster::errorCategory()); +} + +inline error_condition make_error_condition(OneWireMaster::ErrorValue e) { + return error_condition(e, OneWireMaster::errorCategory()); +} + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/OneWireMasterDecorator.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,75 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include "OneWireMasterDecorator.hpp" + +namespace MaximInterfaceCore { + +error_code OneWireMasterDecorator::reset() { return master->reset(); } + +error_code OneWireMasterDecorator::touchBitSetLevel(bool & sendRecvBit, + Level afterLevel) { + return master->touchBitSetLevel(sendRecvBit, afterLevel); +} + +error_code OneWireMasterDecorator::writeByteSetLevel(uint_least8_t sendByte, + Level afterLevel) { + return master->writeByteSetLevel(sendByte, afterLevel); +} + +error_code OneWireMasterDecorator::readByteSetLevel(uint_least8_t & recvByte, + Level afterLevel) { + return master->readByteSetLevel(recvByte, afterLevel); +} + +error_code +OneWireMasterDecorator::writeBlock(span<const uint_least8_t> sendBuf) { + return master->writeBlock(sendBuf); +} + +error_code OneWireMasterDecorator::readBlock(span<uint_least8_t> recvBuf) { + return master->readBlock(recvBuf); +} + +error_code OneWireMasterDecorator::setSpeed(Speed newSpeed) { + return master->setSpeed(newSpeed); +} + +error_code OneWireMasterDecorator::setLevel(Level newLevel) { + return master->setLevel(newLevel); +} + +error_code OneWireMasterDecorator::triplet(TripletData & data) { + return master->triplet(data); +} + +} // namespace MaximInterfaceCore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/OneWireMasterDecorator.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,77 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_OneWireMasterDecorator +#define MaximInterfaceCore_OneWireMasterDecorator + +#include "Config.hpp" +#include "OneWireMaster.hpp" + +namespace MaximInterfaceCore { + +class OneWireMasterDecorator : public OneWireMaster { +protected: + explicit OneWireMasterDecorator(OneWireMaster & master) : master(&master) {} + +public: + void setMaster(OneWireMaster & master) { this->master = &master; } + + MaximInterfaceCore_EXPORT virtual error_code reset(); + + MaximInterfaceCore_EXPORT virtual error_code + touchBitSetLevel(bool & sendRecvBit, Level afterLevel); + + MaximInterfaceCore_EXPORT virtual error_code + writeByteSetLevel(uint_least8_t sendByte, Level afterLevel); + + MaximInterfaceCore_EXPORT virtual error_code + readByteSetLevel(uint_least8_t & recvByte, Level afterLevel); + + MaximInterfaceCore_EXPORT virtual error_code + writeBlock(span<const uint_least8_t> sendBuf); + + MaximInterfaceCore_EXPORT virtual error_code + readBlock(span<uint_least8_t> recvBuf); + + MaximInterfaceCore_EXPORT virtual error_code setSpeed(Speed newSpeed); + + MaximInterfaceCore_EXPORT virtual error_code setLevel(Level newLevel); + + MaximInterfaceCore_EXPORT virtual error_code triplet(TripletData & data); + +private: + OneWireMaster * master; +}; + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/Optional.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,307 @@ +/******************************************************************************* +* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_Optional +#define MaximInterfaceCore_Optional + +#include "None.hpp" +#include "SafeBool.hpp" + +// Include for std::swap. +#include <algorithm> +#include <utility> + +namespace MaximInterfaceCore { + +/// @brief Optional value container similar to std::optional. +/// @details +/// To prevent the need for aligned storage, this implementation imposes that +/// types must be DefaultConstructible, CopyConstructible, and CopyAssignable. +/// No exceptions are thrown when accessing a valueless Optional. +template <typename T> class Optional { +public: + typedef T value_type; + + Optional() : value_(), hasValue_(false) {} + + Optional(None) : value_(), hasValue_(false) {} + + Optional(const T & value) : value_(value), hasValue_(true) {} + + template <typename U> + explicit Optional(const Optional<U> & other) + : value_(other.value()), hasValue_(other.hasValue()) {} + + Optional & operator=(None) { + reset(); + return *this; + } + + template <typename U> Optional & operator=(const Optional<U> & other) { + if (hasValue_ || other.hasValue()) { + value_ = other.value(); + hasValue_ = other.hasValue(); + } + return *this; + } + + bool hasValue() const { return hasValue_; } + + operator SafeBool() const { return makeSafeBool(hasValue()); } + + const T & value() const { return value_; } + + T & value() { + return const_cast<T &>(static_cast<const Optional &>(*this).value()); + } + + const T & operator*() const { return value(); } + + T & operator*() { + return const_cast<T &>(static_cast<const Optional &>(*this).operator*()); + } + + const T * operator->() const { return &value(); } + + T * operator->() { + return const_cast<T *>(static_cast<const Optional &>(*this).operator->()); + } + + const T & valueOr(const T & defaultValue) const { + return hasValue() ? value() : defaultValue; + } + + void swap(Optional & other) { + if (hasValue_ || other.hasValue_) { + using std::swap; + swap(value_, other.value_); + swap(hasValue_, other.hasValue_); + } + } + + void reset() { + if (hasValue_) { + hasValue_ = false; + value_ = T(); + } + } + +private: + T value_; + bool hasValue_; +}; + +template <typename T> Optional<T> makeOptional(const T & value) { + return value; +} + +template <typename T> void swap(Optional<T> & lhs, Optional<T> & rhs) { + lhs.swap(rhs); +} + +template <typename T, typename U> +bool operator==(const Optional<T> & lhs, const Optional<U> & rhs) { + if (lhs.hasValue() != rhs.hasValue()) { + return false; + } + if (!lhs.hasValue()) { + return true; + } + return lhs.value() == rhs.value(); +} + +template <typename T, typename U> +bool operator!=(const Optional<T> & lhs, const Optional<U> & rhs) { + if (lhs.hasValue() != rhs.hasValue()) { + return true; + } + if (!lhs.hasValue()) { + return false; + } + return lhs.value() != rhs.value(); +} + +template <typename T, typename U> +bool operator<(const Optional<T> & lhs, const Optional<U> & rhs) { + if (!rhs.hasValue()) { + return false; + } + if (!lhs.hasValue()) { + return true; + } + return lhs.value() < rhs.value(); +} + +template <typename T, typename U> +bool operator<=(const Optional<T> & lhs, const Optional<U> & rhs) { + if (!lhs.hasValue()) { + return true; + } + if (!rhs.hasValue()) { + return false; + } + return lhs.value() <= rhs.value(); +} + +template <typename T, typename U> +bool operator>(const Optional<T> & lhs, const Optional<U> & rhs) { + if (!lhs.hasValue()) { + return false; + } + if (!rhs.hasValue()) { + return true; + } + return lhs.value() > rhs.value(); +} + +template <typename T, typename U> +bool operator>=(const Optional<T> & lhs, const Optional<U> & rhs) { + if (!rhs.hasValue()) { + return true; + } + if (!lhs.hasValue()) { + return false; + } + return lhs.value() >= rhs.value(); +} + +template <typename T> bool operator==(const Optional<T> & opt, None) { + return !opt.hasValue(); +} + +template <typename T> bool operator==(None, const Optional<T> & opt) { + return operator==(opt, none); +} + +template <typename T> bool operator!=(const Optional<T> & opt, None) { + return !operator==(opt, none); +} + +template <typename T> bool operator!=(None, const Optional<T> & opt) { + return operator!=(opt, none); +} + +template <typename T> bool operator<(const Optional<T> &, None) { + return false; +} + +template <typename T> bool operator<(None, const Optional<T> & opt) { + return opt.hasValue(); +} + +template <typename T> bool operator<=(const Optional<T> & opt, None) { + return !operator>(opt, none); +} + +template <typename T> bool operator<=(None, const Optional<T> & opt) { + return !operator>(none, opt); +} + +template <typename T> bool operator>(const Optional<T> & opt, None) { + return operator<(none, opt); +} + +template <typename T> bool operator>(None, const Optional<T> & opt) { + return operator<(opt, none); +} + +template <typename T> bool operator>=(const Optional<T> & opt, None) { + return !operator<(opt, none); +} + +template <typename T> bool operator>=(None, const Optional<T> & opt) { + return !operator<(none, opt); +} + +template <typename T, typename U> +bool operator==(const Optional<T> & opt, const U & value) { + return opt.hasValue() ? opt.value() == value : false; +} + +template <typename T, typename U> +bool operator==(const T & value, const Optional<U> & opt) { + return operator==(opt, value); +} + +template <typename T, typename U> +bool operator!=(const Optional<T> & opt, const U & value) { + return opt.hasValue() ? opt.value() != value : true; +} + +template <typename T, typename U> +bool operator!=(const T & value, const Optional<U> & opt) { + return operator!=(opt, value); +} + +template <typename T, typename U> +bool operator<(const Optional<T> & opt, const U & value) { + return opt.hasValue() ? opt.value() < value : true; +} + +template <typename T, typename U> +bool operator<(const T & value, const Optional<U> & opt) { + return opt.hasValue() ? value < opt.value() : false; +} + +template <typename T, typename U> +bool operator<=(const Optional<T> & opt, const U & value) { + return opt.hasValue() ? opt.value() <= value : true; +} + +template <typename T, typename U> +bool operator<=(const T & value, const Optional<U> & opt) { + return opt.hasValue() ? value <= opt.value() : false; +} + +template <typename T, typename U> +bool operator>(const Optional<T> & opt, const U & value) { + return opt.hasValue() ? opt.value() > value : false; +} + +template <typename T, typename U> +bool operator>(const T & value, const Optional<U> & opt) { + return opt.hasValue() ? value > opt.value() : true; +} + +template <typename T, typename U> +bool operator>=(const Optional<T> & opt, const U & value) { + return opt.hasValue() ? opt.value() >= value : false; +} + +template <typename T, typename U> +bool operator>=(const T & value, const Optional<U> & opt) { + return opt.hasValue() ? value >= opt.value() : true; +} + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/RomCommands.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,210 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include "RomCommands.hpp" + +namespace MaximInterfaceCore { + +enum RomCmd { + ReadRomCmd = 0x33, + MatchRomCmd = 0x55, + SearchRomCmd = 0xF0, + SkipRomCmd = 0xCC, + ResumeRomCmd = 0xA5, + OverdriveSkipRomCmd = 0x3C, + OverdriveMatchRomCmd = 0x69 +}; + +void skipCurrentFamily(SearchRomState & searchState) { + // Set the last discrepancy to last family discrepancy. + searchState.lastDiscrepancy = searchState.lastFamilyDiscrepancy; + // Clear the last family discrepancy. + searchState.lastFamilyDiscrepancy = 0; + // Check for end of list. + if (searchState.lastDiscrepancy == 0) { + searchState.lastDevice = true; + } +} + +error_code verifyRom(OneWireMaster & master, RomId::const_span romId) { + SearchRomState searchState(romId); + error_code result = searchRom(master, searchState); + if (result) { + return result; + } + // Check if same device found. + if (!equal(romId, make_span(searchState.romId))) { + result = make_error_code(OneWireMaster::NoSlaveError); + } + return result; +} + +error_code readRom(OneWireMaster & master, RomId::span romId) { + error_code result = master.reset(); + if (result) { + return result; + } + result = master.writeByte(ReadRomCmd); + if (result) { + return result; + } + result = master.readBlock(romId); + if (result) { + return result; + } + if (!valid(romId)) { + result = make_error_code(OneWireMaster::NoSlaveError); + } + return result; +} + +error_code skipRom(OneWireMaster & master) { + error_code result = master.reset(); + if (result) { + return result; + } + result = master.writeByte(SkipRomCmd); + return result; +} + +error_code matchRom(OneWireMaster & master, RomId::const_span romId) { + error_code result = master.reset(); + if (result) { + return result; + } + result = master.writeByte(MatchRomCmd); + if (result) { + return result; + } + result = master.writeBlock(romId); + return result; +} + +error_code overdriveSkipRom(OneWireMaster & master) { + error_code result = master.reset(); + if (result) { + return result; + } + result = master.writeByte(OverdriveSkipRomCmd); + if (result) { + return result; + } + result = master.setSpeed(OneWireMaster::OverdriveSpeed); + return result; +} + +error_code overdriveMatchRom(OneWireMaster & master, RomId::const_span romId) { + error_code result = master.reset(); + if (result) { + return result; + } + result = master.writeByte(OverdriveMatchRomCmd); + if (result) { + return result; + } + result = master.setSpeed(OneWireMaster::OverdriveSpeed); + if (result) { + return result; + } + result = master.writeBlock(romId); + return result; +} + +error_code resumeRom(OneWireMaster & master) { + error_code result = master.reset(); + if (result) { + return result; + } + result = master.writeByte(ResumeRomCmd); + return result; +} + +error_code searchRom(OneWireMaster & master, SearchRomState & searchState) { + if (searchState.lastDevice) { + searchState = SearchRomState(); + } + + error_code result = master.reset(); + if (result) { + return result; + } + result = master.writeByte(SearchRomCmd); + if (result) { + return result; + } + + SearchRomState newSearchState; + newSearchState.lastFamilyDiscrepancy = searchState.lastFamilyDiscrepancy; + for (int idBitNumber = 1; idBitNumber <= 64; ++idBitNumber) { + const int idByteNumber = (idBitNumber - 1) / 8; + const unsigned int idBitMask = 1 << ((idBitNumber - 1) % 8); + + OneWireMaster::TripletData tripletData; + if (idBitNumber == searchState.lastDiscrepancy) { + tripletData.writeBit = 1; + } else if (idBitNumber > searchState.lastDiscrepancy) { + tripletData.writeBit = 0; + } else { // idBitNumber < searchState.lastDiscrepancy + tripletData.writeBit = + (searchState.romId[idByteNumber] & idBitMask) == idBitMask; + } + + result = master.triplet(tripletData); + if (result) { + return result; + } + if (tripletData.readBit && tripletData.readBitComplement) { + return make_error_code(OneWireMaster::NoSlaveError); + } + + if (tripletData.writeBit) { + newSearchState.romId[idByteNumber] |= idBitMask; + } else if (!tripletData.readBit && !tripletData.readBitComplement) { + newSearchState.lastDiscrepancy = idBitNumber; + if (idBitNumber <= 8) { + newSearchState.lastFamilyDiscrepancy = idBitNumber; + } + } + } + + if (valid(newSearchState.romId)) { + if (newSearchState.lastDiscrepancy == 0) { + newSearchState.lastDevice = true; + } + searchState = newSearchState; + } else { + result = make_error_code(OneWireMaster::NoSlaveError); + } + return result; +} + +} // namespace MaximInterfaceCore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/RomCommands.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,136 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +/// @file +/// @brief ROM Commands for enumerating and selecting 1-Wire devices. + +#ifndef MaximInterfaceCore_RomCommands +#define MaximInterfaceCore_RomCommands + +#include <stdint.h> +#include "Algorithm.hpp" +#include "Config.hpp" +#include "OneWireMaster.hpp" +#include "RomId.hpp" + +namespace MaximInterfaceCore { + +/// State used by Search ROM command. +struct SearchRomState { + RomId::array romId; + int_least8_t lastDiscrepancy; + int_least8_t lastFamilyDiscrepancy; + bool lastDevice; + + SearchRomState() + : romId(), lastDiscrepancy(0), lastFamilyDiscrepancy(0), + lastDevice(false) {} + + explicit SearchRomState(RomId::const_span romId) + : lastDiscrepancy(64), lastFamilyDiscrepancy(0), lastDevice(false) { + copy(romId, make_span(this->romId)); + } + + explicit SearchRomState(RomId::element familyCode) + : romId(), lastDiscrepancy(64), lastFamilyDiscrepancy(0), + lastDevice(false) { + setFamilyCode(romId, familyCode); + } +}; + +/// @brief +/// Set the search state to skip the current device family on the next +/// Search ROM command. +MaximInterfaceCore_EXPORT void skipCurrentFamily(SearchRomState & searchState); + +/// Verify that the device with the specified ROM ID is present. +MaximInterfaceCore_EXPORT error_code verifyRom(OneWireMaster & master, + RomId::const_span romId); + +/// @brief Use Read ROM command to read ROM ID from device on bus. +/// @note +/// Only use this command with a single-drop bus. +/// Data collisions will occur if there is more than one device on the bus. +/// @param master 1-Wire master for operation. +/// @param[out] romId ROM ID read from device. +MaximInterfaceCore_EXPORT error_code readRom(OneWireMaster & master, + RomId::span romId); + +/// @brief Issue Skip ROM command on bus. +/// @note +/// Only use this command with a single-drop bus. +/// Data collisions will occur if there is more than one device on the bus. +MaximInterfaceCore_EXPORT error_code skipRom(OneWireMaster & master); + +/// @brief Use the Match ROM command to select the device by its known ID. +/// @note +/// This command causes all devices supporting Overdrive mode to switch to +/// Overdrive timing. +/// @param master 1-Wire master for operation. +/// @param[in] romId ROM ID of device to select. +MaximInterfaceCore_EXPORT error_code matchRom(OneWireMaster & master, + RomId::const_span romId); + +/// @brief Issue Overdrive Skip ROM command on bus. +/// @note +/// This command causes all devices supporting Overdrive mode to switch to +/// Overdrive timing. +/// @note +/// Only use this command with a single-drop bus. +/// Data collisions will occur if there is more than one device on the bus. +MaximInterfaceCore_EXPORT error_code overdriveSkipRom(OneWireMaster & master); + +/// @brief +/// Use the Overdrive Match ROM command to select the device by its known ID. +/// @param master 1-Wire master for operation. +/// @param[in] romId ROM ID of device to select. +MaximInterfaceCore_EXPORT error_code overdriveMatchRom(OneWireMaster & master, + RomId::const_span romId); + +/// @brief Perform a Resume ROM command on bus. +/// @details +/// Resumes communication with the last device selected through a Match ROM or +/// Search ROM operation. +MaximInterfaceCore_EXPORT error_code resumeRom(OneWireMaster & master); + +/// @brief Find device on the 1-Wire bus. +/// @details +/// This command uses the Search ROM command to enumerate all 1-Wire devices in +/// sequence. Begin with a new search state and continue using the same search +/// state until the last device flag is set which indicates that all devices +/// have been discovered. +MaximInterfaceCore_EXPORT error_code searchRom(OneWireMaster & master, + SearchRomState & searchState); + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/RomId.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,80 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_RomId +#define MaximInterfaceCore_RomId + +#include "array_span.hpp" +#include "crc.hpp" + +namespace MaximInterfaceCore { + +/// Standard container for a 1-Wire ROM ID. +typedef array_span<uint_least8_t, 8> RomId; + +/// @name Family Code +/// @{ + +/// Get the Family Code byte. +inline RomId::element familyCode(RomId::const_span romId) { return romId[0]; } + +/// Set the Family Code byte. +inline void setFamilyCode(RomId::span romId, RomId::element familyCode) { + romId[0] = familyCode; +} + +/// @} + +/// @name CRC8 +/// @{ + +/// Get the CRC8 byte. +inline RomId::element crc8(RomId::const_span romId) { + return *romId.last<1>().data(); +} + +/// Set the CRC8 byte. +inline void setCrc8(RomId::span romId, RomId::element crc8) { + *romId.last<1>().data() = crc8; +} + +/// @} + +/// @brief Check if the ROM ID is valid (Family Code and CRC8 are both valid). +/// @returns True if the ROM ID is valid. +inline bool valid(RomId::const_span romId) { + return calculateCrc8(romId.first(romId.size() - 1)) == crc8(romId); +} + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/RunCommand.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,210 @@ +/******************************************************************************* +* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include "crc.hpp" +#include "Error.hpp" +#include "I2CMaster.hpp" +#include "OneWireMaster.hpp" +#include "RunCommand.hpp" +#include "Sleep.hpp" + +namespace MaximInterfaceCore { + +const error_category & RunCommandWithOneWireMaster::errorCategory() { + static class : public error_category { + public: + virtual const char * name() const { return "RunCommandWithOneWireMaster"; } + + virtual std::string message(int condition) const { + switch (condition) { + case CrcError: + return "CRC Error"; + + case InvalidResponseError: + return "Invalid Response Error"; + } + return defaultErrorMessage(condition); + } + } instance; + return instance; +} + +error_code RunCommandWithOneWireMaster:: +operator()(span<const uint_least8_t> request, int delayTime, + span<uint_least8_t> & response) const { + // Write request. + error_code result = selectRom(*master); + if (result) { + return result; + } + uint_least8_t xpcBuffer[2] = {0x66, + static_cast<uint_least8_t>(request.size())}; + result = master->writeBlock(xpcBuffer); + if (result) { + return result; + } + result = master->writeBlock(request); + if (result) { + return result; + } + uint_fast16_t expectedCrc = + calculateCrc16(calculateCrc16(xpcBuffer), request) ^ 0xFFFFu; + result = master->readBlock(xpcBuffer); + if (result) { + return result; + } + if (expectedCrc != + ((static_cast<uint_fast16_t>(xpcBuffer[1]) << 8) | xpcBuffer[0])) { + return make_error_code(CrcError); + } + result = master->writeBytePower(0xAA); + if (result) { + return result; + } + + // Wait for device to process. + sleep->invoke(delayTime); + + // Read response. + result = master->setLevel(OneWireMaster::NormalLevel); + if (result) { + return result; + } + result = master->readBlock(xpcBuffer); + if (result) { + return result; + } + if (xpcBuffer[1] > response.size()) { + return make_error_code(InvalidResponseError); + } + response = response.first(xpcBuffer[1]); + result = master->readBlock(response); + if (result) { + return result; + } + expectedCrc = + calculateCrc16(calculateCrc16(make_span(xpcBuffer + 1, 1)), response) ^ + 0xFFFFu; + result = master->readBlock(xpcBuffer); + if (result) { + return result; + } + if (expectedCrc != + ((static_cast<uint_fast16_t>(xpcBuffer[1]) << 8) | xpcBuffer[0])) { + return make_error_code(CrcError); + } + return result; +} + +const error_category & RunCommandWithI2CMaster::errorCategory() { + static class : public error_category { + public: + virtual const char * name() const { return "RunCommandWithI2CMaster"; } + + virtual std::string message(int condition) const { + switch (condition) { + case InvalidResponseError: + return "Invalid Response Error"; + } + return defaultErrorMessage(condition); + } + } instance; + return instance; +} + +error_code RunCommandWithI2CMaster:: +operator()(span<const uint_least8_t> request, int delayTime, + span<uint_least8_t> & response) const { + // Write request. + error_code result = master->start(address_); + if (result == make_error_condition(I2CMaster::NackError) && address_ != 0) { + result = master->start(0); + } + if (result) { + master->stop(); + return result; + } + if (!request.empty()) { + result = master->writeByte(request[0]); + if (result) { + master->stop(); + return result; + } + request = request.subspan(1); + if (!request.empty()) { + result = master->writeByte(static_cast<uint_least8_t>(request.size())); + if (result) { + master->stop(); + return result; + } + result = master->writeBlock(request); + if (result) { + master->stop(); + return result; + } + } + } + result = master->stop(); + if (result) { + return result; + } + + // Wait for device to process. + sleep->invoke(delayTime); + + // Read response. + result = master->start(address_ | 1); + if (result) { + master->stop(); + return result; + } + uint_least8_t length; + result = master->readByte(I2CMaster::Ack, length); + if (result) { + master->stop(); + return result; + } + if (length > response.size()) { + master->stop(); + return make_error_code(InvalidResponseError); + } + response = response.first(length); + result = master->readBlock(I2CMaster::Nack, response); + if (result) { + master->stop(); + return result; + } + result = master->stop(); + return result; +} + +} // namespace MaximInterfaceCore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/RunCommand.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,120 @@ +/******************************************************************************* +* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_RunCommand +#define MaximInterfaceCore_RunCommand + +#include "Config.hpp" +#include "Function.hpp" +#include "SelectRom.hpp" +#include "span.hpp" +#include "system_error.hpp" + +namespace MaximInterfaceCore { + +class I2CMaster; +class OneWireMaster; +class Sleep; + +typedef Function<error_code(span<const uint_least8_t>, int, + span<uint_least8_t> &)> + RunCommand; + +class RunCommandWithOneWireMaster { +public: + typedef RunCommand::result_type result_type; + + enum ErrorValue { CrcError = 1, InvalidResponseError }; + MaximInterfaceCore_EXPORT static const error_category & errorCategory(); + + RunCommandWithOneWireMaster(Sleep & sleep, OneWireMaster & master, + const SelectRom & selectRom) + : selectRom(selectRom), master(&master), sleep(&sleep) {} + + void setSleep(Sleep & sleep) { this->sleep = &sleep; } + + void setMaster(OneWireMaster & master) { this->master = &master; } + + void setSelectRom(const SelectRom & selectRom) { + this->selectRom = selectRom; + } + + MaximInterfaceCore_EXPORT error_code + operator()(span<const uint_least8_t> request, int delayTime, + span<uint_least8_t> & response) const; + +private: + SelectRom selectRom; + OneWireMaster * master; + const Sleep * sleep; +}; + +inline error_code make_error_code(RunCommandWithOneWireMaster::ErrorValue e) { + return error_code(e, RunCommandWithOneWireMaster::errorCategory()); +} + +class RunCommandWithI2CMaster { +public: + typedef RunCommand::result_type result_type; + + enum ErrorValue { InvalidResponseError = 1 }; + MaximInterfaceCore_EXPORT static const error_category & errorCategory(); + + RunCommandWithI2CMaster(Sleep & sleep, I2CMaster & master, + uint_least8_t address) + : sleep(&sleep), master(&master), address_(address & 0xFE) {} + + void setSleep(Sleep & sleep) { this->sleep = &sleep; } + + void setMaster(I2CMaster & master) { this->master = &master; } + + uint_least8_t address() const { return address_; } + + void setAddress(uint_least8_t address) { address_ = address & 0xFE; } + + MaximInterfaceCore_EXPORT error_code + operator()(span<const uint_least8_t> request, int delayTime, + span<uint_least8_t> & response) const; + +private: + const Sleep * sleep; + I2CMaster * master; + uint_least8_t address_; +}; + +inline error_code make_error_code(RunCommandWithI2CMaster::ErrorValue e) { + return error_code(e, RunCommandWithI2CMaster::errorCategory()); +} + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/SafeBool.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,65 @@ +/******************************************************************************* +* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_SafeBool +#define MaximInterfaceCore_SafeBool + +#include <stddef.h> +#include "Unconstructible.hpp" + +namespace MaximInterfaceCore { +namespace detail { + +// Implement SafeBool as a member function pointer since some compilers allow +// function pointer to void pointer conversion. +struct SafeBoolHelper : Unconstructible { + void trueValue() const {} +}; + +} // namespace detail + +/// @brief Type definition for SafeBool. +/// @details +/// SafeBool is a boolean type that eliminates many error-prone implicit +/// conversions allowed by the fundamental bool type. +/// @note +/// SafeBool can be used to add an explicit bool conversion operator to a type. +typedef void (detail::SafeBoolHelper::*SafeBool)() const; + +/// Constructor for SafeBool. +inline SafeBool makeSafeBool(bool value) { + return value ? &detail::SafeBoolHelper::trueValue : NULL; +} + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/Segment.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,135 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_Segment +#define MaximInterfaceCore_Segment + +#include <iterator> +#include <utility> +#include "type_traits.hpp" + +namespace MaximInterfaceCore { + +/// @brief +/// Advances a given iterator by a given number of elements with bounds checking. +/// @tparam InputIt Must meet the requirements of InputIterator. +/// @param[in,out] it Iterator to advance. +/// @param bound +/// Past-the-end boundary iterator. If distance is positive, bound must be +/// reachable by incrementing the given iterator. If distance is negative, bound +/// must be reachable by decrementing the given iterator. +/// @param distance +/// Number of elements to advance the given iterator. If distance is positive, +/// the given iterator is incremented. If distance is negative, the given +/// iterator is decremented, and InputIt must meet the requirements of +/// BidirectionalIterator. +/// @returns The number of elements that the given iterator was advanced. +template <typename InputIt> +typename std::iterator_traits<InputIt>::difference_type checkedAdvance( + InputIt & it, const InputIt bound, + typename std::iterator_traits<InputIt>::difference_type distance) { + typedef + typename std::iterator_traits<InputIt>::difference_type difference_type; + + // Use constant-time operations if InputIt is a random access iterator. + if (is_same<typename std::iterator_traits<InputIt>::iterator_category, + std::random_access_iterator_tag>::value) { + const difference_type boundDistance = std::distance(it, bound); + if (boundDistance >= 0) { + if (distance > boundDistance) { + distance = boundDistance; + } else if (distance < 0) { + distance = 0; + } + } else { + if (distance < boundDistance) { + distance = boundDistance; + } else if (distance > 0) { + distance = 0; + } + } + std::advance(it, distance); + } else { + const difference_type startingDistance = distance; + while (distance != 0 && it != bound) { + if (distance > 0) { + ++it; + --distance; + } else { + --it; + ++distance; + } + } + if (startingDistance > 0) { + distance = startingDistance - distance; + } else { + distance = startingDistance + distance; + } + } + return distance; +} + +/// @brief Locates an iterator sub-range using segment number addressing. +/// @details +/// Useful for devices that divide the memory space into uniform chunks such as +/// pages and segments. +/// @tparam ForwardIt Must meet the requirements of ForwardIterator. +/// @param begin Beginning of the input data range. +/// @param end End of the input data range. +/// @param segmentSize Number of elements contained in a segment. +/// @param segmentNum Zero-indexed number of the desired segment. +/// @returns +/// Pair of iterators representing the sub-range of the segment within +/// the input range. If the segment does not exist within the input range, both +/// iterators in the pair are set to the end iterator of the input range. +template <typename ForwardIt, typename Index> +std::pair<ForwardIt, ForwardIt> createSegment( + ForwardIt begin, const ForwardIt end, + const typename std::iterator_traits<ForwardIt>::difference_type segmentSize, + Index segmentNum) { + ForwardIt segmentEnd = begin; + typename std::iterator_traits<ForwardIt>::difference_type lastSegmentSize = + checkedAdvance(segmentEnd, end, segmentSize); + while (segmentNum > 0 && segmentEnd != end) { + begin = segmentEnd; + lastSegmentSize = checkedAdvance(segmentEnd, end, segmentSize); + --segmentNum; + } + if (segmentNum > 0 || lastSegmentSize != segmentSize) { + begin = segmentEnd; + } + return std::make_pair(begin, segmentEnd); +} + +} // namespace MaximInterfaceCore + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/SelectRom.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,52 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include "SelectRom.hpp" + +namespace MaximInterfaceCore { + +error_code SelectMatchRom::operator()(OneWireMaster & master) const { + return matchRom(master, romId_); +} + +error_code SelectMatchRomWithResume::operator()(OneWireMaster & master) const { + error_code result; + if (romId_ == data->lastRomId) { + result = resumeRom(master); + } else { + result = matchRom(master, romId_); + data->lastRomId = romId_; + } + return result; +} + +} // namespace MaximInterfaceCore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/SelectRom.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,100 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_SelectRom +#define MaximInterfaceCore_SelectRom + +#include "Config.hpp" +#include "Function.hpp" +#include "RomCommands.hpp" +#include "RomId.hpp" +#include "system_error.hpp" + +namespace MaximInterfaceCore { + +class OneWireMaster; + +/// Selects a 1-Wire device on the bus for communication. +typedef Function<error_code(OneWireMaster &)> SelectRom; + +/// Selector for a multidrop 1-Wire bus. +class SelectMatchRom { +public: + typedef SelectRom::argument_type argument_type; + typedef SelectRom::result_type result_type; + + explicit SelectMatchRom(RomId::const_span romId) { setRomId(romId); } + + RomId::const_span romId() const { return romId_; } + + void setRomId(RomId::const_span romId) { copy(romId, make_span(romId_)); } + + MaximInterfaceCore_EXPORT error_code operator()(OneWireMaster & master) const; + +private: + RomId::array romId_; +}; + +/// @brief +/// Selector for a multidrop 1-Wire bus where slaves support the Resume ROM +/// command. +class SelectMatchRomWithResume { +public: + typedef SelectRom::argument_type argument_type; + typedef SelectRom::result_type result_type; + + struct SharedData { + SharedData() : lastRomId() {} + RomId::array lastRomId; + }; + + SelectMatchRomWithResume(SharedData & data, RomId::const_span romId) + : data(&data) { + setRomId(romId); + } + + void setSharedData(SharedData & data) { this->data = &data; } + + RomId::const_span romId() const { return romId_; } + + void setRomId(RomId::const_span romId) { copy(romId, make_span(romId_)); } + + MaximInterfaceCore_EXPORT error_code operator()(OneWireMaster & master) const; + +private: + SharedData * data; + RomId::array romId_; +}; + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/SerialPort.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,59 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_SerialPort +#define MaximInterfaceCore_SerialPort + +#include <string> +#include "Uart.hpp" + +namespace MaximInterfaceCore { + +class SerialPort : public Uart { +public: + /// Connect a specified COM port. + virtual error_code connect(const std::string & portName) = 0; + + /// Disconnect from the current port. + virtual error_code disconnect() = 0; + + /// @brief Check if currently connected to a port. + /// @returns True if connected. + virtual bool connected() const = 0; + + /// Get the currently connected port name. + virtual std::string portName() const = 0; +}; + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/Sleep.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,47 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_Sleep +#define MaximInterfaceCore_Sleep + +namespace MaximInterfaceCore { + +class Sleep { +public: + virtual ~Sleep() {} + virtual void invoke(int ms) const = 0; + void operator()(int ms) const { invoke(ms); } +}; + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/SleepDecorator.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,39 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include "SleepDecorator.hpp" + +namespace MaximInterfaceCore { + +void SleepDecorator::invoke(int ms) const { sleep->invoke(ms); } + +} // namespace MaximInterfaceCore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/SleepDecorator.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,55 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_SleepDecorator +#define MaximInterfaceCore_SleepDecorator + +#include "Config.hpp" +#include "Sleep.hpp" + +namespace MaximInterfaceCore { + +class SleepDecorator : public Sleep { +protected: + explicit SleepDecorator(Sleep & sleep) : sleep(&sleep) {} + +public: + void setSleep(Sleep & sleep) { this->sleep = &sleep; } + MaximInterfaceCore_EXPORT virtual void invoke(int ms) const; + +private: + const Sleep * sleep; +}; + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/Uart.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,76 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include "Error.hpp" +#include "Uart.hpp" + +namespace MaximInterfaceCore { + +error_code Uart::writeBlock(span<const uint_least8_t> data) { + error_code result; + for (span<const uint_least8_t>::index_type i = 0; + i < data.size() && !result; ++i) { + result = writeByte(data[i]); + } + return result; +} + +error_code Uart::readBlock(span<uint_least8_t> data) { + error_code result; + for (span<uint_least8_t>::index_type i = 0; i < data.size() && !result; ++i) { + result = readByte(data[i]); + } + return result; +} + +const error_category & Uart::errorCategory() { + static class : public error_category { + public: + virtual const char * name() const { return "UART"; } + + virtual std::string message(int condition) const { + switch (condition) { + case TimeoutError: + return "Timeout Error"; + + case OverrunError: + return "Overrun Error"; + + default: + return defaultErrorMessage(condition); + } + } + } instance; + return instance; +} + +} // namespace MaximInterfaceCore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/Uart.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,95 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_Uart +#define MaximInterfaceCore_Uart + +#include <stdint.h> +#include "Config.hpp" +#include "span.hpp" +#include "system_error.hpp" + +namespace MaximInterfaceCore { + +/// Universal asynchronous receiver-transmitter interface. +class Uart { +public: + enum ErrorValue { + TimeoutError = 1, ///< Read operation aborted due to timeout. + OverrunError ///< Received data lost due to read buffer overrun. + }; + + virtual ~Uart() {} + + /// Set the baud rate of the port in Hz. + virtual error_code setBaudRate(int_least32_t baudRate) = 0; + + /// Generate a break condition on the port for a small amount of time. + virtual error_code sendBreak() = 0; + + /// Clear all received data that was buffered. + virtual error_code clearReadBuffer() = 0; + + /// Writes a byte of data to the port. + virtual error_code writeByte(uint_least8_t data) = 0; + + /// Writes a block of data to the port. + MaximInterfaceCore_EXPORT virtual error_code + writeBlock(span<const uint_least8_t> data); + + /// @brief + /// Reads a byte of data from the port. Block until data is received or a + /// timeout is reached. + /// @param[out] data Data read from the port if successful. + virtual error_code readByte(uint_least8_t & data) = 0; + + /// @brief + /// Read a block of data from the port. Block until data is received or a + /// timeout is reached. + /// @param[out] data Data read from the port if successful. + MaximInterfaceCore_EXPORT virtual error_code + readBlock(span<uint_least8_t> data); + + MaximInterfaceCore_EXPORT static const error_category & errorCategory(); +}; + +inline error_code make_error_code(Uart::ErrorValue e) { + return error_code(e, Uart::errorCategory()); +} + +inline error_condition make_error_condition(Uart::ErrorValue e) { + return error_condition(e, Uart::errorCategory()); +} + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/Unconstructible.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,45 @@ +/******************************************************************************* +* Copyright (C) 2019 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_Unconstructible +#define MaximInterfaceCore_Unconstructible + +namespace MaximInterfaceCore { + +struct Unconstructible { +private: + Unconstructible(); // deleted +}; + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/Uncopyable.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,50 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_Uncopyable +#define MaximInterfaceCore_Uncopyable + +namespace MaximInterfaceCore { + +class Uncopyable { +protected: + Uncopyable() {} + ~Uncopyable() {} + +private: + Uncopyable(const Uncopyable &); // deleted + const Uncopyable & operator=(const Uncopyable &); // deleted +}; + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/WriteMessage.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,46 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_WriteMessage +#define MaximInterfaceCore_WriteMessage + +#include <string> +#include "Function.hpp" + +namespace MaximInterfaceCore { + +/// Writes a message string to an output. +typedef Function<void(const std::string &)> WriteMessage; + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/array.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,191 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_array +#define MaximInterfaceCore_array + +#include <stddef.h> +#include <stdint.h> +#include <algorithm> +#include <iterator> + +namespace MaximInterfaceCore { + +/// Generic array class similar to std::array. +template <typename T, size_t N> class array { +public: + typedef T value_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef value_type & reference; + typedef const value_type & const_reference; + typedef value_type * pointer; + typedef const value_type * const_pointer; + typedef pointer iterator; + typedef const_pointer const_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + + /// @name Element access + /// @{ + + reference operator[](size_type pos) { + return const_cast<reference>( + static_cast<const array &>(*this).operator[](pos)); + } + + const_reference operator[](size_type pos) const { return data()[pos]; } + + reference front() { + return const_cast<reference>(static_cast<const array &>(*this).front()); + } + + const_reference front() const { return operator[](0); } + + reference back() { + return const_cast<reference>(static_cast<const array &>(*this).back()); + } + + const_reference back() const { return operator[](size() - 1); } + + pointer data() { + return const_cast<pointer>(static_cast<const array &>(*this).data()); + } + + const_pointer data() const { return _buffer; } + + /// @} + + /// @name Iterators + /// @{ + + iterator begin() { + return const_cast<iterator>(static_cast<const array &>(*this).cbegin()); + } + + const_iterator begin() const { return cbegin(); } + + const_iterator cbegin() const { return data(); } + + iterator end() { + return const_cast<iterator>(static_cast<const array &>(*this).cend()); + } + + const_iterator end() const { return cend(); } + + const_iterator cend() const { return cbegin() + size(); } + + reverse_iterator rbegin() { return reverse_iterator(end()); } + + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + + const_reverse_iterator crbegin() const { return rbegin(); } + + reverse_iterator rend() { return reverse_iterator(begin()); } + + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + + const_reverse_iterator crend() const { return rend(); } + + /// @} + + /// @name Capacity + /// @{ + + static bool empty() { return size() == 0; } + + static size_type size() { return N; } + + static size_type max_size() { return size(); } + + /// Alternative to size() when a constant expression is required. + static const size_type csize = N; + + /// @} + + /// @name Operations + /// @{ + + void fill(const_reference value) { std::fill(begin(), end(), value); } + + void swap(array & other) { std::swap_ranges(begin(), end(), other.begin()); } + + /// @} + + /// @private + /// @note Implementation detail set public to allow aggregate initialization. + T _buffer[N]; +}; + +template <typename T, size_t N> +inline bool operator==(const array<T, N> & lhs, const array<T, N> & rhs) { + return std::equal(lhs.begin(), lhs.end(), rhs.begin()); +} + +template <typename T, size_t N> +inline bool operator!=(const array<T, N> & lhs, const array<T, N> & rhs) { + return !operator==(lhs, rhs); +} + +template <typename T, size_t N> +inline bool operator<(const array<T, N> & lhs, const array<T, N> & rhs) { + return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), + rhs.end()); +} + +template <typename T, size_t N> +inline bool operator>(const array<T, N> & lhs, const array<T, N> & rhs) { + return operator<(rhs, lhs); +} + +template <typename T, size_t N> +inline bool operator<=(const array<T, N> & lhs, const array<T, N> & rhs) { + return !operator>(lhs, rhs); +} + +template <typename T, size_t N> +inline bool operator>=(const array<T, N> & lhs, const array<T, N> & rhs) { + return !operator<(lhs, rhs); +} + +template <typename T, size_t N> +inline void swap(array<T, N> & lhs, array<T, N> & rhs) { + lhs.swap(rhs); +} + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/array_span.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,61 @@ +/******************************************************************************* +* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_array_span +#define MaximInterfaceCore_array_span + +#include "array.hpp" +#include "span.hpp" +#include "type_traits.hpp" +#include "Unconstructible.hpp" + +namespace MaximInterfaceCore { + +/// @brief +/// Defines a standard set of types for data fields that are represented as a +/// fixed-size array of elements. +/// @tparam T A const qualifier is not allowed. +template <typename T, size_t N> struct array_span : Unconstructible { + typedef typename remove_volatile<T>::type element; + static const size_t size = N; + + typedef MaximInterfaceCore::array<element, N> array; + typedef MaximInterfaceCore::span<const T, N> const_span; + typedef MaximInterfaceCore::span<T, N> span; +}; + +// Specialization for "const T" is not defined. +template <typename T, size_t N> struct array_span<const T, N>; + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/crc.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,81 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include "crc.hpp" + +namespace MaximInterfaceCore { + +uint_fast8_t calculateCrc8(uint_fast8_t crc, uint_fast8_t data) { + // See Application Note 27 + crc = (crc ^ data) & 0xFF; + for (int i = 0; i < 8; ++i) { + if (crc & 1) { + crc = (crc >> 1) ^ 0x8C; + } else { + crc = (crc >> 1); + } + } + return crc; +} + +uint_fast8_t calculateCrc8(uint_fast8_t crc, span<const uint_least8_t> data) { + for (span<const uint_least8_t>::index_type i = 0; i < data.size(); ++i) { + crc = calculateCrc8(crc, data[i]); + } + return crc; +} + +uint_fast16_t calculateCrc16(uint_fast16_t crc, uint_fast8_t data) { + static const uint_least8_t oddparity[] = {0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0}; + + uint_fast16_t data16 = (data ^ crc) & 0xFF; + crc = (crc >> 8) & 0xFF; + if (oddparity[data16 & 0xF] ^ oddparity[data16 >> 4]) { + crc ^= 0xC001u; + } + data16 <<= 6; + crc ^= data16; + data16 <<= 1; + crc ^= data16; + return crc; +} + +uint_fast16_t calculateCrc16(uint_fast16_t crc, + span<const uint_least8_t> data) { + for (span<const uint_least8_t>::index_type i = 0; i < data.size(); ++i) { + crc = calculateCrc16(crc, data[i]); + } + return crc; +} + +} // namespace MaximInterfaceCore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/crc.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,107 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_crc +#define MaximInterfaceCore_crc + +#include <stddef.h> +#include <stdint.h> +#include "Config.hpp" +#include "span.hpp" + +namespace MaximInterfaceCore { + +/// @brief Perform a CRC8 calculation. +/// @param crc Beginning state of the CRC generator. +/// @param data Data to pass though the CRC generator. +/// @returns The calculated CRC8. +MaximInterfaceCore_EXPORT uint_fast8_t calculateCrc8(uint_fast8_t crc, + uint_fast8_t data); + +/// @brief +/// Perform a CRC8 calculation with the CRC generator initialized to zero. +/// @param data Data to pass though the CRC generator. +/// @returns The calculated CRC8. +inline uint_fast8_t calculateCrc8(uint_fast8_t data) { + return calculateCrc8(0, data); +} + +/// @brief Perform a CRC8 calculation with variable length data. +/// @param crc Beginning state of the CRC generator. +/// @param[in] data Data array to pass through the CRC generator. +/// @returns The calculated CRC8. +MaximInterfaceCore_EXPORT uint_fast8_t +calculateCrc8(uint_fast8_t crc, span<const uint_least8_t> data); + +/// @brief +/// Perform a CRC8 calculation with variable length data and the CRC generator +/// initialized to zero. +/// @param[in] data Data array to pass through the CRC generator. +/// @returns The calculated CRC8. +inline uint_fast8_t calculateCrc8(span<const uint_least8_t> data) { + return calculateCrc8(0, data); +} + +/// @brief Perform a CRC16 calculation. +/// @param crc Beginning state of the CRC generator. +/// @param data Data to pass though the CRC generator. +/// @returns The calculated CRC16. +MaximInterfaceCore_EXPORT uint_fast16_t calculateCrc16(uint_fast16_t crc, + uint_fast8_t data); + +/// @brief +/// Perform a CRC16 calculation with the CRC generator initialized to zero. +/// @param data Data to pass though the CRC generator. +/// @returns The calculated CRC16. +inline uint_fast16_t calculateCrc16(uint_fast8_t data) { + return calculateCrc16(0, data); +} + +/// @brief Perform a CRC16 calculation with variable length data. +/// @param crc Beginning state of the CRC generator. +/// @param[in] data Data array to pass through the CRC generator. +/// @returns The calculated CRC16. +MaximInterfaceCore_EXPORT uint_fast16_t +calculateCrc16(uint_fast16_t crc, span<const uint_least8_t> data); + +/// @brief +/// Perform a CRC16 calculation with variable length data and the CRC generator +/// initialized to zero. +/// @param[in] data Data array to pass through the CRC generator. +/// @returns The calculated CRC16. +inline uint_fast16_t calculateCrc16(span<const uint_least8_t> data) { + return calculateCrc16(0, data); +} + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/span.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,370 @@ +/******************************************************************************* +* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_span +#define MaximInterfaceCore_span + +#include <stddef.h> +#include <stdint.h> +#include <iterator> +#include <vector> +#include "array.hpp" +#include "type_traits.hpp" + +namespace MaximInterfaceCore { + +/// Differentiates spans of static and dynamic extent. +static const size_t dynamic_extent = SIZE_MAX; + +/// @brief +/// Generic memory span class similar to gsl::span and the proposed std::span. +/// @note +/// Separate implementations are used for spans of static and dynamic extent. +template <typename T, size_t Extent = dynamic_extent> class span; + +namespace detail { + +// Implementation of common span functionality using CRTP. +template <template <typename, size_t = MaximInterfaceCore::dynamic_extent> + class span, + typename T, size_t Extent> +class span_base { +public: + typedef T element_type; + typedef typename remove_cv<element_type>::type value_type; + typedef size_t index_type; + typedef ptrdiff_t difference_type; + typedef element_type * pointer; + typedef const element_type * const_pointer; + typedef element_type & reference; + typedef const element_type & const_reference; + typedef element_type * iterator; + typedef const element_type * const_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + + static const index_type extent = Extent; + +protected: + span_base(pointer data) : data_(data) {} + ~span_base() {} + +public: + /// @name Iterators + /// @{ + + iterator begin() const { + return const_cast<iterator>(static_cast<const span_base &>(*this).cbegin()); + } + + const_iterator cbegin() const { return data(); } + + iterator end() const { + return const_cast<iterator>(static_cast<const span_base &>(*this).cend()); + } + + const_iterator cend() const { return cbegin() + size(); } + + reverse_iterator rbegin() const { return reverse_iterator(end()); } + + const_reverse_iterator crbegin() const { + return const_reverse_iterator(cend()); + } + + reverse_iterator rend() const { return reverse_iterator(begin()); } + + const_reverse_iterator crend() const { + return const_reverse_iterator(cbegin()); + } + + /// @} + + /// @name Element access + /// @{ + + reference front() const { return operator[](0); } + + reference back() const { return operator[](size() - 1); } + + reference operator[](index_type idx) const { return data()[idx]; } + + pointer data() const { return data_; } + + /// @} + + /// @name Subviews + /// @{ + + template <index_type Count> span<element_type, Count> first() const { + return subspan<0, Count>(); + } + + span<element_type> first(index_type Count) const { return subspan(0, Count); } + + span<element_type> last(index_type Count) const { + return subspan(size() - Count, Count); + } + + template <index_type Offset, index_type Count> + span<element_type, Count> subspan() const { + return span<element_type, Count>(data() + Offset, Count); + } + + span<element_type> subspan(index_type Offset, + index_type Count = dynamic_extent) const { + return span<element_type>( + data() + Offset, Count == dynamic_extent ? size() - Offset : Count); + } + + /// @} + +private: + index_type size() const { + return static_cast<const span<T, Extent> &>(*this).size(); + } + + pointer data_; +}; + +template <typename T> struct is_array : false_type {}; + +template <typename T> struct is_array<T[]> : true_type {}; + +template <typename T, size_t N> struct is_array<T[N]> : true_type {}; + +template <typename T> struct is_array_class_helper : false_type {}; + +template <typename T, size_t N> +struct is_array_class_helper<array<T, N> > : true_type {}; + +template <typename T> +struct is_array_class : is_array_class_helper<typename remove_cv<T>::type> {}; + +template <typename T> struct is_span_helper : false_type {}; + +template <typename T, size_t Extent> +struct is_span_helper<span<T, Extent> > : true_type {}; + +template <typename T> +struct is_span : is_span_helper<typename remove_cv<T>::type> {}; + +template <typename T> struct is_vector_helper : false_type {}; + +template <typename T, typename Allocator> +struct is_vector_helper<std::vector<T, Allocator> > : true_type {}; + +template <typename T> +struct is_vector : is_vector_helper<typename remove_cv<T>::type> {}; + +// Used by the static extent span to disable the container constructors. +template <typename T> +struct enable_if_static_extent_convertible + : enable_if<!(is_array<T>::value || is_array_class<T>::value || + is_span<T>::value || is_vector<T>::value)> {}; + +// Used by the dynamic extent span to disable the container constructors. +template <typename T> +struct enable_if_dynamic_extent_convertible + : enable_if<!(is_array<T>::value || is_span<T>::value || + is_vector<T>::value)> {}; + +} // namespace detail + +// Implementation of the static extent span. +template <typename T, size_t Extent> +class span : public detail::span_base<MaximInterfaceCore::span, T, Extent> { + typedef detail::span_base<MaximInterfaceCore::span, T, Extent> span_base; + +public: + using span_base::extent; + using typename span_base::element_type; + using typename span_base::index_type; + using typename span_base::pointer; + using typename span_base::value_type; + + span(pointer data, index_type) : span_base(data) {} + + span(pointer begin, pointer) : span_base(begin) {} + + span(element_type (&arr)[extent]) : span_base(arr) {} + + span(array<value_type, extent> & arr) : span_base(arr.data()) {} + + span(const array<value_type, extent> & arr) : span_base(arr.data()) {} + + template <typename U> span(const span<U, extent> & s) : span_base(s.data()) {} + + template <typename Allocator> + span(std::vector<value_type, Allocator> & vec) : span_base(&vec.front()) {} + + template <typename Allocator> + span(const std::vector<value_type, Allocator> & vec) + : span_base(&vec.front()) {} + + template <typename Container> + span(Container & cont, + typename detail::enable_if_static_extent_convertible<Container>::type * = + NULL) + : span_base(cont.data()) {} + + template <typename Container> + span(const Container & cont, + typename detail::enable_if_static_extent_convertible<Container>::type * = + NULL) + : span_base(cont.data()) {} + + /// @name Observers + /// @{ + + static index_type size() { return extent; } + + static index_type size_bytes() { return size() * sizeof(element_type); } + + static bool empty() { return size() == 0; } + + /// @} + + /// @name Subviews + /// @{ + + template <index_type Count> span<element_type, Count> last() const { + return this->template subspan<extent - Count, Count>(); + } + + /// @} +}; + +// Implementation of the dynamic extent span. +template <typename T> +class span<T, dynamic_extent> + : public detail::span_base<MaximInterfaceCore::span, T, dynamic_extent> { + typedef detail::span_base<MaximInterfaceCore::span, T, dynamic_extent> + span_base; + +public: + using typename span_base::element_type; + using typename span_base::index_type; + using typename span_base::pointer; + using typename span_base::value_type; + + span() : span_base(NULL), size_(0) {} + + span(pointer data, index_type size) : span_base(data), size_(size) {} + + span(pointer begin, pointer end) : span_base(begin), size_(end - begin) {} + + template <size_t N> span(element_type (&arr)[N]) : span_base(arr), size_(N) {} + + template <typename U, size_t N> + span(const span<U, N> & s) : span_base(s.data()), size_(s.size()) {} + + template <typename Allocator> + span(std::vector<value_type, Allocator> & vec) + : span_base(vec.empty() ? NULL : &vec.front()), size_(vec.size()) {} + + template <typename Allocator> + span(const std::vector<value_type, Allocator> & vec) + : span_base(vec.empty() ? NULL : &vec.front()), size_(vec.size()) {} + + template <typename Container> + span( + Container & cont, + typename detail::enable_if_dynamic_extent_convertible<Container>::type * = + NULL) + : span_base(cont.data()), size_(cont.size()) {} + + template <typename Container> + span( + const Container & cont, + typename detail::enable_if_dynamic_extent_convertible<Container>::type * = + NULL) + : span_base(cont.data()), size_(cont.size()) {} + + /// @name Observers + /// @{ + + index_type size() const { return size_; } + + index_type size_bytes() const { return size() * sizeof(element_type); } + + bool empty() const { return size() == 0; } + + /// @} + + /// @name Subviews + /// @{ + + template <index_type Count> span<element_type, Count> last() const { + return span<element_type, Count>(this->data() + (size() - Count), Count); + } + + /// @} + +private: + index_type size_; +}; + +template <typename T> +span<T> make_span(T * data, typename span<T>::index_type size) { + return span<T>(data, size); +} + +template <typename T> span<T> make_span(T * begin, T * end) { + return span<T>(begin, end); +} + +template <typename T, size_t N> span<T, N> make_span(T (&arr)[N]) { + return span<T, N>(arr); +} + +template <typename T, size_t N> span<T, N> make_span(array<T, N> & arr) { + return arr; +} + +template <typename T, size_t N> +span<const T, N> make_span(const array<T, N> & arr) { + return arr; +} + +template <typename Container> +span<typename Container::value_type> make_span(Container & cont) { + return cont; +} + +template <typename Container> +span<const typename Container::value_type> make_span(const Container & cont) { + return cont; +} + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/system_error.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,96 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include "Error.hpp" +#include "system_error.hpp" + +namespace MaximInterfaceCore { + +using std::string; + +error_condition error_category::default_error_condition(int code) const { + return error_condition(code, *this); +} + +bool error_category::equivalent(int code, + const error_condition & condition) const { + return default_error_condition(code) == condition; +} + +bool error_category::equivalent(const error_code & code, int condition) const { + return *this == code.category() && code.value() == condition; +} + +const error_category & system_category() { + static class : public error_category { + public: + virtual const char * name() const { return "system"; } + + virtual string message(int condition) const { + return defaultErrorMessage(condition); + } + } instance; + return instance; +} + +static string formatWhat(const error_code & ec) { + return string(ec.category().name()) + ' ' + ec.message(); +} + +template <typename T> +static string formatWhat(const error_code & ec, const T & what_arg) { + return string(what_arg) + ": " + formatWhat(ec); +} + +system_error::system_error(const error_code & ec) + : runtime_error(formatWhat(ec)), code_(ec) {} + +system_error::system_error(const error_code & ec, const string & what_arg) + : runtime_error(formatWhat(ec, what_arg)), code_(ec) {} + +system_error::system_error(const error_code & ec, const char * what_arg) + : runtime_error(formatWhat(ec, what_arg)), code_(ec) {} + +system_error::system_error(int ev, const error_category & ecat) + : runtime_error(formatWhat(error_code(ev, ecat))), code_(ev, ecat) {} + +system_error::system_error(int ev, const error_category & ecat, + const string & what_arg) + : runtime_error(formatWhat(error_code(ev, ecat), what_arg)), + code_(ev, ecat) {} + +system_error::system_error(int ev, const error_category & ecat, + const char * what_arg) + : runtime_error(formatWhat(error_code(ev, ecat), what_arg)), + code_(ev, ecat) {} + +} // namespace MaximInterfaceCore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/system_error.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,227 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +/// @file +/// @brief +/// Error handling constructs similar to std::error_code, std::error_condition, +/// and std::error_category. + +#ifndef MaximInterfaceCore_system_error +#define MaximInterfaceCore_system_error + +#include <stdexcept> +#include <string> +#include "Config.hpp" +#include "SafeBool.hpp" +#include "Uncopyable.hpp" + +namespace MaximInterfaceCore { + +class error_condition; +class error_code; + +class error_category : private Uncopyable { +public: + virtual ~error_category() {} + + virtual const char * name() const = 0; + + MaximInterfaceCore_EXPORT virtual error_condition + default_error_condition(int code) const; + + MaximInterfaceCore_EXPORT virtual bool + equivalent(int code, const error_condition & condition) const; + + MaximInterfaceCore_EXPORT virtual bool equivalent(const error_code & code, + int condition) const; + + virtual std::string message(int condition) const = 0; +}; + +inline bool operator==(const error_category & lhs, const error_category & rhs) { + return &lhs == &rhs; +} + +inline bool operator!=(const error_category & lhs, const error_category & rhs) { + return !operator==(lhs, rhs); +} + +inline bool operator<(const error_category & lhs, const error_category & rhs) { + return &lhs < &rhs; +} + +MaximInterfaceCore_EXPORT const error_category & system_category(); + +class error_condition { +public: + error_condition() : value_(0), category_(&system_category()) {} + + error_condition(int value, const error_category & category) + : value_(value), category_(&category) {} + + void assign(int value, const error_category & category) { + value_ = value; + category_ = &category; + } + + void clear() { + value_ = 0; + category_ = &system_category(); + } + + int value() const { return value_; } + + const error_category & category() const { return *category_; } + + std::string message() const { return category().message(value()); } + + operator SafeBool() const { return makeSafeBool(value() != 0); } + +private: + int value_; + const error_category * category_; +}; + +inline bool operator==(const error_condition & lhs, + const error_condition & rhs) { + return (lhs.value() == rhs.value()) && (lhs.category() == rhs.category()); +} + +inline bool operator!=(const error_condition & lhs, + const error_condition & rhs) { + return !operator==(lhs, rhs); +} + +inline bool operator<(const error_condition & lhs, + const error_condition & rhs) { + return (lhs.category() < rhs.category()) || + ((lhs.category() == rhs.category()) && (lhs.value() < rhs.value())); +} + +class error_code { +public: + error_code() : value_(0), category_(&system_category()) {} + + error_code(int value, const error_category & category) + : value_(value), category_(&category) {} + + void assign(int value, const error_category & category) { + value_ = value; + category_ = &category; + } + + void clear() { + value_ = 0; + category_ = &system_category(); + } + + int value() const { return value_; } + + const error_category & category() const { return *category_; } + + error_condition default_error_condition() const { + return category().default_error_condition(value()); + } + + std::string message() const { return category().message(value()); } + + operator SafeBool() const { return makeSafeBool(value() != 0); } + +private: + int value_; + const error_category * category_; +}; + +inline bool operator==(const error_code & lhs, const error_code & rhs) { + return (lhs.value() == rhs.value()) && (lhs.category() == rhs.category()); +} + +inline bool operator!=(const error_code & lhs, const error_code & rhs) { + return !operator==(lhs, rhs); +} + +inline bool operator<(const error_code & lhs, const error_code & rhs) { + return (lhs.category() < rhs.category()) || + ((lhs.category() == rhs.category()) && (lhs.value() < rhs.value())); +} + +template <typename CharT, typename Traits> +std::basic_ostream<CharT, Traits> & +operator<<(std::basic_ostream<CharT, Traits> & os, const error_code & ec) { + os << ec.category().name() << ':' << ec.value(); + return os; +} + +inline bool operator==(const error_code & lhs, const error_condition & rhs) { + return lhs.category().equivalent(lhs.value(), rhs) || + rhs.category().equivalent(lhs, rhs.value()); +} + +inline bool operator!=(const error_code & lhs, const error_condition & rhs) { + return !operator==(lhs, rhs); +} + +inline bool operator==(const error_condition & lhs, const error_code & rhs) { + return operator==(rhs, lhs); +} + +inline bool operator!=(const error_condition & lhs, const error_code & rhs) { + return !operator==(lhs, rhs); +} + +class system_error : public std::runtime_error { +public: + MaximInterfaceCore_EXPORT system_error(const error_code & ec); + + MaximInterfaceCore_EXPORT system_error(const error_code & ec, + const std::string & what_arg); + + MaximInterfaceCore_EXPORT system_error(const error_code & ec, + const char * what_arg); + + MaximInterfaceCore_EXPORT system_error(int ev, const error_category & ecat); + + MaximInterfaceCore_EXPORT system_error(int ev, const error_category & ecat, + const std::string & what_arg); + + MaximInterfaceCore_EXPORT system_error(int ev, const error_category & ecat, + const char * what_arg); + + const error_code & code() const { return code_; } + +private: + error_code code_; +}; + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceCore/type_traits.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,88 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceCore_type_traits +#define MaximInterfaceCore_type_traits + +namespace MaximInterfaceCore { + +template <typename T, T v> struct integral_constant { + static const T value = v; + typedef T value_type; + typedef integral_constant<T, v> type; + operator value_type() const { return value; } + value_type operator()() const { return value; } +}; + +typedef integral_constant<bool, true> true_type; +typedef integral_constant<bool, false> false_type; + +template <typename T, typename U> struct is_same : false_type {}; +template <typename T> struct is_same<T, T> : true_type {}; + +template <bool B, typename T, typename F> struct conditional { + typedef T type; +}; +template <typename T, typename F> struct conditional<false, T, F> { + typedef F type; +}; + +template <bool B, typename T = void> struct enable_if {}; +template <typename T> struct enable_if<true, T> { typedef T type; }; + +namespace detail { + +template <typename T> struct alignment_of_helper { + char a; + T b; +}; + +} // namespace detail + +template <typename T> +struct alignment_of + : integral_constant<size_t, + sizeof(detail::alignment_of_helper<T>) - sizeof(T)> {}; + +template <typename T> struct remove_const { typedef T type; }; +template <typename T> struct remove_const<const T> { typedef T type; }; + +template <typename T> struct remove_volatile { typedef T type; }; +template <typename T> struct remove_volatile<volatile T> { typedef T type; }; + +template <typename T> struct remove_cv { + typedef typename remove_volatile<typename remove_const<T>::type>::type type; +}; + +} // namespace MaximInterfaceCore + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/Config.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,37 @@ +/******************************************************************************* +* Copyright (C) 2019 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceDevices_EXPORT + #define MaximInterfaceDevices_EXPORT +#endif + +namespace MaximInterfaceDevices { namespace Core = MaximInterfaceCore; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS18B20.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,253 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include <MaximInterfaceCore/Error.hpp> +#include <MaximInterfaceCore/OneWireMaster.hpp> +#include "DS18B20.hpp" + +namespace MaximInterfaceDevices { + +using namespace Core; + +const uint_least8_t DS18B20::nineBitResolution; +const uint_least8_t DS18B20::tenBitResolution; +const uint_least8_t DS18B20::elevenBitResolution; +const uint_least8_t DS18B20::twelveBitResolution; + +error_code DS18B20::initialize() { + Scratchpad::array scratchpad; + return readScratchpad(scratchpad); +} + +error_code DS18B20::writeScratchpad(uint_least8_t th, uint_least8_t tl, + uint_least8_t res) { + error_code result = selectRom(*master); + if (!result) { + const uint_least8_t sendBlock[] = {0x4E, th, tl, res}; + result = master->writeBlock(sendBlock); + if (!result) { + resolution = res; + } + } + return result; +} + +error_code DS18B20::readScratchpad(Scratchpad::span scratchpad) { + error_code result = selectRom(*master); + if (result) { + return result; + } + result = master->writeByte(0xBE); + if (result) { + return result; + } + result = master->readBlock(scratchpad); + if (result) { + return result; + } + uint_least8_t receivedCrc; + result = master->readByte(receivedCrc); + if (result) { + return result; + } + if (receivedCrc == calculateCrc8(scratchpad)) { + resolution = scratchpad[4]; + } else { + result = make_error_code(CrcError); + } + return result; +} + +error_code DS18B20::readPowerSupply(bool & localPower) { + error_code result = selectRom(*master); + if (result) { + return result; + } + result = master->writeByte(0xB4); + if (result) { + return result; + } + result = master->touchBit(localPower); + return result; +} + +error_code DS18B20::copyScratchpad() { + const uint_least8_t copyScratchpadCmd = 0x48; + + bool hasLocalPower; + error_code result = readPowerSupply(hasLocalPower); + if (result) { + return result; + } + result = selectRom(*master); + if (result) { + return result; + } + if (hasLocalPower) { + result = master->writeByte(copyScratchpadCmd); + bool recvbit = 0; + while (!recvbit && !result) { + result = master->touchBit(recvbit); + } + } else { + result = master->writeByteSetLevel(copyScratchpadCmd, + OneWireMaster::StrongLevel); + if (!result) { + sleep->invoke(10); + result = master->setLevel(OneWireMaster::NormalLevel); + } + } + return result; +} + +error_code DS18B20::convertTemperature() { + const uint_least8_t convertTemperatureCmd = 0x44; + + bool hasLocalPower; + error_code result = readPowerSupply(hasLocalPower); + if (result) { + return result; + } + result = selectRom(*master); + if (result) { + return result; + } + if (hasLocalPower) { + result = master->writeByte(convertTemperatureCmd); + bool recvbit = 0; + while (!result && !recvbit) { + result = master->touchBit(recvbit); + } + } else { + result = master->writeByteSetLevel(convertTemperatureCmd, + OneWireMaster::StrongLevel); + if (!result) { + int sleepTime; + switch (resolution) { + case nineBitResolution: + sleepTime = 94; + break; + + case tenBitResolution: + sleepTime = 188; + break; + + case elevenBitResolution: + sleepTime = 375; + break; + + case twelveBitResolution: + default: + sleepTime = 750; + break; + } + sleep->invoke(sleepTime); + result = master->setLevel(OneWireMaster::NormalLevel); + } + } + return result; +} + +error_code DS18B20::recallEeprom() { + error_code result = selectRom(*master); + if (!result) { + result = master->writeByte(0xB8); + } + return result; +} + +const error_category & DS18B20::errorCategory() { + static class : public error_category { + public: + virtual const char * name() const { return "DS18B20"; } + + virtual std::string message(int condition) const { + switch (condition) { + case CrcError: + return "CRC Error"; + + case DataError: + return "Data Error"; + + default: + return defaultErrorMessage(condition); + } + } + } instance; + return instance; +} + +error_code readTemperature(DS18B20 & ds18b20, int & temperature) { + error_code result = ds18b20.convertTemperature(); + if (result) { + return result; + } + DS18B20::Scratchpad::array scratchpad; + result = ds18b20.readScratchpad(scratchpad); + if (result) { + return result; + } + + const unsigned int tempData = + (static_cast<unsigned int>(scratchpad[1]) << 8) | scratchpad[0]; + const unsigned int signMask = 0xF800; + if ((tempData & signMask) == signMask) { + temperature = -0x800; + } else if ((tempData & signMask) == 0) { + temperature = 0; + } else { + return make_error_code(DS18B20::DataError); + } + unsigned int precisionMask; + switch (scratchpad[4]) { + case DS18B20::nineBitResolution: + default: + precisionMask = 0x7; + break; + + case DS18B20::tenBitResolution: + precisionMask = 0x3; + break; + + case DS18B20::elevenBitResolution: + precisionMask = 0x1; + break; + + case DS18B20::twelveBitResolution: + precisionMask = 0x0; + break; + } + temperature += static_cast<int>(tempData & ~(signMask | precisionMask)); + return error_code(); +} + +} // namespace MaximInterfaceDevices
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS18B20.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,142 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceDevices_DS18B20 +#define MaximInterfaceDevices_DS18B20 + +#include <MaximInterfaceCore/array_span.hpp> +#include <MaximInterfaceCore/SelectRom.hpp> +#include <MaximInterfaceCore/Sleep.hpp> +#include "Config.hpp" + +namespace MaximInterfaceDevices { + +/// @brief DS18B20 Programmable Resolution 1-Wire Digital Thermometer +/// @details The DS18B20 digital thermometer provides 9-bit to 12-bit +/// Celsius temperature measurements and has an alarm function with +/// nonvolatile user-programmable upper and lower trigger points. The +/// DS18B20 communicates over a 1-Wire bus that by definition requires +/// only one data line (and ground) for communication with a central +/// microprocessor. In addition, the DS18B20 can derive power directly +/// from the data line ("parasite power"), eliminating the need for an +/// external power supply. +class DS18B20 { +public: + enum ErrorValue { CrcError = 1, DataError }; + + static const uint_least8_t nineBitResolution = 0x1F; + static const uint_least8_t tenBitResolution = 0x3F; + static const uint_least8_t elevenBitResolution = 0x5F; + static const uint_least8_t twelveBitResolution = 0x7F; + + /// Holds the contents of the device scratchpad. + typedef Core::array_span<uint_least8_t, 8> Scratchpad; + + DS18B20(Core::Sleep & sleep, Core::OneWireMaster & master, + const Core::SelectRom & selectRom) + : selectRom(selectRom), master(&master), sleep(&sleep), resolution(0) {} + + void setSleep(Core::Sleep & sleep) { this->sleep = &sleep; } + + void setMaster(Core::OneWireMaster & master) { this->master = &master; } + + void setSelectRom(const Core::SelectRom & selectRom) { + this->selectRom = selectRom; + } + + /// Initializes the device for first time use. + MaximInterfaceDevices_EXPORT Core::error_code initialize(); + + /// @brief Write Scratchpad Command + /// @details If the result of a temperature measurement is higher + /// than TH or lower than TL, an alarm flag inside the device is + /// set. This flag is updated with every temperature measurement. + /// As long as the alarm flag is set, the DS1920 will respond to + /// the alarm search command. + /// @param[in] th 8-bit upper temperature threshold, MSB indicates sign. + /// @param[in] tl 8-bit lower temperature threshold, LSB indicates sign. + /// @param[in] res Resolution of the DS18B20. + MaximInterfaceDevices_EXPORT Core::error_code + writeScratchpad(uint_least8_t th, uint_least8_t tl, uint_least8_t res); + + /// @brief Read Scratchpad Command + /// @param[out] scratchpad Contents of scratchpad. + MaximInterfaceDevices_EXPORT Core::error_code + readScratchpad(Scratchpad::span scratchpad); + + /// @brief Copy Scratchpad Command + /// @details This command copies from the scratchpad into the + /// EEPROM of the DS18B20, storing the temperature trigger bytes + /// and resolution in nonvolatile memory. + MaximInterfaceDevices_EXPORT Core::error_code copyScratchpad(); + + /// @brief Read Power Supply command + /// @details This command determines if the DS18B20 is parasite + /// powered or has a local supply + /// @param[out] localPower + /// True if the device is powered by a local power supply, or false if the + /// device is parasitically powered. + MaximInterfaceDevices_EXPORT Core::error_code + readPowerSupply(bool & localPower); + + /// @brief Convert Temperature Command + /// @details This command begins a temperature conversion. + MaximInterfaceDevices_EXPORT Core::error_code convertTemperature(); + + /// @brief Recall Command + /// @details This command recalls the temperature trigger values + /// and resolution stored in EEPROM to the scratchpad. + MaximInterfaceDevices_EXPORT Core::error_code recallEeprom(); + + MaximInterfaceDevices_EXPORT static const Core::error_category & + errorCategory(); + +private: + Core::SelectRom selectRom; + Core::OneWireMaster * master; + const Core::Sleep * sleep; + uint_least8_t resolution; +}; + +/// @brief Reads the current temperature as an integer value with decimal. +/// @param ds18b20 Device to read. +/// @param[out] temperature Temperature in degrees Celsius multiplied by 16. +MaximInterfaceDevices_EXPORT Core::error_code +readTemperature(DS18B20 & ds18b20, int & temperature); + +inline Core::error_code make_error_code(DS18B20::ErrorValue e) { + return Core::error_code(e, DS18B20::errorCategory()); +} + +} // namespace MaximInterfaceDevices + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS1920.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,147 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include <MaximInterfaceCore/Error.hpp> +#include <MaximInterfaceCore/OneWireMaster.hpp> +#include "DS1920.hpp" + +namespace MaximInterfaceDevices { + +using namespace Core; + +error_code DS1920::writeScratchpad(uint_least8_t th, uint_least8_t tl) { + error_code result = selectRom(*master); + if (!result) { + const uint_least8_t sendBlock[] = {0x4E, th, tl}; + result = master->writeBlock(sendBlock); + } + return result; +} + +error_code DS1920::readScratchpad(Scratchpad::span scratchpad) { + error_code result = selectRom(*master); + if (!result) { + result = master->writeByte(0xBE); + if (!result) { + result = master->readBlock(scratchpad); + if (!result) { + uint_least8_t receivedCrc; + result = master->readByte(receivedCrc); + if (!result && (receivedCrc != calculateCrc8(scratchpad))) { + result = make_error_code(CrcError); + } + } + } + } + return result; +} + +error_code DS1920::copyScratchpad() { + error_code result = selectRom(*master); + if (!result) { + result = master->writeByteSetLevel(0x48, OneWireMaster::StrongLevel); + if (!result) { + sleep->invoke(10); + result = master->setLevel(OneWireMaster::NormalLevel); + } + } + return result; +} + +error_code DS1920::convertTemperature() { + error_code result = selectRom(*master); + if (!result) { + result = master->writeByteSetLevel(0x44, OneWireMaster::StrongLevel); + if (!result) { + sleep->invoke(750); + result = master->setLevel(OneWireMaster::NormalLevel); + } + } + return result; +} + +error_code DS1920::recallEeprom() { + error_code result = selectRom(*master); + if (!result) { + result = master->writeByte(0xB8); + } + return result; +} + +const error_category & DS1920::errorCategory() { + static class : public error_category { + public: + virtual const char * name() const { return "DS1920"; } + + virtual std::string message(int condition) const { + switch (condition) { + case CrcError: + return "CRC Error"; + + case DataError: + return "Data Error"; + + default: + return defaultErrorMessage(condition); + } + } + } instance; + return instance; +} + +error_code readTemperature(DS1920 & ds1920, int & temperature) { + error_code result = ds1920.convertTemperature(); + if (result) { + return result; + } + DS1920::Scratchpad::array scratchpad; + result = ds1920.readScratchpad(scratchpad); + if (result) { + return result; + } + + unsigned int tempData = + (static_cast<unsigned int>(scratchpad[1]) << 8) | scratchpad[0]; + const unsigned int signMask = 0xFF00; + if ((tempData & signMask) == signMask) { + temperature = -0x100; + tempData &= ~signMask; + } else if ((tempData & signMask) == 0) { + temperature = 0; + } else { + return make_error_code(DS1920::DataError); + } + temperature += static_cast<int>(tempData); + return error_code(); +} + +} // namespace MaximInterfaceDevices
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS1920.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,124 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceDevices_DS1920 +#define MaximInterfaceDevices_DS1920 + +#include <MaximInterfaceCore/array_span.hpp> +#include <MaximInterfaceCore/SelectRom.hpp> +#include <MaximInterfaceCore/Sleep.hpp> +#include "Config.hpp" + +namespace MaximInterfaceDevices { + +/// @brief DS1920 1-Wire Temperature iButton +/// @details The iButton® temperature logger (DS1920) provides +/// direct-to-digital 9-bit temperature readings over a range of +/// -55°C to +100°C in 0.5° increments. The iButton communicates with +/// a processor using the 1-Wire® protocol through a hardware port +/// interface. The port interface provides both the physical link and +/// handles the communication protocols that enable the processor to +/// access iButton resources with simple commands. Two bytes of +/// EEPROM can be used either to set alarm triggers or for storing +/// user data. +class DS1920 { +public: + enum ErrorValue { CrcError = 1, DataError }; + + /// Holds the contents of the device scratchpad. + typedef Core::array_span<uint_least8_t, 8> Scratchpad; + + DS1920(Core::Sleep & sleep, Core::OneWireMaster & master, + const Core::SelectRom & selectRom) + : selectRom(selectRom), master(&master), sleep(&sleep) {} + + void setSleep(Core::Sleep & sleep) { this->sleep = &sleep; } + + void setMaster(Core::OneWireMaster & master) { this->master = &master; } + + void setSelectRom(const Core::SelectRom & selectRom) { + this->selectRom = selectRom; + } + + /// @brief Write Scratchpad Command + /// @details If the result of a temperature measurement is higher + /// than TH or lower than TL, an alarm flag inside the device is + /// set. This flag is updated with every temperature measurement. + /// As long as the alarm flag is set, the DS1920 will respond to + /// the alarm search command. + /// @param[in] th 8-bit upper temperature threshold, MSB indicates sign. + /// @param[in] tl 8-bit lower temperature threshold, MSB indicates sign. + MaximInterfaceDevices_EXPORT Core::error_code + writeScratchpad(uint_least8_t th, uint_least8_t tl); + + /// @brief Read Scratchpad Command + /// @param[out] scratchpad Contents of scratchpad. + MaximInterfaceDevices_EXPORT Core::error_code + readScratchpad(Scratchpad::span scratchpad); + + /// @brief Copy Scratchpad Command + /// @details This command copies from the scratchpad into the + /// EEPROM of the DS1920, storing the temperature trigger bytes + /// in nonvolatile memory. + MaximInterfaceDevices_EXPORT Core::error_code copyScratchpad(); + + /// @brief Convert Temperature Command + /// @details This command begins a temperature conversion. + MaximInterfaceDevices_EXPORT Core::error_code convertTemperature(); + + /// @brief Recall Command + /// @details This command recalls the temperature trigger values + /// stored in EEPROM to the scratchpad. + MaximInterfaceDevices_EXPORT Core::error_code recallEeprom(); + + MaximInterfaceDevices_EXPORT static const Core::error_category & + errorCategory(); + +private: + Core::SelectRom selectRom; + Core::OneWireMaster * master; + const Core::Sleep * sleep; +}; + +/// @brief Reads the current temperature as an integer value. +/// @param ds1920 Device to read. +/// @param[out] temperature Temperature in degrees Celsius multiplied by 2. +MaximInterfaceDevices_EXPORT Core::error_code +readTemperature(DS1920 & ds1920, int & temperature); + +inline Core::error_code make_error_code(DS1920::ErrorValue e) { + return Core::error_code(e, DS1920::errorCategory()); +} + +} // namespace MaximInterfaceDevices + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS2413.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,126 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include <MaximInterfaceCore/Error.hpp> +#include <MaximInterfaceCore/OneWireMaster.hpp> +#include "DS2413.hpp" + +namespace MaximInterfaceDevices { + +using namespace Core; + +error_code DS2413::readStatus(Status & status) const { + uint_least8_t val; + const error_code result = pioAccessRead(val); + if (!result) { + status = val; + } + return result; +} + +error_code DS2413::writeOutputState(bool pioAState, bool pioBState) { + uint_least8_t val = 0xFC; + if (pioAState) { + val |= 0x1; + } + if (pioBState) { + val |= 0x2; + } + return pioAccessWrite(val); +} + +error_code DS2413::pioAccessRead(uint_least8_t & val) const { + error_code result = selectRom(*master); + if (!result) { + result = master->writeByte(0xF5); + if (!result) { + result = master->readByte(val); + if (!result && (val != ((val ^ 0xF0) >> 4))) { + result = make_error_code(CommunicationError); + } + } + } + return result; +} + +error_code DS2413::pioAccessWrite(uint_least8_t val) { + error_code result = selectRom(*master); + if (!result) { + uint_least8_t block[] = {0x5A, val, static_cast<uint_least8_t>(val ^ 0xFF)}; + result = master->writeBlock(block); + if (!result) { + result = master->readByte(block[0]); + if (!result && block[0] != 0xAA) { + result = make_error_code(CommunicationError); + } + } + } + return result; +} + +const error_category & DS2413::errorCategory() { + static class : public error_category { + public: + virtual const char * name() const { return "DS2413"; } + + virtual std::string message(int condition) const { + switch (condition) { + case CommunicationError: + return "Communication Error"; + } + return defaultErrorMessage(condition); + } + } instance; + return instance; +} + +error_code writePioAOutputState(DS2413 & ds2413, bool pioAState) { + DS2413::Status status; + error_code result = ds2413.readStatus(status); + if (!result && pioAState != status[DS2413::PioAOutputState]) { + result = + ds2413.writeOutputState(pioAState, status[DS2413::PioBOutputState]); + } + return result; +} + +error_code writePioBOutputState(DS2413 & ds2413, bool pioBState) { + DS2413::Status status; + error_code result = ds2413.readStatus(status); + if (!result && pioBState != status[DS2413::PioBOutputState]) { + result = + ds2413.writeOutputState(status[DS2413::PioAOutputState], pioBState); + } + return result; +} + +} // namespace MaximInterfaceDevices
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS2413.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,107 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceDevices_DS2413 +#define MaximInterfaceDevices_DS2413 + +#include <stdint.h> +#include <MaximInterfaceCore/FlagSet.hpp> +#include <MaximInterfaceCore/SelectRom.hpp> +#include "Config.hpp" + +namespace MaximInterfaceDevices { + +/// @brief DS2413 1-Wire Dual Channel Addressable Switch +/// @details The DS2413 is a dual-channel programmable I/O 1-Wire® +/// chip. The PIO outputs are configured as open-drain and provide up +/// to 20mA continuous sink capability and off-state operating voltage +/// up to 28V. Control and sensing of the PIO pins is performed with +/// a dedicated device-level command protocol. To provide a high level +/// of fault tolerance in the end application, the 1-Wire I/O and PIO +/// pins are all capable of withstanding continuous application of +/// voltages up to 28V max. Communication and operation of the DS2413 +/// is performed with the single contact Maxim 1-Wire serial interface. +class DS2413 { +public: + enum ErrorValue { CommunicationError = 1 }; + + enum StatusFlags { + PioAInputState = 0x1, + PioAOutputState = 0x2, + PioBInputState = 0x4, + PioBOutputState = 0x8 + }; + typedef Core::FlagSet<StatusFlags, 4> Status; + + DS2413(Core::OneWireMaster & master, const Core::SelectRom & selectRom) + : selectRom(selectRom), master(&master) {} + + void setMaster(Core::OneWireMaster & master) { this->master = &master; } + + void setSelectRom(const Core::SelectRom & selectRom) { + this->selectRom = selectRom; + } + + /// Read the input and output logic states for all PIO pins. + MaximInterfaceDevices_EXPORT Core::error_code + readStatus(Status & status) const; + + /// Write the output logic states for all PIO pins. + MaximInterfaceDevices_EXPORT Core::error_code + writeOutputState(bool pioAState, bool pioBState); + + MaximInterfaceDevices_EXPORT static const Core::error_category & + errorCategory(); + +private: + Core::error_code pioAccessRead(uint_least8_t & val) const; + Core::error_code pioAccessWrite(uint_least8_t val); + + Core::SelectRom selectRom; + Core::OneWireMaster * master; +}; + +/// Write the output logic state for only PIOA. +MaximInterfaceDevices_EXPORT Core::error_code +writePioAOutputState(DS2413 & ds2413, bool pioAState); + +/// Write the output logic state for only PIOB. +MaximInterfaceDevices_EXPORT Core::error_code +writePioBOutputState(DS2413 & ds2413, bool pioBState); + +inline Core::error_code make_error_code(DS2413::ErrorValue e) { + return Core::error_code(e, DS2413::errorCategory()); +} + +} // namespace MaximInterfaceDevices + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS2431.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,178 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include <algorithm> +#include <MaximInterfaceCore/Error.hpp> +#include <MaximInterfaceCore/OneWireMaster.hpp> +#include "DS2431.hpp" + +namespace MaximInterfaceDevices { + +using namespace Core; + +error_code writeMemory(DS2431 & device, DS2431::Address targetAddress, + DS2431::Scratchpad::const_span data) { + error_code result = device.writeScratchpad(targetAddress, data); + if (result) { + return result; + } + DS2431::Scratchpad::array readData; + uint_least8_t esByte; + result = device.readScratchpad(readData, esByte); + if (result) { + return result; + } + result = device.copyScratchpad(targetAddress, esByte); + return result; +} + +error_code DS2431::readMemory(Address beginAddress, + span<uint_least8_t> data) const { + error_code result = selectRom(*master); + if (result) { + return result; + } + const uint_least8_t sendBlock[] = {0xF0, beginAddress, 0x00}; + result = master->writeBlock(sendBlock); + if (result) { + return result; + } + result = master->readBlock(data); + return result; +} + +error_code DS2431::writeScratchpad(Address targetAddress, + Scratchpad::const_span data) { + error_code result = selectRom(*master); + if (result) { + return result; + } + uint_least8_t block[3 + Scratchpad::size] = {0x0F, targetAddress, 0x00}; + std::copy(data.begin(), data.end(), block + 3); + result = master->writeBlock(block); + if (result) { + return result; + } + const uint_fast16_t calculatedCrc = calculateCrc16(block) ^ 0xFFFFu; + result = master->readBlock(make_span(block, 2)); + if (result) { + return result; + } + if (calculatedCrc != + ((static_cast<uint_fast16_t>(block[1]) << 8) | block[0])) { + result = make_error_code(CrcError); + } + return result; +} + +error_code DS2431::readScratchpad(Scratchpad::span data, + uint_least8_t & esByte) { + typedef array<uint_least8_t, 6 + Scratchpad::size> Block; + + error_code result = selectRom(*master); + if (result) { + return result; + } + Block block = {0xAA}; + result = master->writeByte(block.front()); + if (result) { + return result; + } + result = master->readBlock(make_span(block).subspan(1)); + if (result) { + return result; + } + Block::const_iterator blockIt = block.end(); + uint_fast16_t receivedCrc = static_cast<uint_fast16_t>(*(--blockIt)) << 8; + receivedCrc |= *(--blockIt); + const uint_fast16_t expectedCrc = + calculateCrc16(make_span(block.data(), block.size() - 2)) ^ 0xFFFFu; + if (expectedCrc == receivedCrc) { + Block::const_iterator blockItEnd = blockIt; + blockIt -= data.size(); + std::copy(blockIt, blockItEnd, data.begin()); + esByte = *(--blockIt); + } else { + result = make_error_code(CrcError); + } + return result; +} + +error_code DS2431::copyScratchpad(Address targetAddress, uint_least8_t esByte) { + error_code result = selectRom(*master); + if (result) { + return result; + } + uint_least8_t block[] = {0x55, targetAddress, 0x00}; + result = master->writeBlock(block); + if (result) { + return result; + } + result = master->writeByteSetLevel(esByte, OneWireMaster::StrongLevel); + if (result) { + return result; + } + sleep->invoke(10); + result = master->setLevel(OneWireMaster::NormalLevel); + if (result) { + return result; + } + result = master->readByte(block[0]); + if (result) { + return result; + } + if (block[0] != 0xAA) { + result = make_error_code(OperationFailure); + } + return result; +} + +const error_category & DS2431::errorCategory() { + static class : public error_category { + public: + virtual const char * name() const { return "DS2431"; } + + virtual std::string message(int condition) const { + switch (condition) { + case CrcError: + return "CRC Error"; + + case OperationFailure: + return "Operation Failure"; + } + return defaultErrorMessage(condition); + } + } instance; + return instance; +} + +} // namespace MaximInterfaceDevices
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS2431.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,126 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceDevices_DS2431 +#define MaximInterfaceDevices_DS2431 + +#include <MaximInterfaceCore/array_span.hpp> +#include <MaximInterfaceCore/SelectRom.hpp> +#include <MaximInterfaceCore/Sleep.hpp> +#include "Config.hpp" + +namespace MaximInterfaceDevices { + +/// @brief DS2431 1024-bit 1-Wire EEPROM +/// @details The DS2431 is a 1024-bit, 1-Wire® EEPROM chip organized +/// as four memory pages of 256 bits each. Data is written to an 8-byte +/// scratchpad, verified, and then copied to the EEPROM memory. As a +/// special feature, the four memory pages can individually be write +/// protected or put in EPROM-emulation mode, where bits can only be +/// changed from a 1 to a 0 state. The DS2431 communicates over the +/// single-conductor 1-Wire bus. The communication follows the standard +/// 1-Wire protocol. Each device has its own unalterable and unique +/// 64-bit ROM registration number that is factory lasered into the chip. +/// The registration number is used to address the device in a multidrop, +/// 1-Wire net environment. +class DS2431 { +public: + enum ErrorValue { CrcError = 1, OperationFailure }; + + typedef Core::array_span<uint_least8_t, 8> Scratchpad; + typedef uint_least8_t Address; + + DS2431(Core::Sleep & sleep, Core::OneWireMaster & master, + const Core::SelectRom & selectRom) + : selectRom(selectRom), master(&master), sleep(&sleep) {} + + void setSleep(Core::Sleep & sleep) { this->sleep = &sleep; } + + void setMaster(Core::OneWireMaster & master) { this->master = &master; } + + void setSelectRom(const Core::SelectRom & selectRom) { + this->selectRom = selectRom; + } + + /// @brief Reads block of data from EEPROM memory. + /// @param[in] beginAddress EEPROM memory address to start reading from. + /// @param[out] data EEPROM data read from the device. + MaximInterfaceDevices_EXPORT Core::error_code + readMemory(Address beginAddress, Core::span<uint_least8_t> data) const; + + /// @brief Writes 8 bytes to the scratchpad. + /// @param[in] targetAddress + /// EEPROM memory address that this data will be copied to. + /// Must be on row boundary. + /// @param[in] data Data to write to scratchpad. + MaximInterfaceDevices_EXPORT Core::error_code + writeScratchpad(Address targetAddress, Scratchpad::const_span data); + + /// @brief Reads contents of scratchpad. + /// @param[out] data Data read from scratchpad. + /// @param[out] esByte E/S byte read before scratchpad data. + MaximInterfaceDevices_EXPORT Core::error_code + readScratchpad(Scratchpad::span data, uint_least8_t & esByte); + + /// @brief Copies contents of scratchpad to EEPROM. + /// @param[in] targetAddress EEPROM memory address that scratchpad + /// will be copied to. Must be on row boundary. + /// @param[in] esByte E/S byte from preceding Read Scratchpad command. + MaximInterfaceDevices_EXPORT Core::error_code + copyScratchpad(Address targetAddress, uint_least8_t esByte); + + MaximInterfaceDevices_EXPORT static const Core::error_category & + errorCategory(); + +private: + Core::SelectRom selectRom; + Core::OneWireMaster * master; + const Core::Sleep * sleep; +}; + +/// @brief +/// Writes data to EEPROM using Write Scratchpad, Read Scratchpad, +/// and Copy Scratchpad commands. +/// @param device Device to write. +/// @param[in] targetAddress EEPROM memory address to start writing at. +/// @param[in] data Data to write to EEPROM. +MaximInterfaceDevices_EXPORT Core::error_code +writeMemory(DS2431 & device, DS2431::Address targetAddress, + DS2431::Scratchpad::const_span data); + +inline Core::error_code make_error_code(DS2431::ErrorValue e) { + return Core::error_code(e, DS2431::errorCategory()); +} + +} // namespace MaximInterfaceDevices + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS2465.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,782 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include <MaximInterfaceCore/Error.hpp> +#include "DS2465.hpp" + +namespace MaximInterfaceDevices { + +using namespace Core; + +/// Delay required after writing an EEPROM segment. +static const int eepromSegmentWriteDelayMs = 10; +/// Delay required after writing an EEPROM page such as the secret memory. +static const int eepromPageWriteDelayMs = 8 * eepromSegmentWriteDelayMs; +/// Delay required for a SHA computation to complete. +static const int shaComputationDelayMs = 2; + +static const uint_least8_t scratchpad = 0x00; +static const uint_least8_t commandReg = 0x60; + +static const uint_least8_t owTransmitBlockCmd = 0x69; + +/// DS2465 Status bits. +enum StatusBit { + Status_1WB = 0x01, + Status_PPD = 0x02, + Status_SD = 0x04, + Status_LL = 0x08, + Status_RST = 0x10, + Status_SBR = 0x20, + Status_TSB = 0x40, + Status_DIR = 0x80 +}; + +static const int maxBlockSize = 63; + +const int DS2465::memoryPages; +const int DS2465::segmentsPerPage; + +error_code DS2465::initialize(Config config) { + // reset DS2465 + error_code result = resetDevice(); + if (!result) { + // write the default configuration setup + result = writeConfig(config); + } + return result; +} + +error_code DS2465::computeNextMasterSecret(bool swap, int pageNum, + PageRegion region) { + error_code result = make_error_code(ArgumentOutOfRangeError); + if (pageNum >= 0) { + const uint_least8_t command[] = { + 0x1E, static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region) + : 0xBF)}; + result = writeMemory(commandReg, command); + } + return result; +} + +error_code DS2465::computeWriteMac(bool regwrite, bool swap, int pageNum, + int segmentNum) const { + error_code result = make_error_code(ArgumentOutOfRangeError); + if (pageNum >= 0 && segmentNum >= 0) { + const uint_least8_t command[] = { + 0x2D, static_cast<uint_least8_t>((regwrite << 7) | (swap << 6) | + (pageNum << 4) | segmentNum)}; + result = writeMemory(commandReg, command); + if (!result) { + sleep->invoke(shaComputationDelayMs); + } + } + return result; +} + +error_code DS2465::computeAuthMac(bool swap, int pageNum, + PageRegion region) const { + error_code result = make_error_code(ArgumentOutOfRangeError); + if (pageNum >= 0) { + const uint_least8_t command[] = { + 0x3C, static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region) + : 0xBF)}; + result = writeMemory(commandReg, command); + if (!result) { + sleep->invoke(shaComputationDelayMs * 2); + } + } + return result; +} + +error_code DS2465::computeSlaveSecret(bool swap, int pageNum, + PageRegion region) { + error_code result = make_error_code(ArgumentOutOfRangeError); + if (pageNum >= 0) { + const uint_least8_t command[] = { + 0x4B, static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region) + : 0xBF)}; + result = writeMemory(commandReg, command); + if (!result) { + sleep->invoke(shaComputationDelayMs * 2); + } + } + return result; +} + +error_code DS2465::readPage(int pageNum, Page::span data) const { + uint_least8_t addr; + switch (pageNum) { + case 0: + addr = 0x80; + break; + case 1: + addr = 0xA0; + break; + default: + return make_error_code(ArgumentOutOfRangeError); + } + return readMemory(addr, data); +} + +error_code DS2465::writePage(int pageNum, Page::const_span data) { + error_code result = writeMemory(scratchpad, data); + if (!result) { + result = copyScratchpad(false, pageNum, false, 0); + } + if (!result) { + sleep->invoke(eepromPageWriteDelayMs); + } + return result; +} + +error_code DS2465::writeSegment(int pageNum, int segmentNum, + Segment::const_span data) { + error_code result = writeMemory(scratchpad, data); + if (!result) { + result = copyScratchpad(false, pageNum, true, segmentNum); + } + if (!result) { + sleep->invoke(eepromSegmentWriteDelayMs); + } + return result; +} + +error_code DS2465::writeMasterSecret(Page::const_span masterSecret) { + error_code result = writeMemory(scratchpad, masterSecret); + if (!result) { + result = copyScratchpad(true, 0, false, 0); + } + if (!result) { + sleep->invoke(eepromPageWriteDelayMs); + } + return result; +} + +error_code DS2465::copyScratchpad(bool destSecret, int pageNum, bool notFull, + int segmentNum) { + error_code result = make_error_code(ArgumentOutOfRangeError); + if (pageNum >= 0 && segmentNum >= 0) { + const uint_least8_t command[] = { + 0x5A, + static_cast<uint_least8_t>(destSecret ? 0 + : (0x80 | (pageNum << 4) | + (notFull << 3) | segmentNum))}; + result = writeMemory(commandReg, command); + } + return result; +} + +error_code DS2465::configureLevel(Level level) { + // Check if supported level + if (!((level == NormalLevel) || (level == StrongLevel))) { + return make_error_code(InvalidLevelError); + } + // Check if requested level already set + if (curConfig.getSPU() == (level == StrongLevel)) { + return error_code(); + } + // Set the level + return writeConfig(Config(curConfig).setSPU(level == StrongLevel)); +} + +error_code DS2465::setLevel(Level newLevel) { + if (newLevel == StrongLevel) { + return make_error_code(InvalidLevelError); + } + + return configureLevel(newLevel); +} + +error_code DS2465::setSpeed(Speed newSpeed) { + // Check if supported speed + if (!((newSpeed == OverdriveSpeed) || (newSpeed == StandardSpeed))) { + return make_error_code(InvalidSpeedError); + } + // Check if requested speed is already set + if (curConfig.get1WS() == (newSpeed == OverdriveSpeed)) { + return error_code(); + } + // Set the speed + return writeConfig(Config(curConfig).set1WS(newSpeed == OverdriveSpeed)); +} + +error_code DS2465::triplet(TripletData & data) { + // 1-Wire Triplet (Case B) + // S AD,0 [A] 1WT [A] SS [A] Sr AD,1 [A] [Status] A [Status] A\ P + // \--------/ + // Repeat until 1WB bit has changed to 0 + // [] indicates from slave + // SS indicates byte containing search direction bit value in msbit + + const uint_least8_t command[] = { + 0x78, static_cast<uint_least8_t>(data.writeBit ? 0x80 : 0x00)}; + error_code result = writeMemory(commandReg, command); + if (!result) { + uint_least8_t status; + result = pollBusy(&status); + if (!result) { + // check bit results in status byte + data.readBit = ((status & Status_SBR) == Status_SBR); + data.readBitComplement = ((status & Status_TSB) == Status_TSB); + data.writeBit = ((status & Status_DIR) == Status_DIR); + } + } + return result; +} + +error_code DS2465::readBlock(span<uint_least8_t> recvBuf) { + // 1-Wire Receive Block (Case A) + // S AD,0 [A] CommandReg [A] 1WRF [A] PR [A] P + // [] indicates from slave + // PR indicates byte containing parameter + + error_code result; + span<uint_least8_t>::index_type recvIdx = 0; + while (recvIdx < recvBuf.size() && !result) { + const uint_least8_t command[] = { + 0xE1, + static_cast<uint_least8_t>(std::min<span<uint_least8_t>::index_type>( + recvBuf.size() - recvIdx, maxBlockSize))}; + result = writeMemory(commandReg, command); + if (!result) { + result = pollBusy(); + } + if (!result) { + result = readMemory(scratchpad, recvBuf.subspan(recvIdx, command[1])); + } + recvIdx += command[1]; + } + return result; +} + +error_code DS2465::writeBlock(span<const uint_least8_t> sendBuf) { + error_code result; + span<const uint_least8_t>::index_type sendIdx = 0; + while (sendIdx < sendBuf.size() && !result) { + const uint_least8_t command[] = { + owTransmitBlockCmd, static_cast<uint_least8_t>( + std::min<span<const uint_least8_t>::index_type>( + sendBuf.size() - sendIdx, maxBlockSize))}; + + // prefill scratchpad with required data + result = writeMemory(scratchpad, sendBuf.subspan(sendIdx, command[1])); + + // 1-Wire Transmit Block (Case A) + // S AD,0 [A] CommandReg [A] 1WTB [A] PR [A] P + // [] indicates from slave + // PR indicates byte containing parameter + if (!result) { + result = writeMemory(commandReg, command); + } + if (!result) { + result = pollBusy(); + } + sendIdx += command[1]; + } + return result; +} + +error_code DS2465::writeMacBlock() const { + // 1-Wire Transmit Block (Case A) + // S AD,0 [A] CommandReg [A] 1WTB [A] PR [A] P + // [] indicates from slave + // PR indicates byte containing parameter + + const uint_least8_t command[] = {owTransmitBlockCmd, 0xFF}; + error_code result = writeMemory(commandReg, command); + if (!result) { + result = pollBusy(); + } + return result; +} + +error_code DS2465::readByteSetLevel(uint_least8_t & recvByte, + Level afterLevel) { + // 1-Wire Read Bytes (Case C) + // S AD,0 [A] CommandReg [A] 1WRB [A] Sr AD,1 [A] [Status] A [Status] A + // \--------/ + // Repeat until 1WB bit has changed to 0 + // Sr AD,0 [A] SRP [A] E1 [A] Sr AD,1 [A] DD A\ P + // + // [] indicates from slave + // DD data read + + error_code result = configureLevel(afterLevel); + if (result) { + return result; + } + + const uint_least8_t command = 0x96; + result = writeMemory(commandReg, make_span(&command, 1)); + if (result) { + return result; + } + + result = pollBusy(); + if (result) { + return result; + } + + result = readMemory(0x62, make_span(&recvByte, 1)); + return result; +} + +error_code DS2465::writeByteSetLevel(uint_least8_t sendByte, Level afterLevel) { + // 1-Wire Write Byte (Case B) + // S AD,0 [A] CommandReg [A] 1WWB [A] DD [A] Sr AD,1 [A] [Status] A [Status] + // A\ P + // \--------/ + // Repeat until 1WB bit has changed to 0 + // [] indicates from slave + // DD data to write + + error_code result = configureLevel(afterLevel); + if (result) { + return result; + } + + const uint_least8_t command[] = {0xA5, sendByte}; + result = writeMemory(commandReg, command); + if (result) { + return result; + } + + result = pollBusy(); + return result; +} + +error_code DS2465::touchBitSetLevel(bool & sendRecvBit, Level afterLevel) { + // 1-Wire bit (Case B) + // S AD,0 [A] CommandReg [A] 1WSB [A] BB [A] Sr AD,1 [A] [Status] A [Status] + // A\ P + // \--------/ + // Repeat until 1WB bit has changed to 0 + // [] indicates from slave + // BB indicates byte containing bit value in msbit + + error_code result = configureLevel(afterLevel); + if (result) { + return result; + } + + const uint_least8_t command[] = { + 0x87, static_cast<uint_least8_t>(sendRecvBit ? 0x80 : 0x00)}; + result = writeMemory(commandReg, command); + if (result) { + return result; + } + + uint_least8_t status; + result = pollBusy(&status); + if (!result) { + sendRecvBit = ((status & Status_SBR) == Status_SBR); + } + return result; +} + +error_code DS2465::writeMemory(uint_least8_t addr, + span<const uint_least8_t> buf) const { + // Write SRAM (Case A) + // S AD,0 [A] VSA [A] DD [A] P + // \-----/ + // Repeat for each data byte + // [] indicates from slave + // VSA valid SRAM memory address + // DD memory data to write + + error_code result = master->start(address_); + if (result) { + master->stop(); + return result; + } + result = master->writeByte(addr); + if (result) { + master->stop(); + return result; + } + result = master->writeBlock(buf); + if (result) { + master->stop(); + return result; + } + result = master->stop(); + return result; +} + +error_code DS2465::readMemory(uint_least8_t addr, + span<uint_least8_t> buf) const { + // Read (Case A) + // S AD,0 [A] MA [A] Sr AD,1 [A] [DD] A [DD] A\ P + // \-----/ + // Repeat for each data byte, NAK last byte + // [] indicates from slave + // MA memory address + // DD memory data read + + error_code result = master->start(address_); + if (result) { + master->stop(); + return result; + } + result = master->writeByte(addr); + if (result) { + master->stop(); + return result; + } + result = readMemory(buf); + return result; +} + +error_code DS2465::readMemory(span<uint_least8_t> buf) const { + error_code result = master->start(address_ | 1); + if (result) { + master->stop(); + return result; + } + result = master->readBlock(I2CMaster::Nack, buf); + if (result) { + master->stop(); + return result; + } + result = master->stop(); + return result; +} + +error_code DS2465::writeConfig(Config config) { + const uint_least8_t configReg = 0x67; + uint_least8_t configBuf = + ((config.readByte() ^ 0xF) << 4) | config.readByte(); + error_code result = writeMemory(configReg, make_span(&configBuf, 1)); + if (!result) { + result = readMemory(configReg, make_span(&configBuf, 1)); + } + if (!result) { + if (configBuf != config.readByte()) + result = make_error_code(HardwareError); + } + if (!result) { + curConfig = config; + } + return result; +} + +error_code DS2465::writePortParameter(PortParameter param, int val) { + if (val < 0 || val > 15) { + return make_error_code(ArgumentOutOfRangeError); + } + + uint_least8_t addr = 0; + switch (param) { + case tRSTL_STD: + case tRSTL_OD: + addr = 0x68; + break; + case tMSP_STD: + case tMSP_OD: + addr = 0x69; + break; + case tW0L_STD: + case tW0L_OD: + addr = 0x6A; + break; + case tREC0: + addr = 0x6B; + break; + case RWPU: + addr = 0x6C; + break; + case tW1L_OD: + addr = 0x6D; + break; + } + + uint_least8_t data; + error_code result = readMemory(addr, make_span(&data, 1)); + if (result) { + return result; + } + + uint_least8_t newData; + if (param == tRSTL_OD || param == tMSP_OD || param == tW0L_OD) { + newData = (data & 0x0F) | (val << 4); + } else { + newData = (data & 0xF0) | val; + } + + if (newData != data) { + result = writeMemory(addr, make_span(&newData, 1)); + } + return result; +} + +error_code DS2465::pollBusy(uint_least8_t * pStatus) const { + const int pollLimit = 200; + + int pollCount = 0; + uint_least8_t status; + do { + error_code result = readMemory(make_span(&status, 1)); + if (result) { + return result; + } + if (pStatus != NULL) { + *pStatus = status; + } + if (pollCount++ >= pollLimit) { + return make_error_code(HardwareError); + } + } while (status & Status_1WB); + + return error_code(); +} + +error_code DS2465::reset() { + // 1-Wire reset (Case B) + // S AD,0 [A] CommandReg [A] 1WRS [A] Sr AD,1 [A] [Status] A [Status] A\ P + // \--------/ + // Repeat until 1WB bit has changed to 0 + // [] indicates from slave + + uint_least8_t buf = 0xB4; + error_code result = writeMemory(commandReg, make_span(&buf, 1)); + + if (!result) { + result = pollBusy(&buf); + } + + if (!result) { + if ((buf & Status_SD) == Status_SD) { + result = make_error_code(ShortDetectedError); + } else if ((buf & Status_PPD) != Status_PPD) { + result = make_error_code(NoSlaveError); + } + } + + return result; +} + +error_code DS2465::resetDevice() { + // Device Reset + // S AD,0 [A] CommandReg [A] 1WMR [A] Sr AD,1 [A] [SS] A\ P + // [] indicates from slave + // SS status byte to read to verify state + + uint_least8_t buf = 0xF0; + error_code result = writeMemory(commandReg, make_span(&buf, 1)); + + if (!result) { + result = readMemory(make_span(&buf, 1)); + } + + if (!result) { + if ((buf & 0xF7) != 0x10) { + result = make_error_code(HardwareError); + } + } + + if (!result) { + reset(); // do a command to get 1-Wire master reset out of holding state + } + + return result; +} + +error_code +DS2465::computeNextMasterSecret(AuthenticationData::const_span data) { + error_code result = writeMemory(scratchpad, data); + if (!result) { + result = computeNextMasterSecret(false, 0, FullPage); + } + return result; +} + +error_code +DS2465::computeNextMasterSecretWithSwap(AuthenticationData::const_span data, + int pageNum, PageRegion region) { + error_code result = writeMemory(scratchpad, data); + if (!result) { + result = computeNextMasterSecret(true, pageNum, region); + } + return result; +} + +error_code DS2465::computeWriteMac(WriteMacData::const_span data) const { + error_code result = writeMemory(scratchpad, data); + if (!result) { + result = computeWriteMac(false, false, 0, 0); + } + return result; +} + +error_code DS2465::computeWriteMac(WriteMacData::const_span data, + Page::span mac) const { + error_code result = computeWriteMac(data); + if (!result) { + result = readMemory(mac); + } + return result; +} + +error_code +DS2465::computeAndTransmitWriteMac(WriteMacData::const_span data) const { + error_code result = computeWriteMac(data); + if (!result) { + result = writeMacBlock(); + } + return result; +} + +error_code DS2465::computeWriteMacWithSwap(WriteMacData::const_span data, + int pageNum, int segmentNum) const { + error_code result = writeMemory(scratchpad, data); + if (!result) { + result = computeWriteMac(false, true, pageNum, segmentNum); + } + return result; +} + +error_code DS2465::computeWriteMacWithSwap(WriteMacData::const_span data, + int pageNum, int segmentNum, + Page::span mac) const { + error_code result = computeWriteMacWithSwap(data, pageNum, segmentNum); + if (!result) { + result = readMemory(mac); + } + return result; +} + +error_code +DS2465::computeAndTransmitWriteMacWithSwap(WriteMacData::const_span data, + int pageNum, int segmentNum) const { + error_code result = computeWriteMacWithSwap(data, pageNum, segmentNum); + if (!result) { + result = writeMacBlock(); + } + return result; +} + +error_code DS2465::computeSlaveSecret(AuthenticationData::const_span data) { + error_code result = writeMemory(scratchpad, data); + if (!result) { + result = computeSlaveSecret(false, 0, FullPage); + } + return result; +} + +error_code +DS2465::computeSlaveSecretWithSwap(AuthenticationData::const_span data, + int pageNum, PageRegion region) { + error_code result = writeMemory(scratchpad, data); + if (!result) { + result = computeSlaveSecret(true, pageNum, region); + } + return result; +} + +error_code DS2465::computeAuthMac(AuthenticationData::const_span data) const { + error_code result = writeMemory(scratchpad, data); + if (!result) { + result = computeAuthMac(false, 0, FullPage); + } + return result; +} + +error_code DS2465::computeAuthMac(AuthenticationData::const_span data, + Page::span mac) const { + error_code result = computeAuthMac(data); + if (!result) { + result = readMemory(mac); + } + return result; +} + +error_code +DS2465::computeAndTransmitAuthMac(AuthenticationData::const_span data) const { + error_code result = computeAuthMac(data); + if (!result) { + result = writeMacBlock(); + } + return result; +} + +error_code DS2465::computeAuthMacWithSwap(AuthenticationData::const_span data, + int pageNum, + PageRegion region) const { + error_code result = writeMemory(scratchpad, data); + if (!result) { + result = computeAuthMac(true, pageNum, region); + } + return result; +} + +error_code DS2465::computeAuthMacWithSwap(AuthenticationData::const_span data, + int pageNum, PageRegion region, + Page::span mac) const { + error_code result = computeAuthMacWithSwap(data, pageNum, region); + if (!result) { + result = readMemory(mac); + } + return result; +} + +error_code DS2465::computeAndTransmitAuthMacWithSwap( + AuthenticationData::const_span data, int pageNum, PageRegion region) const { + error_code result = computeAuthMacWithSwap(data, pageNum, region); + if (!result) { + result = writeMacBlock(); + } + return result; +} + +const error_category & DS2465::errorCategory() { + static class : public error_category { + public: + virtual const char * name() const { return "DS2465"; } + + virtual std::string message(int condition) const { + switch (condition) { + case HardwareError: + return "Hardware Error"; + + case ArgumentOutOfRangeError: + return "Argument Out of Range Error"; + + default: + return defaultErrorMessage(condition); + } + } + } instance; + return instance; +} + +} // namespace MaximInterfaceDevices
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS2465.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,420 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceDevices_DS2465 +#define MaximInterfaceDevices_DS2465 + +#include <MaximInterfaceCore/array_span.hpp> +#include <MaximInterfaceCore/I2CMaster.hpp> +#include <MaximInterfaceCore/OneWireMaster.hpp> +#include <MaximInterfaceCore/Sleep.hpp> +#include "Config.hpp" + +namespace MaximInterfaceDevices { + +/// Interface to the DS2465 1-Wire master and SHA-256 coprocessor. +class DS2465 : public Core::OneWireMaster { +public: + enum ErrorValue { HardwareError = 1, ArgumentOutOfRangeError }; + + /// @brief 1-Wire port adjustment parameters. + /// @note See datasheet page 13. + enum PortParameter { + tRSTL_STD, + tRSTL_OD, + tMSP_STD, + tMSP_OD, + tW0L_STD, + tW0L_OD, + tREC0, + RWPU, + tW1L_OD + }; + + /// Page region to use for swapping. + enum PageRegion { FullPage = 0x03, FirstHalf = 0x01, SecondHalf = 0x02 }; + + /// Holds the contents of a device memory segment. + typedef Core::array_span<uint_least8_t, 4> Segment; + + /// Holds the contents of a device memory page. + typedef Core::array_span<uint_least8_t, 32> Page; + + /// Data for Compute Write MAC operation. + typedef Core::array_span<uint_least8_t, 20> WriteMacData; + + /// Data for the Compute Auth. MAC and Compute Slave Secret operations. + typedef Core::array_span<uint_least8_t, 76> AuthenticationData; + + static const int memoryPages = 2; + static const int segmentsPerPage = Page::size / Segment::size; + + /// Represents a DS2465 configuration. + class Config { + public: + /// Default construct with power-on config. + explicit Config(uint_least8_t readByte = optionAPU) + : readByte_(readByte & 0xF) {} + + /// @name 1WS + /// @brief 1-Wire Speed + /// @{ + + /// Get 1WS bit. + bool get1WS() const { return (readByte_ & option1WS) == option1WS; } + + /// Set 1WS bit. + Config & set1WS(bool new1WS) { + if (new1WS) { + readByte_ |= option1WS; + } else { + readByte_ &= ~option1WS; + } + return *this; + } + + /// @} + + /// @name SPU + /// @brief Strong Pullup + /// @{ + + /// Get SPU bit. + bool getSPU() const { return (readByte_ & optionSPU) == optionSPU; } + + /// Set SPU bit. + Config & setSPU(bool newSPU) { + if (newSPU) { + readByte_ |= optionSPU; + } else { + readByte_ &= ~optionSPU; + } + return *this; + } + + /// @} + + /// @name PDN + /// @brief 1-Wire Power Down + /// @{ + + /// Get PDN bit. + bool getPDN() const { return (readByte_ & optionPDN) == optionPDN; } + + /// Set PDN bit. + Config & setPDN(bool newPDN) { + if (newPDN) { + readByte_ |= optionPDN; + } else { + readByte_ &= ~optionPDN; + } + return *this; + } + + /// @} + + /// @name APU + /// @brief Active Pullup + /// @{ + + /// Get APU bit. + bool getAPU() const { return (readByte_ & optionAPU) == optionAPU; } + + /// Set APU bit. + Config & setAPU(bool newAPU) { + if (newAPU) { + readByte_ |= optionAPU; + } else { + readByte_ &= ~optionAPU; + } + return *this; + } + + /// @} + + /// Byte representation that is read from the DS2465. + uint_least8_t readByte() const { return readByte_; } + + private: + static const unsigned int option1WS = 0x8; + static const unsigned int optionSPU = 0x4; + static const unsigned int optionPDN = 0x2; + static const unsigned int optionAPU = 0x1; + + uint_least8_t readByte_; + }; + + // Const member functions should not change the settings of the DS2465 or + // affect the state of the 1-Wire bus. Read pointer, scratchpad, MAC output + // register, and command register on the DS2465 are considered mutable. + + DS2465(Core::Sleep & sleep, Core::I2CMaster & master, + uint_least8_t address = 0x30) + : sleep(&sleep), master(&master), address_(address & 0xFE) {} + + void setSleep(Core::Sleep & sleep) { this->sleep = &sleep; } + + void setMaster(Core::I2CMaster & master) { this->master = &master; } + + uint_least8_t address() const { return address_; } + + void setAddress(uint_least8_t address) { address_ = address & 0xFE; } + + /// Initialize hardware for use. + MaximInterfaceDevices_EXPORT Core::error_code + initialize(Config config = Config()); + + /// @brief Write a new configuration to the DS2465. + /// @param[in] config New configuration to write. + MaximInterfaceDevices_EXPORT Core::error_code writeConfig(Config config); + + /// @brief Write a new port configuration parameter to the DS2465. + /// @param[in] param Parameter to adjust. + /// @param[in] val + /// New parameter value to set. Consult datasheet for value mappings. + MaximInterfaceDevices_EXPORT Core::error_code + writePortParameter(PortParameter param, int val); + + // 1-Wire Master Commands + + MaximInterfaceDevices_EXPORT virtual Core::error_code reset(); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + touchBitSetLevel(bool & sendRecvBit, Level afterLevel); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + readByteSetLevel(uint_least8_t & recvByte, Level afterLevel); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + writeByteSetLevel(uint_least8_t sendByte, Level afterLevel); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + readBlock(Core::span<uint_least8_t> recvBuf); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + writeBlock(Core::span<const uint_least8_t> sendBuf); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + setSpeed(Speed newSpeed); + + /// @copydoc Core::OneWireMaster::setLevel + /// @note + /// The DS2465 only supports enabling strong pullup following a 1-Wire read or + /// write operation. + MaximInterfaceDevices_EXPORT virtual Core::error_code + setLevel(Level newLevel); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + triplet(TripletData & data); + + // DS2465 Coprocessor Commands + + /// @brief Read data from an EEPROM memory page. + /// @param pageNum Page number to read from. + /// @param[out] data Data that was read. + MaximInterfaceDevices_EXPORT Core::error_code readPage(int pageNum, + Page::span data) const; + + /// @brief Write data to an EEPROM memory page. + /// @param pageNum Page number to copy to. + /// @param data Data to write. + MaximInterfaceDevices_EXPORT Core::error_code + writePage(int pageNum, Page::const_span data); + + /// @brief Write data to an EEPROM memory segment. + /// @param pageNum Page number to copy to. + /// @param segmentNum Segment number to copy to. + /// @param data Data to write. + MaximInterfaceDevices_EXPORT Core::error_code + writeSegment(int pageNum, int segmentNum, Segment::const_span data); + + /// Write data to the secret EEPROM memory page. + MaximInterfaceDevices_EXPORT Core::error_code + writeMasterSecret(Page::const_span masterSecret); + + /// @brief Compute Next Master Secret. + /// @param data Combined data fields for computation. + MaximInterfaceDevices_EXPORT Core::error_code + computeNextMasterSecret(AuthenticationData::const_span data); + + /// @brief Compute Next Master Secret with page swapping. + /// @param data Combined data fields for computation. + /// @param pageNum Page number to swap in. + /// @param region Region of the page to swap in. + MaximInterfaceDevices_EXPORT Core::error_code + computeNextMasterSecretWithSwap(AuthenticationData::const_span data, + int pageNum, PageRegion region); + + /// @brief Compute Write MAC. + /// @param data Combined data fields for computation. + /// @param[out] mac Computed Write MAC. + MaximInterfaceDevices_EXPORT Core::error_code + computeWriteMac(WriteMacData::const_span data, Page::span mac) const; + + /// @brief Compute Write MAC. + /// @param data Combined data fields for computation. + MaximInterfaceDevices_EXPORT Core::error_code + computeAndTransmitWriteMac(WriteMacData::const_span data) const; + + /// @brief Compute Write MAC with page swapping. + /// @param data Combined data fields for computation. + /// @param pageNum Page number to swap in. + /// @param segmentNum Segment number to swap in. + /// @param[out] mac Computed Write MAC. + MaximInterfaceDevices_EXPORT Core::error_code + computeWriteMacWithSwap(WriteMacData::const_span data, int pageNum, + int segmentNum, Page::span mac) const; + + /// @brief Compute Write MAC with page swapping. + /// @param data Combined data fields for computation. + /// @param pageNum Page number to swap in. + /// @param segmentNum Segment number to swap in. + MaximInterfaceDevices_EXPORT Core::error_code + computeAndTransmitWriteMacWithSwap(WriteMacData::const_span data, int pageNum, + int segmentNum) const; + + /// @brief Compute Slave Secret (S-Secret). + /// @param data Combined data fields for computation. + MaximInterfaceDevices_EXPORT Core::error_code + computeSlaveSecret(AuthenticationData::const_span data); + + /// @brief Compute Slave Secret (S-Secret) with page swapping. + /// @param data Combined data fields for computation. + /// @param pageNum Page number to swap in. + /// @param region Region of the page to swap in. + MaximInterfaceDevices_EXPORT Core::error_code + computeSlaveSecretWithSwap(AuthenticationData::const_span data, int pageNum, + PageRegion region); + + /// @brief Compute Authentication MAC. + /// @param data Combined data fields for computation. + /// @param[out] mac Computed Auth MAC. + MaximInterfaceDevices_EXPORT Core::error_code + computeAuthMac(AuthenticationData::const_span data, Page::span mac) const; + + /// @brief Compute Authentication MAC. + /// @param data Combined data fields for computation. + MaximInterfaceDevices_EXPORT Core::error_code + computeAndTransmitAuthMac(AuthenticationData::const_span data) const; + + /// @brief Compute Authentication MAC with page swapping. + /// @param data Combined data fields for computation. + /// @param pageNum Page number to swap in. + /// @param region Region of the page to swap in. + /// @param[out] mac Computed Auth MAC. + MaximInterfaceDevices_EXPORT Core::error_code + computeAuthMacWithSwap(AuthenticationData::const_span data, int pageNum, + PageRegion region, Page::span mac) const; + + /// @brief Compute Authentication MAC with page swapping. + /// @param data Combined data fields for computation. + /// @param pageNum Page number to swap in. + /// @param region Region of the page to swap in. + MaximInterfaceDevices_EXPORT Core::error_code + computeAndTransmitAuthMacWithSwap(AuthenticationData::const_span data, + int pageNum, PageRegion region) const; + + MaximInterfaceDevices_EXPORT static const Core::error_category & + errorCategory(); + +private: + const Core::Sleep * sleep; + Core::I2CMaster * master; + uint_least8_t address_; + Config curConfig; + + /// @brief Performs a soft reset on the DS2465. + /// @note This is not a 1-Wire Reset. + Core::error_code resetDevice(); + + /// @brief + /// Polls the DS2465 status waiting for the 1-Wire Busy bit (1WB) to be + /// cleared. + /// @param[out] pStatus Optionally retrive the status byte when 1WB cleared. + /// @returns Success or TimeoutError if poll limit reached. + Core::error_code pollBusy(uint_least8_t * pStatus = NULL) const; + + /// @brief Ensure that the desired 1-Wire level is set in the configuration. + /// @param level Desired 1-Wire level. + Core::error_code configureLevel(Level level); + + /// @note Const since only for internal use. + Core::error_code writeMemory(uint_least8_t addr, + Core::span<const uint_least8_t> buf) const; + + /// @brief Read memory from the DS2465. + /// @param addr Address to begin reading from. + /// @param[out] buf Buffer to hold read data. + Core::error_code readMemory(uint_least8_t addr, + Core::span<uint_least8_t> buf) const; + + /// @brief Read memory from the DS2465 at the current pointer. + /// @param[out] buf Buffer to hold read data. + Core::error_code readMemory(Core::span<uint_least8_t> buf) const; + + /// Write the last computed MAC to the 1-Wire bus. + Core::error_code writeMacBlock() const; + + Core::error_code computeWriteMac(WriteMacData::const_span data) const; + + Core::error_code computeWriteMacWithSwap(WriteMacData::const_span data, + int pageNum, int segmentNum) const; + + Core::error_code computeAuthMac(AuthenticationData::const_span data) const; + + Core::error_code computeAuthMacWithSwap(AuthenticationData::const_span data, + int pageNum, PageRegion region) const; + + // Legacy implementations + Core::error_code copyScratchpad(bool destSecret, int pageNum, bool notFull, + int segmentNum); + + Core::error_code computeNextMasterSecret(bool swap, int pageNum, + PageRegion region); + + Core::error_code computeWriteMac(bool regwrite, bool swap, int pageNum, + int segmentNum) const; + + Core::error_code computeSlaveSecret(bool swap, int pageNum, + PageRegion region); + + Core::error_code computeAuthMac(bool swap, int pageNum, + PageRegion region) const; +}; + +inline Core::error_code make_error_code(DS2465::ErrorValue e) { + return Core::error_code(e, DS2465::errorCategory()); +} + +} // namespace MaximInterfaceDevices + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS2480B.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,561 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include <MaximInterfaceCore/Error.hpp> +#include "DS2480B.hpp" + +// Mode Commands +#define MODE_DATA 0xE1 +#define MODE_COMMAND 0xE3 +#define MODE_STOP_PULSE 0xF1 + +// Return byte value +#define RB_CHIPID_MASK 0x1C +#define RB_RESET_MASK 0x03 +#define RB_1WIRESHORT 0x00 +#define RB_PRESENCE 0x01 +#define RB_ALARMPRESENCE 0x02 +#define RB_NOPRESENCE 0x03 + +#define RB_BIT_MASK 0x03 +#define RB_BIT_ONE 0x03 +#define RB_BIT_ZERO 0x00 + +// Masks for all bit ranges +#define CMD_MASK 0x80 +#define FUNCTSEL_MASK 0x60 +#define BITPOL_MASK 0x10 +#define SPEEDSEL_MASK 0x0C +#define MODSEL_MASK 0x02 +#define PARMSEL_MASK 0x70 +#define PARMSET_MASK 0x0E + +// Command or config bit +#define CMD_COMM 0x81 +#define CMD_CONFIG 0x01 + +// Function select bits +#define FUNCTSEL_BIT 0x00 +#define FUNCTSEL_SEARCHON 0x30 +#define FUNCTSEL_SEARCHOFF 0x20 +#define FUNCTSEL_RESET 0x40 +#define FUNCTSEL_CHMOD 0x60 + +// Bit polarity/Pulse voltage bits +#define BITPOL_ONE 0x10 +#define BITPOL_ZERO 0x00 +#define BITPOL_5V 0x00 +#define BITPOL_12V 0x10 + +// One Wire speed bits +#define SPEEDSEL_STD 0x00 +#define SPEEDSEL_FLEX 0x04 +#define SPEEDSEL_OD 0x08 +#define SPEEDSEL_PULSE 0x0C + +// Data/Command mode select bits +#define MODSEL_DATA 0x00 +#define MODSEL_COMMAND 0x02 + +// 5V Follow Pulse select bits +#define PRIME5V_TRUE 0x02 +#define PRIME5V_FALSE 0x00 + +// Parameter select bits +#define PARMSEL_PARMREAD 0x00 +#define PARMSEL_SLEW 0x10 +#define PARMSEL_12VPULSE 0x20 +#define PARMSEL_5VPULSE 0x30 +#define PARMSEL_WRITE1LOW 0x40 +#define PARMSEL_SAMPLEOFFSET 0x50 +#define PARMSEL_ACTIVEPULLUPTIME 0x60 +#define PARMSEL_BAUDRATE 0x70 + +// Pull down slew rate. +#define PARMSET_Slew15Vus 0x00 +#define PARMSET_Slew2p2Vus 0x02 +#define PARMSET_Slew1p65Vus 0x04 +#define PARMSET_Slew1p37Vus 0x06 +#define PARMSET_Slew1p1Vus 0x08 +#define PARMSET_Slew0p83Vus 0x0A +#define PARMSET_Slew0p7Vus 0x0C +#define PARMSET_Slew0p55Vus 0x0E + +// 12V programming pulse time table +#define PARMSET_32us 0x00 +#define PARMSET_64us 0x02 +#define PARMSET_128us 0x04 +#define PARMSET_256us 0x06 +#define PARMSET_512us 0x08 +#define PARMSET_1024us 0x0A +#define PARMSET_2048us 0x0C +#define PARMSET_infinite 0x0E + +// 5V strong pull up pulse time table +#define PARMSET_16p4ms 0x00 +#define PARMSET_65p5ms 0x02 +#define PARMSET_131ms 0x04 +#define PARMSET_262ms 0x06 +#define PARMSET_524ms 0x08 +#define PARMSET_1p05s 0x0A +#define PARMSET_dynamic 0x0C +#define PARMSET_infinite 0x0E + +// Write 1 low time +#define PARMSET_Write8us 0x00 +#define PARMSET_Write9us 0x02 +#define PARMSET_Write10us 0x04 +#define PARMSET_Write11us 0x06 +#define PARMSET_Write12us 0x08 +#define PARMSET_Write13us 0x0A +#define PARMSET_Write14us 0x0C +#define PARMSET_Write15us 0x0E + +// Data sample offset and Write 0 recovery time +#define PARMSET_SampOff3us 0x00 +#define PARMSET_SampOff4us 0x02 +#define PARMSET_SampOff5us 0x04 +#define PARMSET_SampOff6us 0x06 +#define PARMSET_SampOff7us 0x08 +#define PARMSET_SampOff8us 0x0A +#define PARMSET_SampOff9us 0x0C +#define PARMSET_SampOff10us 0x0E + +// Active pull up on time +#define PARMSET_PullUp0p0us 0x00 +#define PARMSET_PullUp0p5us 0x02 +#define PARMSET_PullUp1p0us 0x04 +#define PARMSET_PullUp1p5us 0x06 +#define PARMSET_PullUp2p0us 0x08 +#define PARMSET_PullUp2p5us 0x0A +#define PARMSET_PullUp3p0us 0x0C +#define PARMSET_PullUp3p5us 0x0E + +// Baud rate bits +#define PARMSET_9600 0x00 +#define PARMSET_19200 0x02 +#define PARMSET_57600 0x04 +#define PARMSET_115200 0x06 + +// DS2480B program voltage available +#define DS2480BPROG_MASK 0x20 + +namespace MaximInterfaceDevices { + +using namespace Core; + +error_code DS2480B::initialize() { + level = NormalLevel; + mode = MODSEL_COMMAND; + speed = SPEEDSEL_STD; + + // Send a break to reset the DS2480B. + // Switch to lower baud rate to ensure break is longer than 2 ms. + error_code result = uart->setBaudRate(4800); + if (result) { + return result; + } + result = uart->sendBreak(); + if (result) { + return result; + } + result = uart->setBaudRate(9600); + if (result) { + return result; + } + + // Wait for master reset. + sleep->invoke(1); + + // Flush the read buffer. + result = uart->clearReadBuffer(); + if (result) { + return result; + } + + // Send the timing byte. + result = uart->writeByte(CMD_COMM | FUNCTSEL_RESET | SPEEDSEL_STD); + if (result) { + return result; + } + + // Change the DS2480 baud rate. + result = uart->writeByte(CMD_CONFIG | PARMSEL_BAUDRATE | PARMSET_115200); + if (result) { + return result; + } + + // Change our baud rate. + result = uart->setBaudRate(115200); + if (result) { + return result; + } + + uint_least8_t response; + + // Verify response. + result = uart->readByte(response); + if (result) { + return result; + } + if ((response & (PARMSEL_MASK | PARMSET_MASK)) != + (PARMSEL_BAUDRATE | PARMSET_115200)) { + return make_error_code(HardwareError); + } + + // Set the SPUD time value. + result = uart->writeByte(CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite); + if (result) { + return result; + } + + // Verify response. + result = uart->readByte(response); + if (result) { + return result; + } + if ((response & (PARMSEL_MASK | PARMSET_MASK)) != + (PARMSEL_5VPULSE | PARMSET_infinite)) { + return make_error_code(HardwareError); + } + + return result; +} + +error_code DS2480B::reset() { + if (level != NormalLevel) { + return make_error_code(InvalidLevelError); + } + + uint_least8_t packet[2]; + int packetLen = 0; + + // Check for correct mode. + if (mode != MODSEL_COMMAND) { + mode = MODSEL_COMMAND; + packet[packetLen++] = MODE_COMMAND; + } + + // Construct the command. + packet[packetLen++] = CMD_COMM | FUNCTSEL_RESET | speed; + + // Send the packet. + error_code result = uart->writeBlock(make_span(packet, packetLen)); + if (result) { + return result; + } + + // Read back the response. + result = uart->readByte(packet[0]); + if (result) { + return result; + } + + // Make sure this byte looks like a reset byte. + if ((packet[0] & RB_RESET_MASK) == RB_1WIRESHORT) { + result = make_error_code(ShortDetectedError); + } else if ((packet[0] & RB_RESET_MASK) == RB_NOPRESENCE) { + result = make_error_code(NoSlaveError); + } + return result; +} + +error_code DS2480B::touchBitSetLevel(bool & sendRecvBit, Level afterLevel) { + if (level != NormalLevel) { + return make_error_code(InvalidLevelError); + } + + uint_least8_t packet[3]; + int packetLen = 0; + + // Check for correct mode. + if (mode != MODSEL_COMMAND) { + mode = MODSEL_COMMAND; + packet[packetLen++] = MODE_COMMAND; + } + + // Construct the command. + packet[packetLen++] = CMD_COMM | FUNCTSEL_BIT | + (sendRecvBit ? BITPOL_ONE : BITPOL_ZERO) | speed; + switch (afterLevel) { + case NormalLevel: + break; + + case StrongLevel: + // Add the command to begin the pulse. + packet[packetLen++] = + CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V | PRIME5V_FALSE; + break; + + default: + return make_error_code(InvalidLevelError); + } + + // Send the packet. + error_code result = uart->writeBlock(make_span(packet, packetLen)); + if (result) { + return result; + } + + // Read back the response. + result = uart->readByte(packet[0]); + if (result) { + return result; + } + + // Interpret the response. + if ((packet[0] & 0xE0) == 0x80) { + sendRecvBit = ((packet[0] & RB_BIT_MASK) == RB_BIT_ONE); + level = afterLevel; + } else { + result = make_error_code(HardwareError); + } + return result; +} + +error_code DS2480B::writeByteSetLevel(uint_least8_t sendByte, + Level afterLevel) { + if (level != NormalLevel) { + return make_error_code(InvalidLevelError); + } + + switch (afterLevel) { + case NormalLevel: + break; + + case StrongLevel: + return OneWireMaster::writeByteSetLevel(sendByte, afterLevel); + + default: + return make_error_code(InvalidLevelError); + } + + uint_least8_t packet[3]; + int packetLen = 0; + + // Check for correct mode. + if (mode != MODSEL_DATA) { + mode = MODSEL_DATA; + packet[packetLen++] = MODE_DATA; + } + + // Add the byte to send. + packet[packetLen++] = sendByte; + + // Check for duplication of data that looks like COMMAND mode. + if (sendByte == MODE_COMMAND) { + packet[packetLen++] = sendByte; + } + + // Send the packet. + error_code result = uart->writeBlock(make_span(packet, packetLen)); + if (result) { + return result; + } + + // Read back the response. + result = uart->readByte(packet[0]); + if (result) { + return result; + } + + // Interpret the response. + if (packet[0] != sendByte) { + result = make_error_code(HardwareError); + } + return result; +} + +error_code DS2480B::readByteSetLevel(uint_least8_t & recvByte, + Level afterLevel) { + if (level != NormalLevel) { + return make_error_code(InvalidLevelError); + } + + switch (afterLevel) { + case NormalLevel: + break; + + case StrongLevel: + return OneWireMaster::readByteSetLevel(recvByte, afterLevel); + + default: + return make_error_code(InvalidLevelError); + } + + uint_least8_t packet[2]; + int packetLen = 0; + + // Check for correct mode. + if (mode != MODSEL_DATA) { + mode = MODSEL_DATA; + packet[packetLen++] = MODE_DATA; + } + + // Add the byte to send. + packet[packetLen++] = 0xFF; + + // Send the packet. + error_code result = uart->writeBlock(make_span(packet, packetLen)); + if (result) { + return result; + } + + // Read back the response. + result = uart->readByte(recvByte); + return result; +} + +error_code DS2480B::setSpeed(Speed newSpeed) { + uint_least8_t newSpeedByte; + switch (newSpeed) { + case OverdriveSpeed: + newSpeedByte = SPEEDSEL_OD; + break; + + case StandardSpeed: + newSpeedByte = SPEEDSEL_STD; + break; + + default: + return make_error_code(InvalidSpeedError); + } + if (speed == newSpeedByte) { + return error_code(); + } + speed = newSpeedByte; + + uint_least8_t packet[2]; + int packetLen = 0; + + // Check for correct mode. + if (mode != MODSEL_COMMAND) { + mode = MODSEL_COMMAND; + packet[packetLen++] = MODE_COMMAND; + } + + // Change DS2480 speed. + packet[packetLen++] = CMD_COMM | FUNCTSEL_SEARCHOFF | speed; + + // Send the packet. + return uart->writeBlock(make_span(packet, packetLen)); +} + +error_code DS2480B::setLevel(Level newLevel) { + if (level == newLevel) { + return error_code(); + } + + uint_least8_t packet[2]; + int packetLen = 0; + + switch (newLevel) { + case NormalLevel: + // Stop pulse command. + packet[packetLen++] = MODE_STOP_PULSE; + break; + + case StrongLevel: + // Check for correct mode. + if (mode != MODSEL_COMMAND) { + mode = MODSEL_COMMAND; + packet[packetLen++] = MODE_COMMAND; + } + + // Add the command to begin the pulse. + packet[packetLen++] = + CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V | PRIME5V_FALSE; + break; + + default: + return make_error_code(InvalidLevelError); + } + + // Send the packet. + error_code result = uart->writeBlock(make_span(packet, packetLen)); + if (result) { + return result; + } + + if (newLevel == NormalLevel) { + // Read back the response. + result = uart->readByte(packet[0]); + if (result) { + return result; + } + + // Interpret the response. + if ((packet[0] & 0xE0) != 0xE0) { + return make_error_code(HardwareError); + } + } + + level = newLevel; + return result; +} + +error_code DS2480B::sendCommand(uint_least8_t command) { + uint_least8_t packet[2]; + int packetLen = 0; + + // Check for correct mode. + if (mode != MODSEL_COMMAND) { + mode = MODSEL_COMMAND; + packet[packetLen++] = MODE_COMMAND; + } + + // Add command. + packet[packetLen++] = command; + + // Send the packet. + return uart->writeBlock(make_span(packet, packetLen)); +} + +const error_category & DS2480B::errorCategory() { + static class : public error_category { + public: + virtual const char * name() const { return "DS2480B"; } + + virtual std::string message(int condition) const { + switch (condition) { + case HardwareError: + return "Hardware Error"; + + default: + return defaultErrorMessage(condition); + } + } + } instance; + return instance; +} + +} // namespace MaximInterfaceDevices
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS2480B.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,96 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceDevices_DS2480B +#define MaximInterfaceDevices_DS2480B + +#include <MaximInterfaceCore/OneWireMaster.hpp> +#include <MaximInterfaceCore/Sleep.hpp> +#include <MaximInterfaceCore/Uart.hpp> +#include "Config.hpp" + +namespace MaximInterfaceDevices { + +/// Serial to 1-Wire Line Driver +class DS2480B : public Core::OneWireMaster { +public: + enum ErrorValue { HardwareError = 1 }; + + DS2480B(Core::Sleep & sleep, Core::Uart & uart) + : sleep(&sleep), uart(&uart) {} + + void setSleep(Core::Sleep & sleep) { this->sleep = &sleep; } + + void setUart(Core::Uart & uart) { this->uart = &uart; } + + MaximInterfaceDevices_EXPORT Core::error_code initialize(); + + MaximInterfaceDevices_EXPORT virtual Core::error_code reset(); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + touchBitSetLevel(bool & sendRecvBit, Level afterLevel); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + writeByteSetLevel(uint_least8_t sendByte, Level afterLevel); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + readByteSetLevel(uint_least8_t & recvByte, Level afterLevel); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + setSpeed(Speed newSpeed); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + setLevel(Level newLevel); + + MaximInterfaceDevices_EXPORT static const Core::error_category & + errorCategory(); + +protected: + MaximInterfaceDevices_EXPORT Core::error_code + sendCommand(uint_least8_t command); + +private: + const Core::Sleep * sleep; + Core::Uart * uart; + + Level level; + uint_least8_t mode; + uint_least8_t speed; +}; + +inline Core::error_code make_error_code(DS2480B::ErrorValue e) { + return Core::error_code(e, DS2480B::errorCategory()); +} + +} // namespace MaximInterfaceDevices + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS2482_DS2484.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,426 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include <MaximInterfaceCore/Error.hpp> +#include "DS2482_DS2484.hpp" + +namespace MaximInterfaceDevices { + +using namespace Core; + +// Device Status bits +enum StatusBit { + Status_1WB = 0x01, + Status_PPD = 0x02, + Status_SD = 0x04, + Status_LL = 0x08, + Status_RST = 0x10, + Status_SBR = 0x20, + Status_TSB = 0x40, + Status_DIR = 0x80 +}; + +error_code DS2482_DS2484::initialize(Config config) { + error_code result = resetDevice(); + if (result) { + return result; + } + // Write the default configuration setup. + result = writeConfig(config); + return result; +} + +error_code DS2482_DS2484::resetDevice() { + // Device Reset + // S AD,0 [A] DRST [A] Sr AD,1 [A] [SS] A\ P + // [] indicates from slave + // SS status byte to read to verify state + + error_code result = sendCommand(0xF0); + if (result) { + return result; + } + + uint_least8_t buf; + result = readRegister(buf); + if (result) { + return result; + } + + if ((buf & 0xF7) != 0x10) { + return make_error_code(HardwareError); + } + + // Do a command to get 1-Wire master reset out of holding state. + reset(); + + return result; +} + +error_code DS2482_DS2484::triplet(TripletData & data) { + // 1-Wire Triplet (Case B) + // S AD,0 [A] 1WT [A] SS [A] Sr AD,1 [A] [Status] A [Status] A\ P + // \--------/ + // Repeat until 1WB bit has changed to 0 + // [] indicates from slave + // SS indicates byte containing search direction bit value in msbit + + error_code result = sendCommand(0x78, data.writeBit ? 0x80 : 0x00); + if (!result) { + uint_least8_t status; + result = pollBusy(&status); + if (!result) { + data.readBit = ((status & Status_SBR) == Status_SBR); + data.readBitComplement = ((status & Status_TSB) == Status_TSB); + data.writeBit = ((status & Status_DIR) == Status_DIR); + } + } + return result; +} + +error_code DS2482_DS2484::reset() { + // 1-Wire reset (Case B) + // S AD,0 [A] 1WRS [A] Sr AD,1 [A] [Status] A [Status] A\ P + // \--------/ + // Repeat until 1WB bit has changed to 0 + // [] indicates from slave + + error_code result = sendCommand(0xB4); + if (result) { + return result; + } + + uint_least8_t buf; + result = pollBusy(&buf); + if (result) { + return result; + } + + if ((buf & Status_SD) == Status_SD) { + result = make_error_code(ShortDetectedError); + } else if ((buf & Status_PPD) != Status_PPD) { + result = make_error_code(NoSlaveError); + } + + return result; +} + +error_code DS2482_DS2484::touchBitSetLevel(bool & sendRecvBit, + Level afterLevel) { + // 1-Wire bit (Case B) + // S AD,0 [A] 1WSB [A] BB [A] Sr AD,1 [A] [Status] A [Status] A\ P + // \--------/ + // Repeat until 1WB bit has changed to 0 + // [] indicates from slave + // BB indicates byte containing bit value in msbit + + error_code result = configureLevel(afterLevel); + if (result) { + return result; + } + + result = sendCommand(0x87, sendRecvBit ? 0x80 : 0x00); + if (result) { + return result; + } + + uint_least8_t status; + result = pollBusy(&status); + if (!result) { + sendRecvBit = ((status & Status_SBR) == Status_SBR); + } + return result; +} + +error_code DS2482_DS2484::writeByteSetLevel(uint_least8_t sendByte, + Level afterLevel) { + // 1-Wire Write Byte (Case B) + // S AD,0 [A] 1WWB [A] DD [A] Sr AD,1 [A] [Status] A [Status] A\ P + // \--------/ + // Repeat until 1WB bit has changed to 0 + // [] indicates from slave + // DD data to write + + error_code result = configureLevel(afterLevel); + if (result) { + return result; + } + + result = sendCommand(0xA5, sendByte); + if (result) { + return result; + } + + result = pollBusy(); + return result; +} + +error_code DS2482_DS2484::readByteSetLevel(uint_least8_t & recvByte, + Level afterLevel) { + // 1-Wire Read Bytes (Case C) + // S AD,0 [A] 1WRB [A] Sr AD,1 [A] [Status] A [Status] A + // \--------/ + // Repeat until 1WB bit has changed to 0 + // Sr AD,0 [A] SRP [A] E1 [A] Sr AD,1 [A] DD A\ P + // + // [] indicates from slave + // DD data read + + error_code result = configureLevel(afterLevel); + if (result) { + return result; + } + + result = sendCommand(0x96); + if (result) { + return result; + } + + result = pollBusy(); + if (result) { + return result; + } + + result = readRegister(0xE1, recvByte); + return result; +} + +error_code DS2482_DS2484::setSpeed(Speed newSpeed) { + // Check if supported speed + if (!((newSpeed == OverdriveSpeed) || (newSpeed == StandardSpeed))) { + return make_error_code(InvalidSpeedError); + } + // Check if requested speed is already set + if (curConfig.get1WS() == (newSpeed == OverdriveSpeed)) { + return error_code(); + } + // Set the speed + return writeConfig(Config(curConfig).set1WS(newSpeed == OverdriveSpeed)); +} + +error_code DS2482_DS2484::setLevel(Level newLevel) { + if (newLevel == StrongLevel) { + return make_error_code(InvalidLevelError); + } + + return configureLevel(newLevel); +} + +error_code DS2482_DS2484::writeConfig(Config config) { + uint_least8_t configBuf = + ((config.readByte() ^ 0xF) << 4) | config.readByte(); + error_code result = sendCommand(0xD2, configBuf); + if (!result) { + result = readRegister(0xC3, configBuf); + } + if (!result) { + if (configBuf != config.readByte()) { + result = make_error_code(HardwareError); + } + } + if (!result) { + curConfig = config; + } + return result; +} + +error_code DS2482_DS2484::readRegister(uint_least8_t reg, + uint_least8_t & buf) const { + error_code result = sendCommand(0xE1, reg); + if (!result) { + result = readRegister(buf); + } + return result; +} + +error_code DS2482_DS2484::readRegister(uint_least8_t & buf) const { + return master->readPacket(address_, make_span(&buf, 1)); +} + +error_code DS2482_DS2484::pollBusy(uint_least8_t * pStatus) { + const int pollLimit = 200; + + int pollCount = 0; + uint_least8_t status; + do { + error_code result = readRegister(status); + if (result) { + return result; + } + if (pStatus != NULL) { + *pStatus = status; + } + if (pollCount++ >= pollLimit) { + return make_error_code(HardwareError); + } + } while (status & Status_1WB); + + return error_code(); +} + +error_code DS2482_DS2484::configureLevel(Level level) { + // Check if supported level + if (!((level == NormalLevel) || (level == StrongLevel))) { + return make_error_code(InvalidLevelError); + } + // Check if requested level already set + if (curConfig.getSPU() == (level == StrongLevel)) { + return error_code(); + } + // Set the level + return writeConfig(Config(curConfig).setSPU(level == StrongLevel)); +} + +error_code DS2482_DS2484::sendCommand(uint_least8_t cmd) const { + return master->writePacket(address_, make_span(&cmd, 1)); +} + +error_code DS2482_DS2484::sendCommand(uint_least8_t cmd, + uint_least8_t param) const { + uint_least8_t buf[] = {cmd, param}; + return master->writePacket(address_, buf); +} + +const error_category & DS2482_DS2484::errorCategory() { + static class : public error_category { + public: + virtual const char * name() const { return "DS2482_DS2484"; } + + virtual std::string message(int condition) const { + switch (condition) { + case HardwareError: + return "Hardware Error"; + + case ArgumentOutOfRangeError: + return "Argument Out of Range Error"; + + default: + return defaultErrorMessage(condition); + } + } + } instance; + return instance; +} + +error_code DS2482_800::selectChannel(int channel) { + // Channel Select (Case A) + // S AD,0 [A] CHSL [A] CC [A] Sr AD,1 [A] [RR] A\ P + // [] indicates from slave + // CC channel value + // RR channel read back + + uint_least8_t ch; + uint_least8_t ch_read; + switch (channel) { + case 0: + ch = 0xF0; + ch_read = 0xB8; + break; + + case 1: + ch = 0xE1; + ch_read = 0xB1; + break; + + case 2: + ch = 0xD2; + ch_read = 0xAA; + break; + + case 3: + ch = 0xC3; + ch_read = 0xA3; + break; + + case 4: + ch = 0xB4; + ch_read = 0x9C; + break; + + case 5: + ch = 0xA5; + ch_read = 0x95; + break; + + case 6: + ch = 0x96; + ch_read = 0x8E; + break; + + case 7: + ch = 0x87; + ch_read = 0x87; + break; + + default: + return make_error_code(ArgumentOutOfRangeError); + }; + + error_code result = sendCommand(0xC3, ch); + if (!result) { + result = readRegister(ch); + if (!result) { + // check for failure due to incorrect read back of channel + if (ch != ch_read) { + result = make_error_code(HardwareError); + } + } + } + + return result; +} + +error_code DS2484::adjustPort(PortParameter param, int val) { + if (val < 0 || val > 15) { + return make_error_code(ArgumentOutOfRangeError); + } + + error_code result = sendCommand(0xC3, (param << 4) | val); + if (result) { + return result; + } + + uint_least8_t portConfig = val + 1; + for (int reads = -1; reads < param; ++reads) { + result = readRegister(portConfig); + if (result) { + return result; + } + } + if (val != portConfig) { + result = make_error_code(HardwareError); + } + + return result; +} + +} // namespace MaximInterfaceDevices
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS2482_DS2484.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,267 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceDevices_DS2482_DS2484 +#define MaximInterfaceDevices_DS2482_DS2484 + +#include <MaximInterfaceCore/I2CMaster.hpp> +#include <MaximInterfaceCore/OneWireMaster.hpp> +#include "Config.hpp" + +namespace MaximInterfaceDevices { + +/// Interface to the DS2484, DS2482-100, DS2482-101, DS2482-800 1-Wire masters. +class DS2482_DS2484 : public Core::OneWireMaster { +public: + enum ErrorValue { HardwareError = 1, ArgumentOutOfRangeError }; + + /// Represents a device configuration. + class Config { + public: + /// Default construct with power-on config. + explicit Config(uint_least8_t readByte = optionAPU) + : readByte_(readByte & 0xF) {} + + /// @name 1WS + /// @brief 1-Wire Speed + /// @{ + + /// Get 1WS bit. + bool get1WS() const { return (readByte_ & option1WS) == option1WS; } + + /// Set 1WS bit. + Config & set1WS(bool new1WS) { + if (new1WS) { + readByte_ |= option1WS; + } else { + readByte_ &= ~option1WS; + } + return *this; + } + + /// @} + + /// @name SPU + /// @brief Strong Pullup + /// @{ + + /// Get SPU bit. + bool getSPU() const { return (readByte_ & optionSPU) == optionSPU; } + + /// Set SPU bit. + Config & setSPU(bool newSPU) { + if (newSPU) { + readByte_ |= optionSPU; + } else { + readByte_ &= ~optionSPU; + } + return *this; + } + + /// @} + + /// @name PDN + /// @brief 1-Wire Power Down + /// @{ + + /// Get PDN bit. + bool getPDN() const { return (readByte_ & optionPDN) == optionPDN; } + + /// Set PDN bit. + Config & setPDN(bool newPDN) { + if (newPDN) { + readByte_ |= optionPDN; + } else { + readByte_ &= ~optionPDN; + } + return *this; + } + + /// @} + + /// @name APU + /// @brief Active Pullup + /// @{ + + /// Get APU bit. + bool getAPU() const { return (readByte_ & optionAPU) == optionAPU; } + + /// Set APU bit. + Config & setAPU(bool newAPU) { + if (newAPU) { + readByte_ |= optionAPU; + } else { + readByte_ &= ~optionAPU; + } + return *this; + } + + /// @} + + /// Byte representation that is read from the device. + uint_least8_t readByte() const { return readByte_; } + + private: + static const unsigned int option1WS = 0x8; + static const unsigned int optionSPU = 0x4; + static const unsigned int optionPDN = 0x2; + static const unsigned int optionAPU = 0x1; + + uint_least8_t readByte_; + }; + + void setMaster(Core::I2CMaster & master) { this->master = &master; } + + uint_least8_t address() const { return address_; } + + void setAddress(uint_least8_t address) { address_ = address; } + + /// Initialize hardware for use. + MaximInterfaceDevices_EXPORT Core::error_code + initialize(Config config = Config()); + + /// @brief Write a new configuration to the device. + /// @param[in] config New configuration to write. + MaximInterfaceDevices_EXPORT Core::error_code writeConfig(Config config); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + triplet(TripletData & data); + + MaximInterfaceDevices_EXPORT virtual Core::error_code reset(); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + touchBitSetLevel(bool & sendRecvBit, Level afterLevel); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + readByteSetLevel(uint_least8_t & recvByte, Level afterLevel); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + writeByteSetLevel(uint_least8_t sendByte, Level afterLevel); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + setSpeed(Speed newSpeed); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + setLevel(Level newLevel); + + MaximInterfaceDevices_EXPORT static const Core::error_category & + errorCategory(); + +protected: + DS2482_DS2484(Core::I2CMaster & master, uint_least8_t address) + : master(&master), address_(address) {} + + /// @note Allow marking const since not public. + Core::error_code sendCommand(uint_least8_t cmd) const; + + /// @note Allow marking const since not public. + Core::error_code sendCommand(uint_least8_t cmd, uint_least8_t param) const; + + /// @brief Reads a register from the device. + /// @param reg Register to read from. + /// @param[out] buf Buffer to hold read data. + Core::error_code readRegister(uint_least8_t reg, uint_least8_t & buf) const; + + /// @brief Reads the current register from the device. + /// @param[out] buf Buffer to hold read data. + Core::error_code readRegister(uint_least8_t & buf) const; + +private: + /// @brief Performs a soft reset on the device. + /// @note This is not a 1-Wire Reset. + Core::error_code resetDevice(); + + /// @brief + /// Polls the device status waiting for the 1-Wire Busy bit (1WB) to be cleared. + /// @param[out] pStatus Optionally retrieve the status byte when 1WB cleared. + /// @returns Success or TimeoutError if poll limit reached. + Core::error_code pollBusy(uint_least8_t * pStatus = NULL); + + /// @brief Ensure that the desired 1-Wire level is set in the configuration. + /// @param level Desired 1-Wire level. + Core::error_code configureLevel(Level level); + + Core::I2CMaster * master; + uint_least8_t address_; + Config curConfig; +}; + +inline Core::error_code make_error_code(DS2482_DS2484::ErrorValue e) { + return Core::error_code(e, DS2482_DS2484::errorCategory()); +} + +class DS2482_100 : public DS2482_DS2484 { +public: + DS2482_100(Core::I2CMaster & i2c_bus, uint_least8_t adrs) + : DS2482_DS2484(i2c_bus, adrs) {} +}; + +/// DS2482-800 I2C to 1-Wire Master +class DS2482_800 : public DS2482_DS2484 { +public: + DS2482_800(Core::I2CMaster & i2c_bus, uint_least8_t adrs) + : DS2482_DS2484(i2c_bus, adrs) {} + + /// @brief Select the active 1-Wire channel. + /// @param channel Channel number to select from 0 to 7. + MaximInterfaceDevices_EXPORT Core::error_code selectChannel(int channel); +}; + +/// DS2484 I2C to 1-Wire Master +class DS2484 : public DS2482_DS2484 { +public: + /// @brief 1-Wire port adjustment parameters. + /// @note See datasheet page 13. + enum PortParameter { + tRSTL = 0, + tRSTL_OD, + tMSP, + tMSP_OD, + tW0L, + tW0L_OD, + tREC0, // OD N/A + RWPU = 8 // OD N/A + }; + + explicit DS2484(Core::I2CMaster & i2c_bus, uint_least8_t adrs = 0x30) + : DS2482_DS2484(i2c_bus, adrs) {} + + /// @brief Adjust 1-Wire port parameters. + /// @param param Parameter to adjust. + /// @param val New parameter value to set. Consult datasheet for value mappings. + MaximInterfaceDevices_EXPORT Core::error_code adjustPort(PortParameter param, + int val); +}; + +} // namespace MaximInterfaceDevices + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS28C36_DS2476.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,725 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include <algorithm> +#include <MaximInterfaceCore/Error.hpp> +#include <MaximInterfaceCore/I2CMaster.hpp> +#include <MaximInterfaceCore/RomId.hpp> +#include "DS28C36_DS2476.hpp" + +namespace MaximInterfaceDevices { + +using namespace Core; +using namespace Ecc256; +using std::copy; + +static error_code convertResultByte(uint_least8_t resultByte) { + error_code errorCode; + if (resultByte != 0xAA) { + errorCode.assign((resultByte == 0x00) + ? static_cast<int>(DS28C36::AuthenticationError) + : resultByte, + DS28C36::errorCategory()); + } + return errorCode; +} + +const int DS28C36::publicKeyAxPage; +const int DS28C36::publicKeyAyPage; +const int DS28C36::publicKeyBxPage; +const int DS28C36::publicKeyByPage; +const int DS28C36::publicKeyCxPage; +const int DS28C36::publicKeyCyPage; +const int DS28C36::privateKeyAPage; +const int DS28C36::privateKeyBPage; +const int DS28C36::privateKeyCPage; +const int DS28C36::secretAPage; +const int DS28C36::secretBPage; +const int DS28C36::decrementCounterPage; +const int DS28C36::romOptionsPage; +const int DS28C36::gpioControlPage; +const int DS28C36::publicKeySxPage; +const int DS28C36::publicKeySyPage; +const int DS28C36::memoryPages; + +error_code DS28C36::writeMemory(int pageNum, Page::const_span page) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t buffer[1 + Page::size]; + buffer[0] = pageNum; + copy(page.begin(), page.end(), buffer + 1); + error_code result = writeCommand(0x96, buffer); + if (!result) { + sleep(writeMemoryTimeMs); + result = readFixedLengthResponse(make_span(buffer, 1)); + if (!result) { + result = convertResultByte(buffer[0]); + } + } + return result; +} + +error_code DS28C36::readMemory(int pageNum, Page::span page) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + const uint_least8_t parameter = pageNum; + error_code result = writeCommand(0x69, make_span(¶meter, 1)); + if (!result) { + sleep(readMemoryTimeMs); + array<uint_least8_t, 1 + Page::size> response; + result = readFixedLengthResponse(response); + if (!result) { + result = convertResultByte(response[0]); + copy(response.begin() + 1, response.end(), page.begin()); + } + } + return result; +} + +error_code DS28C36::writeBuffer(span<const uint_least8_t> data) { + return writeCommand(0x87, data); +} + +error_code DS28C36::readBuffer(std::vector<uint_least8_t> & data) { + error_code result = writeCommand(0x5A); + if (!result) { + data.resize(80); + span<uint_least8_t> dataSpan(data); + result = readVariableLengthResponse(dataSpan); + if (result) { + data.clear(); + } else { + data.resize(dataSpan.size()); + } + } + return result; +} + +error_code DS28C36::readPageProtection(int pageNum, + PageProtection & protection) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t buffer = pageNum; + error_code result = writeCommand(0xAA, make_span(&buffer, 1)); + if (!result) { + sleep(readMemoryTimeMs); + result = readFixedLengthResponse(make_span(&buffer, 1)); + if (!result) { + protection = buffer; + } + } + return result; +} + +error_code DS28C36::setPageProtection(int pageNum, + const PageProtection & protection) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t buffer[] = {static_cast<uint_least8_t>(pageNum), + static_cast<uint_least8_t>(protection.to_ulong())}; + error_code result = writeCommand(0xC3, buffer); + if (!result) { + sleep(writeMemoryTimeMs); + result = readFixedLengthResponse(make_span(buffer, 1)); + if (!result) { + result = convertResultByte(buffer[0]); + } + } + return result; +} + +error_code DS28C36::decrementCounter() { + error_code result = writeCommand(0xC9); + if (!result) { + sleep(writeMemoryTimeMs); + uint_least8_t response; + result = readFixedLengthResponse(make_span(&response, 1)); + if (!result) { + result = convertResultByte(response); + } + } + return result; +} + +error_code DS28C36::readRng(span<uint_least8_t> data) { + if ((data.size() < 1) || (data.size() > 64)) { + return make_error_code(InvalidParameterError); + } + + data[0] = static_cast<uint_least8_t>(data.size() - 1); + error_code result = writeCommand(0xD2, data.first(1)); + if (!result) { + sleep(sha256ComputationTimeMs); + result = readFixedLengthResponse(data); + } + return result; +} + +error_code DS28C36::encryptedReadMemory(int pageNum, SecretNum secretNum, + EncryptionChallenge::span challenge, + Page::span data) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + const uint_least8_t parameter = (secretNum << 6) | pageNum; + error_code result = writeCommand(0x4B, make_span(¶meter, 1)); + if (!result) { + sleep(readMemoryTimeMs + sha256ComputationTimeMs); + uint_least8_t response[1 + EncryptionChallenge::size + Page::size]; + result = readFixedLengthResponse(response); + if (!result) { + result = convertResultByte(response[0]); + const uint_least8_t * begin = response + 1; + const uint_least8_t * end = begin + challenge.size(); + copy(begin, end, challenge.begin()); + begin = end; + end = begin + data.size(); + copy(begin, end, data.begin()); + } + } + return result; +} + +error_code DS28C36::computeAndReadPageAuthentication(int pageNum, + AuthType authType) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + const uint_least8_t parameter = (authType << 5) | pageNum; + return writeCommand(0xA5, make_span(¶meter, 1)); +} + +error_code +DS28C36::computeAndReadPageAuthentication(int pageNum, KeyNum keyNum, + Signature::span signature) { + AuthType authType; + switch (keyNum) { + case KeyNumA: + authType = EcdsaWithKeyA; + break; + case KeyNumB: + authType = EcdsaWithKeyB; + break; + case KeyNumC: + authType = EcdsaWithKeyC; + break; + default: + return make_error_code(InvalidParameterError); + } + error_code result = computeAndReadPageAuthentication(pageNum, authType); + if (!result) { + sleep(readMemoryTimeMs + generateEcdsaSignatureTimeMs); + uint_least8_t response[1 + 2 * Scalar::size]; + result = readFixedLengthResponse(response); + if (!result) { + result = convertResultByte(response[0]); + const uint_least8_t * begin = response + 1; + const uint_least8_t * end = begin + signature.s.size(); + copy(begin, end, signature.s.begin()); + begin = end; + end = begin + signature.r.size(); + copy(begin, end, signature.r.begin()); + } + } + return result; +} + +error_code DS28C36::computeAndReadPageAuthentication(int pageNum, + SecretNum secretNum, + Page::span hmac) { + AuthType authType; + switch (secretNum) { + case SecretNumA: + authType = HmacWithSecretA; + break; + case SecretNumB: + authType = HmacWithSecretB; + break; + case SecretNumS: + authType = HmacWithSecretS; + break; + default: + return make_error_code(InvalidParameterError); + } + error_code result = computeAndReadPageAuthentication(pageNum, authType); + if (!result) { + sleep(readMemoryTimeMs + sha256ComputationTimeMs); + array<uint_least8_t, 1 + Page::size> response; + result = readFixedLengthResponse(response); + if (!result) { + result = convertResultByte(response[0]); + copy(response.begin() + 1, response.end(), hmac.begin()); + } + } + return result; +} + +error_code DS28C36::authenticatedSha2WriteMemory(int pageNum, + SecretNum secretNum, + Page::const_span page) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t buffer[1 + Page::size]; + buffer[0] = (secretNum << 6) | pageNum; + copy(page.begin(), page.end(), buffer + 1); + error_code result = writeCommand(0x99, buffer); + if (!result) { + sleep(writeMemoryTimeMs + (2 * sha256ComputationTimeMs)); + result = readFixedLengthResponse(make_span(buffer, 1)); + if (!result) { + result = convertResultByte(buffer[0]); + } + } + return result; +} + +error_code DS28C36::computeAndLockSha2Secret(int pageNum, SecretNum msecretNum, + SecretNum dsecretNum, + bool writeProtectEnable) { + // User pages only + if (pageNum < 0 || pageNum > 15) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t buffer[] = { + static_cast<uint_least8_t>((dsecretNum << 6) | (msecretNum << 4) | + pageNum), + static_cast<uint_least8_t>(writeProtectEnable ? 0x80 : 0x00)}; + error_code result = writeCommand(0x3C, buffer); + if (!result) { + sleep(sha256ComputationTimeMs + + ((writeProtectEnable ? 2 : 1) * writeMemoryTimeMs)); + result = readFixedLengthResponse(make_span(buffer, 1)); + if (!result) { + result = convertResultByte(buffer[0]); + } + } + return result; +} + +error_code DS28C36::generateEcc256KeyPair(KeyNum keyNum, + bool writeProtectEnable) { + if (keyNum == KeyNumS) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t buffer = keyNum; + if (writeProtectEnable) { + buffer |= 0x80; + } + error_code result = writeCommand(0xCB, make_span(&buffer, 1)); + if (!result) { + sleep(generateEccKeyPairTimeMs); + result = readFixedLengthResponse(make_span(&buffer, 1)); + if (!result) { + result = convertResultByte(buffer); + } + } + return result; +} + +error_code DS28C36::computeMultiblockHash(bool firstBlock, bool lastBlock, + span<const uint_least8_t> data) { + const span<const uint_least8_t>::index_type maxDataSize = 64; + + if (data.size() < 1 || data.size() > maxDataSize) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t buffer[1 + maxDataSize]; + buffer[0] = 0; + if (firstBlock) { + buffer[0] |= 0x40; + } + if (lastBlock) { + buffer[0] |= 0x80; + } + copy(data.begin(), data.end(), buffer + 1); + error_code result = writeCommand(0x33, make_span(buffer, data.size() + 1)); + if (!result) { + sleep(sha256ComputationTimeMs); + result = readFixedLengthResponse(make_span(buffer, 1)); + if (!result) { + result = convertResultByte(buffer[0]); + } + } + return result; +} + +error_code DS28C36::verifyEcdsaSignature(KeyNum keyNum, HashType hashType, + Signature::const_span signature, + PioState pioa, PioState piob) { + uint_least8_t buffer[1 + 2 * Scalar::size]; + buffer[0] = keyNum | (hashType << 2); + if (pioa != Unchanged) { + buffer[0] |= 0x20; + } + if (pioa == Conducting) { + buffer[0] |= 0x10; + } + if (piob != Unchanged) { + buffer[0] |= 0x80; + } + if (piob == Conducting) { + buffer[0] |= 0x40; + } + uint_least8_t * bufferIt = + copy(signature.r.begin(), signature.r.end(), buffer + 1); + copy(signature.s.begin(), signature.s.end(), bufferIt); + error_code result = writeCommand(0x59, buffer); + if (!result) { + sleep(verifyEsdsaSignatureOrComputeEcdhTimeMs + + ((hashType == DataInBuffer) ? sha256ComputationTimeMs : 0)); + result = readFixedLengthResponse(make_span(buffer, 1)); + if (!result) { + result = convertResultByte(buffer[0]); + } + } + return result; +} + +error_code +DS28C36::authenticateEcdsaPublicKey(bool authWrites, bool ecdh, KeyNum keyNum, + int csOffset, + Signature::const_span signature) { + if (((keyNum != KeyNumA) && (keyNum != KeyNumB)) || (csOffset < 0) || + (csOffset > 31)) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t buffer[1 + 2 * Scalar::size]; + buffer[0] = (csOffset << 3) | (keyNum << 2); + if (ecdh) { + buffer[0] |= 0x02; + } + if (authWrites) { + buffer[0] |= 0x01; + } + uint_least8_t * bufferIt = + copy(signature.r.begin(), signature.r.end(), buffer + 1); + copy(signature.s.begin(), signature.s.end(), bufferIt); + error_code result = writeCommand(0xA8, buffer); + if (!result) { + sleep((ecdh ? 2 : 1) * verifyEsdsaSignatureOrComputeEcdhTimeMs); + result = readFixedLengthResponse(make_span(buffer, 1)); + if (!result) { + result = convertResultByte(buffer[0]); + } + } + return result; +} + +error_code DS28C36::authenticatedEcdsaWriteMemory(int pageNum, + Page::const_span page) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t buffer[1 + Page::size]; + buffer[0] = pageNum; + copy(page.begin(), page.end(), buffer + 1); + error_code result = writeCommand(0x89, buffer); + if (!result) { + sleep(verifyEsdsaSignatureOrComputeEcdhTimeMs + writeMemoryTimeMs + + sha256ComputationTimeMs); + result = readFixedLengthResponse(make_span(buffer, 1)); + if (!result) { + result = convertResultByte(buffer[0]); + } + } + return result; +} + +error_code DS28C36::writeCommand(uint_least8_t command, + span<const uint_least8_t> parameters) { + error_code result = master->start(address_); + if (result) { + master->stop(); + return result; + } + result = master->writeByte(command); + if (result) { + master->stop(); + return result; + } + if (!parameters.empty()) { + result = master->writeByte(static_cast<uint_least8_t>(parameters.size())); + if (result) { + master->stop(); + return result; + } + result = master->writeBlock(parameters); + if (result) { + master->stop(); + return result; + } + } + result = master->stop(); + return result; +} + +error_code DS28C36::readVariableLengthResponse(span<uint_least8_t> & response) { + error_code result = master->start(address_ | 1); + if (result) { + master->stop(); + return result; + } + uint_least8_t length; + result = master->readByte(I2CMaster::Ack, length); + if (result) { + master->stop(); + return result; + } + if (length > response.size()) { + master->stop(); + return make_error_code(InvalidResponseError); + } + response = response.first(length); + if (!response.empty()) { + result = master->readBlock(I2CMaster::Nack, response); + if (result) { + master->stop(); + return result; + } + } + result = master->stop(); + return result; +} + +error_code DS28C36::readFixedLengthResponse(span<uint_least8_t> response) { + const span<uint_least8_t>::index_type requestedResponseSize = response.size(); + error_code result = readVariableLengthResponse(response); + if (!result && response.size() != requestedResponseSize) { + result = make_error_code(InvalidResponseError); + } + return result; +} + +const error_category & DS28C36::errorCategory() { + static class : public error_category { + public: + virtual const char * name() const { return "DS28C36"; } + + virtual std::string message(int condition) const { + switch (condition) { + case ProtectionError: + return "Protection Error"; + + case InvalidParameterError: + return "Invalid Parameter Error"; + + case InvalidSequenceError: + return "Invalid Sequence Error"; + + case InvalidEcdsaInputOrResultError: + return "Invalid ECDSA Input or Result Error"; + + case AuthenticationError: + return "Authentication Error"; + + case InvalidResponseError: + return "Invalid Response Error"; + + default: + return defaultErrorMessage(condition); + } + } + } instance; + return instance; +} + +error_code DS2476::generateEcdsaSignature(KeyNum keyNum, + Signature::span signature) { + if (keyNum == KeyNumS) { + return make_error_code(InvalidParameterError); + } + + const uint_least8_t parameter = keyNum; + error_code result = writeCommand(0x1E, make_span(¶meter, 1)); + if (!result) { + sleep(generateEcdsaSignatureTimeMs); + uint_least8_t response[1 + 2 * Scalar::size]; + result = readFixedLengthResponse(response); + if (!result) { + result = convertResultByte(response[0]); + const uint_least8_t * begin = response + 1; + const uint_least8_t * end = begin + signature.s.size(); + copy(begin, end, signature.s.begin()); + begin = end; + end = begin + signature.r.size(); + copy(begin, end, signature.r.begin()); + } + } + return result; +} + +error_code DS2476::computeSha2UniqueSecret(SecretNum msecretNum) { + uint_least8_t buffer = msecretNum << 4; + error_code result = writeCommand(0x55, make_span(&buffer, 1)); + if (!result) { + sleep(sha256ComputationTimeMs); + result = readFixedLengthResponse(make_span(&buffer, 1)); + if (!result) { + convertResultByte(buffer); + } + } + return result; +} + +error_code DS2476::computeSha2Hmac(Page::span hmac) { + error_code result = writeCommand(0x2D); + if (!result) { + sleep(sha256ComputationTimeMs); + array<uint_least8_t, 1 + Page::size> response; + result = readFixedLengthResponse(response); + if (!result) { + result = convertResultByte(response[0]); + copy(response.begin() + 1, response.end(), hmac.begin()); + } + } + return result; +} + +error_code computeMultiblockHash(DS28C36 & ds28c36, + span<const uint_least8_t> data) { + error_code result; + span<const uint_least8_t>::index_type dataIdx = 0; + while (dataIdx < data.size() && !result) { + const span<const uint_least8_t>::index_type remainingSize = + data.size() - dataIdx; + const span<const uint_least8_t>::index_type chunkSize = + std::min<span<const uint_least8_t>::index_type>(remainingSize, 64); + result = + ds28c36.computeMultiblockHash(dataIdx == 0, remainingSize == chunkSize, + data.subspan(dataIdx, chunkSize)); + dataIdx += chunkSize; + } + return result; +} + +error_code verifyEcdsaSignature(DS28C36 & ds28c36, DS28C36::KeyNum publicKey, + span<const uint_least8_t> data, + Signature::const_span signature, + DS28C36::PioState pioa, + DS28C36::PioState piob) { + error_code result = computeMultiblockHash(ds28c36, data); + if (!result) { + result = ds28c36.verifyEcdsaSignature(publicKey, DS28C36::THASH, signature, + pioa, piob); + } + return result; +} + +error_code verifyEcdsaSignature(DS28C36 & ds28c36, + PublicKey::const_span publicKey, + span<const uint_least8_t> data, + Signature::const_span signature, + DS28C36::PioState pioa, + DS28C36::PioState piob) { + error_code result = + ds28c36.writeMemory(DS28C36::publicKeySxPage, publicKey.x); + if (!result) { + result = ds28c36.writeMemory(DS28C36::publicKeySyPage, publicKey.y); + } + if (!result) { + result = verifyEcdsaSignature(ds28c36, DS28C36::KeyNumS, data, signature, + pioa, piob); + } + return result; +} + +error_code readRomIdAndManId(DS28C36 & ds28c36, RomId::span romId, + ManId::span manId) { + DS28C36::Page::array page; + error_code result = ds28c36.readMemory(DS28C36::romOptionsPage, page); + if (!result) { + const DS28C36::RomOptions romOptions(page); + copy(romOptions.romId(), romId); + copy(romOptions.manId(), manId); + } + return result; +} + +error_code enableCoprocessor(DS2476 & ds2476) { + DS2476::Page::array page; + error_code result = ds2476.readMemory(DS2476::gpioControlPage, page); + if (!result) { + DS2476::GpioControl gpioControl(page); + if (!gpioControl.pioaConducting()) { + gpioControl.setPioaConducting(true); + result = ds2476.writeMemory(DS2476::gpioControlPage, page); + } + } + return result; +} + +error_code enableRomId(DS2476 & ds2476) { + DS2476::Page::array page; + error_code result = ds2476.readMemory(DS2476::romOptionsPage, page); + if (!result) { + DS2476::RomOptions romOptions(page); + if (!romOptions.romBlockDisable()) { + romOptions.setRomBlockDisable(true); + result = ds2476.writeMemory(DS2476::romOptionsPage, page); + } + } + return result; +} + +static void setAnonymous(RomId::span romId) { + std::fill(romId.begin(), romId.end(), 0xFF); +} + +DS28C36::PageAuthenticationData & +DS28C36::PageAuthenticationData::setAnonymousRomId() { + setAnonymous(romId()); + return *this; +} + +DS28C36::EncryptionHmacData & DS28C36::EncryptionHmacData::setAnonymousRomId() { + setAnonymous(romId()); + return *this; +} + +} // namespace MaximInterfaceDevices
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS28C36_DS2476.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,944 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceDevices_DS28C36_DS2476 +#define MaximInterfaceDevices_DS28C36_DS2476 + +#include <stdint.h> +#include <vector> +#include <MaximInterfaceCore/Algorithm.hpp> +#include <MaximInterfaceCore/array_span.hpp> +#include <MaximInterfaceCore/Ecc256.hpp> +#include <MaximInterfaceCore/FlagSet.hpp> +#include <MaximInterfaceCore/I2CMaster.hpp> +#include <MaximInterfaceCore/ManId.hpp> +#include <MaximInterfaceCore/RomId.hpp> +#include <MaximInterfaceCore/Sleep.hpp> +#include <MaximInterfaceCore/system_error.hpp> +#include "Config.hpp" + +namespace MaximInterfaceDevices { + +/// Interface to the DS28C36 authenticator. +class DS28C36 { +public: + /// Device command results. + enum ErrorValue { + ProtectionError = 0x55, + InvalidParameterError = 0x77, + InvalidSequenceError = 0x33, + InvalidEcdsaInputOrResultError = 0x22, + AuthenticationError = 0x100, + InvalidResponseError = 0x101 ///< Response does not match expected format. + }; + + /// @name Device memory pages + /// @{ + + static const int publicKeyAxPage = 16; + static const int publicKeyAyPage = 17; + static const int publicKeyBxPage = 18; + static const int publicKeyByPage = 19; + static const int publicKeyCxPage = 20; + static const int publicKeyCyPage = 21; + static const int privateKeyAPage = 22; + static const int privateKeyBPage = 23; + static const int privateKeyCPage = 24; + static const int secretAPage = 25; + static const int secretBPage = 26; + static const int decrementCounterPage = 27; + static const int romOptionsPage = 28; + static const int gpioControlPage = 29; + static const int publicKeySxPage = 30; + static const int publicKeySyPage = 31; + + /// @} + + /// Number of memory pages on the device. + static const int memoryPages = 32; + + /// Available keys for ECDSA operations. + enum KeyNum { KeyNumA = 0, KeyNumB = 1, KeyNumC = 2, KeyNumS = 3 }; + + /// Available secrets for HMAC operations. + enum SecretNum { SecretNumA = 0, SecretNumB = 1, SecretNumS = 2 }; + + /// Data hash type when verifying an ECDSA signature. + enum HashType { + HashInBuffer = 0, ///< Hash is loaded in the buffer. + DataInBuffer = 1, ///< Compute hash from data loaded in the buffer. + THASH = 2 ///< Use THASH from Compute Multiblock Hash command. + }; + + /// Available PIO states when verifying an ECDSA signature. + enum PioState { Unchanged, Conducting, HighImpedance }; + + /// Holds a device memory page. + typedef Core::array_span<uint_least8_t, 32> Page; + + // Format page authentication input data. + class PageAuthenticationData; + + // Format authenticated write input data. + class WriteAuthenticationData; + + // Format compute secret input data. + class ComputeSecretData; + + // Format encryption or decryption HMAC input data. + class EncryptionHmacData; + + // Access fields in the ROM Options page. + class RomOptions; + + // Access fields in the GPIO Control page. + class GpioControl; + + /// Page protection types. + enum PageProtectionType { + RP = 0x01, ///< Read protection. + WP = 0x02, ///< Write protection. + EM = 0x04, ///< EPROM emulation mode. + APH = 0x08, ///< Authentication write protection HMAC. + EPH = 0x10, ///< Encryption and authenticated write protection HMAC. + AUTH = 0x20, ///< Public Key C is set to authority public key. + ECH = 0x40, ///< Encrypted read and write using shared key from ECDH. + ECW = 0x80 ///< Authentication write protection ECDSA. + }; + typedef Core::FlagSet<PageProtectionType, 8> PageProtection; + + /// Challenge for an encrypted device memory page. + typedef Core::array_span<uint_least8_t, 8> EncryptionChallenge; + + DS28C36(Core::Sleep & sleep, Core::I2CMaster & master, + uint_least8_t address = 0x36) + : sleep_(&sleep), master(&master), address_(address & 0xFE) {} + + void setSleep(Core::Sleep & sleep) { sleep_ = &sleep; } + + void setMaster(Core::I2CMaster & master) { this->master = &master; } + + uint_least8_t address() const { return address_; } + + void setAddress(uint_least8_t address) { address_ = address & 0xFE; } + + /// @brief Write memory with no protection. + /// @param pageNum Number of page to write. + /// @param page Data to write. + MaximInterfaceDevices_EXPORT Core::error_code + writeMemory(int pageNum, Page::const_span page); + + /// @brief Read memory with no protection. + /// @param pageNum Number of page to read. + /// @param[out] page Data that was read. + MaximInterfaceDevices_EXPORT Core::error_code readMemory(int pageNum, + Page::span page); + + /// @brief Write the temporary buffer. + /// @param data Data to write. + MaximInterfaceDevices_EXPORT Core::error_code + writeBuffer(Core::span<const uint_least8_t> data); + + /// @brief Read the temporary buffer. + /// @param[out] data Data that was read. + MaximInterfaceDevices_EXPORT Core::error_code + readBuffer(std::vector<uint_least8_t> & data); + + /// @brief Read the protection settings of a page. + /// @param pageNum Number of page to read. + /// @param[out] protection Protection that was read. + MaximInterfaceDevices_EXPORT Core::error_code + readPageProtection(int pageNum, PageProtection & protection); + + /// @brief Set the protection settings of a page. + /// @param pageNum Number of page to write. + /// @param protection Protection to write. + MaximInterfaceDevices_EXPORT Core::error_code + setPageProtection(int pageNum, const PageProtection & protection); + + /// Decrement the decrement-only counter. + MaximInterfaceDevices_EXPORT Core::error_code decrementCounter(); + + /// @brief Read a block of random data from the RNG. + /// @param[out] data Random data from RNG with length from 1 to 64. + MaximInterfaceDevices_EXPORT Core::error_code + readRng(Core::span<uint_least8_t> data); + + /// @brief Read memory with encryption. + /// @param pageNum Number of page to read from. + /// @param secretNum Secret to use for encryption. + /// @param[out] challenge Encryption challenge that was read. + /// @param[out] data Encrypted page data that was read. + MaximInterfaceDevices_EXPORT Core::error_code + encryptedReadMemory(int pageNum, SecretNum secretNum, + EncryptionChallenge::span challenge, Page::span data); + + /// @brief Compute and read page authentication with ECDSA. + /// @param pageNum Number of page to authenticate. + /// @param keyNum + /// Private key to use for authentication. + /// Key S cannot be used with this command. + /// @param[out] signature Computed page signature. + MaximInterfaceDevices_EXPORT Core::error_code + computeAndReadPageAuthentication(int pageNum, KeyNum keyNum, + Core::Ecc256::Signature::span signature); + + /// @brief Compute and read page authentication with HMAC. + /// @param pageNum Number of page to authenticate. + /// @param secretNum Secret to use for authentication. + /// @param[out] hmac Computed page HMAC. + MaximInterfaceDevices_EXPORT Core::error_code + computeAndReadPageAuthentication(int pageNum, SecretNum secretNum, + Page::span hmac); + + /// @brief Write with SHA2 authentication. + /// @param pageNum Number of page to write. + /// @param secretNum Secret to use for authentication. + /// @param page Data to write. + MaximInterfaceDevices_EXPORT Core::error_code + authenticatedSha2WriteMemory(int pageNum, SecretNum secretNum, + Page::const_span page); + + /// @brief Compute SHA2 secret and optionally lock. + /// @param pageNum Number of page to use in computation. + /// @param msecretNum Master secret to use in computation. + /// @param dsecretNum Destination secret to receive the computation result. + /// @param writeProtectEnable + /// True to lock the destination secret against further writes. + MaximInterfaceDevices_EXPORT Core::error_code + computeAndLockSha2Secret(int pageNum, SecretNum msecretNum, + SecretNum dsecretNum, bool writeProtectEnable); + + /// @brief Generate a new ECDSA key pair. + /// @param keyNum Key to generate. Key S cannot be used with this command. + /// @param writeProtectEnable True to lock the key against further writes. + MaximInterfaceDevices_EXPORT Core::error_code + generateEcc256KeyPair(KeyNum keyNum, bool writeProtectEnable); + + /// @brief Compute a hash over multiple blocks. + /// @param firstBlock True if this is the first block being hashed. + /// @param lastBlock True if this is the last block being hashed. + /// @param data + /// Data block to hash. Should be 64 bytes unless this is the last block. + MaximInterfaceDevices_EXPORT Core::error_code + computeMultiblockHash(bool firstBlock, bool lastBlock, + Core::span<const uint_least8_t> data); + + /// @brief Verify ECDSA signature. + /// @param keyNum Public key to use for verification. + /// @param hashType Source of the data hash input. + /// @param signature Signature to verify. + /// @param pioa New state of PIOA if verification successful. + /// @param piob New state of PIOB if verification successful. + MaximInterfaceDevices_EXPORT Core::error_code + verifyEcdsaSignature(KeyNum keyNum, HashType hashType, + Core::Ecc256::Signature::const_span signature, + PioState pioa = Unchanged, PioState piob = Unchanged); + + /// @brief + /// Authenticate a public key for authenticated writes or encrypted reads + /// with ECDH. + /// @param authWrites True to select authentication for writes. + /// @param ecdh True to select ECDH key exchange. + /// @param keyNum + /// Private key to use for ECDH key exchange. Key A or B can be selected. + /// @param csOffset Certificate customization field ending offset in buffer. + /// @param signature Signature to use for authentication of public key S. + MaximInterfaceDevices_EXPORT Core::error_code + authenticateEcdsaPublicKey(bool authWrites, bool ecdh, KeyNum keyNum, + int csOffset, + Core::Ecc256::Signature::const_span signature); + + /// @brief Write with ECDSA authentication. + /// @param pageNum Number of page to write. + /// @param page Data to write. + MaximInterfaceDevices_EXPORT Core::error_code + authenticatedEcdsaWriteMemory(int pageNum, Page::const_span page); + + MaximInterfaceDevices_EXPORT static const Core::error_category & + errorCategory(); + +protected: + // Timing constants. + static const int generateEcdsaSignatureTimeMs = 50; + static const int generateEccKeyPairTimeMs = 100; + static const int verifyEsdsaSignatureOrComputeEcdhTimeMs = 150; + static const int sha256ComputationTimeMs = 3; + static const int readMemoryTimeMs = /*1*/ 2; + static const int writeMemoryTimeMs = 15; + + Core::error_code writeCommand(uint_least8_t command, + Core::span<const uint_least8_t> parameters); + + Core::error_code writeCommand(uint_least8_t command) { + return writeCommand(command, Core::span<const uint_least8_t>()); + } + + Core::error_code + readVariableLengthResponse(Core::span<uint_least8_t> & response); + + Core::error_code readFixedLengthResponse(Core::span<uint_least8_t> response); + + void sleep(int ms) const { sleep_->invoke(ms); } + +private: + enum AuthType { + HmacWithSecretA = 0, + HmacWithSecretB = 1, + HmacWithSecretS = 2, + EcdsaWithKeyA = 3, + EcdsaWithKeyB = 4, + EcdsaWithKeyC = 5 + }; + + const Core::Sleep * sleep_; + Core::I2CMaster * master; + uint_least8_t address_; + + Core::error_code computeAndReadPageAuthentication(int pageNum, + AuthType authType); +}; + +/// Interface to the DS2476 coprocessor. +class DS2476 : public DS28C36 { +public: + DS2476(Core::Sleep & sleep, Core::I2CMaster & master, + uint_least8_t address = 0x76) + : DS28C36(sleep, master, address) {} + + /// @brief Generate ECDSA signature. + /// @param keyNum + /// Private key to use to create signature. + /// Key S cannot be used with this command. + /// @param[out] signature Computed signature. + MaximInterfaceDevices_EXPORT Core::error_code + generateEcdsaSignature(KeyNum keyNum, + Core::Ecc256::Signature::span signature); + + /// @brief Compute unique SHA2 secret. + /// @param msecretNum Master secret to use in computation. + MaximInterfaceDevices_EXPORT Core::error_code + computeSha2UniqueSecret(SecretNum msecretNum); + + /// @brief Compute SHA2 HMAC. + /// @param[out] hmac Computed HMAC. + MaximInterfaceDevices_EXPORT Core::error_code + computeSha2Hmac(Page::span hmac); +}; + +inline Core::error_code make_error_code(DS28C36::ErrorValue e) { + return Core::error_code(e, DS28C36::errorCategory()); +} + +/// @brief +/// Hash arbitrary length data with successive Compute Multiblock Hash commands. +/// @param ds28c36 Device for computation. +/// @param data Data to hash. +MaximInterfaceDevices_EXPORT Core::error_code +computeMultiblockHash(DS28C36 & ds28c36, Core::span<const uint_least8_t> data); + +/// @brief Verify ECDSA signature. +/// @param ds28c36 Device for computation. +/// @param publicKey Public key to use for verification. +/// @param data Data to verify. +/// @param signature Signature to verify. +/// @param pioa New state of PIOA if verification successful. +/// @param piob New state of PIOB if verification successful. +MaximInterfaceDevices_EXPORT Core::error_code +verifyEcdsaSignature(DS28C36 & ds28c36, DS28C36::KeyNum publicKey, + Core::span<const uint_least8_t> data, + Core::Ecc256::Signature::const_span signature, + DS28C36::PioState pioa = DS28C36::Unchanged, + DS28C36::PioState piob = DS28C36::Unchanged); + +/// @brief Verify ECDSA signature. +/// @param ds28c36 Device for computation. +/// @param publicKey +/// Public key to use for verification which is loaded into Public Key S. +/// @param data Data to verify. +/// @param signature Signature to verify. +/// @param pioa New state of PIOA if verification successful. +/// @param piob New state of PIOB if verification successful. +MaximInterfaceDevices_EXPORT Core::error_code +verifyEcdsaSignature(DS28C36 & ds28c36, + Core::Ecc256::PublicKey::const_span publicKey, + Core::span<const uint_least8_t> data, + Core::Ecc256::Signature::const_span signature, + DS28C36::PioState pioa = DS28C36::Unchanged, + DS28C36::PioState piob = DS28C36::Unchanged); + +/// @brief +/// Read the device ROM ID and MAN ID using the Read Memory command on the +/// ROM Options page. +/// @param ds28c36 Device to read. +/// @param[out] romId Read ROM ID valid when operation is successful. +/// @param[out] manId Read MAN ID valid when operation is successful. +MaximInterfaceDevices_EXPORT Core::error_code +readRomIdAndManId(DS28C36 & ds28c36, Core::RomId::span romId, + Core::ManId::span manId); + +/// @brief +/// Enable coprocessor functionality on the DS2476 by writing to the +/// GPIO Control page. +MaximInterfaceDevices_EXPORT Core::error_code +enableCoprocessor(DS2476 & ds2476); + +/// @brief +/// Disable blocking of the ROM ID on the DS2476 by writing to the +/// ROM Options page. +MaximInterfaceDevices_EXPORT Core::error_code enableRomId(DS2476 & ds2476); + +/// Format page authentication input data. +class DS28C36::PageAuthenticationData { +public: + typedef Core::array_span<uint_least8_t, Core::RomId::size + 2 * Page::size + + 1 + Core::ManId::size> + Result; + + PageAuthenticationData() : result_() {} + + /// Formatted data result. + Result::const_span result() const { return result_; } + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { + return make_span(result_).subspan<romIdIdx, Core::RomId::size>(); + } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { + return const_cast<PageAuthenticationData &>(*this).romId(); + } + + /// Set ROM ID. + PageAuthenticationData & setRomId(Core::RomId::const_span romId) { + copy(romId, this->romId()); + return *this; + } + + /// Set ROM ID for use in anonymous mode. + MaximInterfaceDevices_EXPORT PageAuthenticationData & setAnonymousRomId(); + + /// @} + + /// @name Page + /// @brief Data from a device memory page. + /// @{ + + /// Get mutable page. + Page::span page() { + return make_span(result_).subspan<pageIdx, Page::size>(); + } + + /// Get immutable page. + Page::const_span page() const { + return const_cast<PageAuthenticationData &>(*this).page(); + } + + /// Set page. + PageAuthenticationData & setPage(Page::const_span page) { + copy(page, this->page()); + return *this; + } + + /// @} + + /// @name Challenge + /// @brief Random challenge used to prevent replay attacks. + /// @{ + + /// Get mutable Challenge. + Page::span challenge() { + return make_span(result_).subspan<challengeIdx, Page::size>(); + } + + /// Get immutable Challenge. + Page::const_span challenge() const { + return const_cast<PageAuthenticationData &>(*this).challenge(); + } + + /// Set Challenge. + PageAuthenticationData & setChallenge(Page::const_span challenge) { + copy(challenge, this->challenge()); + return *this; + } + + /// @} + + /// @name Page number + /// @brief Number of the page to use data from. + /// @{ + + /// Get page number. + int pageNum() const { return result_[pageNumIdx]; } + + /// Set page number. + PageAuthenticationData & setPageNum(int pageNum) { + result_[pageNumIdx] = pageNum; + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get mutable MAN ID. + Core::ManId::span manId() { + return make_span(result_).subspan<manIdIdx, Core::ManId::size>(); + } + + /// Get immutable MAN ID. + Core::ManId::const_span manId() const { + return const_cast<PageAuthenticationData &>(*this).manId(); + } + + /// Set MAN ID. + PageAuthenticationData & setManId(Core::ManId::const_span manId) { + copy(manId, this->manId()); + return *this; + } + + /// @} + +private: + typedef Result::span::index_type index; + + static const index romIdIdx = 0; + static const index pageIdx = romIdIdx + Core::RomId::size; + static const index challengeIdx = pageIdx + Page::size; + static const index pageNumIdx = challengeIdx + Page::size; + static const index manIdIdx = pageNumIdx + 1; + + Result::array result_; +}; + +/// Format authenticated write input data. +class DS28C36::WriteAuthenticationData { +public: + typedef PageAuthenticationData::Result Result; + + WriteAuthenticationData() : data() {} + + /// Formatted data result. + Result::const_span result() const { return data.result(); } + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { return data.romId(); } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { return data.romId(); } + + /// Set ROM ID. + WriteAuthenticationData & setRomId(Core::RomId::const_span romId) { + data.setRomId(romId); + return *this; + } + + /// Set ROM ID for use in anonymous mode. + WriteAuthenticationData & setAnonymousRomId() { + data.setAnonymousRomId(); + return *this; + } + + /// @} + + /// @name Old page + /// @brief Existing data contained in the page. + /// @{ + + /// Get mutable old page. + Page::span oldPage() { return data.page(); } + + /// Get immutable old page. + Page::const_span oldPage() const { return data.page(); } + + /// Set old page. + WriteAuthenticationData & setOldPage(Page::const_span oldPage) { + data.setPage(oldPage); + return *this; + } + + /// @} + + /// @name New page + /// @brief New data to write to the page. + /// @{ + + /// Get mutable new page. + Page::span newPage() { return data.challenge(); } + + /// Get immutable new page. + Page::const_span newPage() const { return data.challenge(); } + + /// Set new page. + WriteAuthenticationData & setNewPage(Page::const_span newPage) { + data.setChallenge(newPage); + return *this; + } + + /// @} + + /// @name Page number + /// @brief Page number for write operation. + /// @{ + + /// Get page number. + int pageNum() const { return data.pageNum(); } + + /// Set page number. + WriteAuthenticationData & setPageNum(int pageNum) { + data.setPageNum(pageNum); + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get mutable MAN ID. + Core::ManId::span manId() { return data.manId(); } + + /// Get immutable MAN ID. + Core::ManId::const_span manId() const { return data.manId(); } + + /// Set MAN ID. + WriteAuthenticationData & setManId(Core::ManId::const_span manId) { + data.setManId(manId); + return *this; + } + + /// @} + +private: + PageAuthenticationData data; +}; + +/// Format compute secret input data. +class DS28C36::ComputeSecretData { +public: + typedef PageAuthenticationData::Result Result; + + ComputeSecretData() : data() {} + + /// Formatted data result. + Result::const_span result() const { return data.result(); } + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { return data.romId(); } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { return data.romId(); } + + /// Set ROM ID. + ComputeSecretData & setRomId(Core::RomId::const_span romId) { + data.setRomId(romId); + return *this; + } + + /// @} + + /// @name Binding Data + /// @brief Binding Data contained in the selected page. + /// @{ + + /// Get mutable Binding Data. + Page::span bindingData() { return data.page(); } + + /// Get immutable Binding Data. + Page::const_span bindingData() const { return data.page(); } + + /// Set Binding Data. + ComputeSecretData & setBindingData(Page::const_span bindingData) { + data.setPage(bindingData); + return *this; + } + + /// @} + + /// @name Partial Secret + /// @brief Partial Secret used for customization. + /// @{ + + /// Get mutable Partial Secret. + Page::span partialSecret() { return data.challenge(); } + + /// Get immutable Partial Secret. + Page::const_span partialSecret() const { return data.challenge(); } + + /// Set Partial Secret. + ComputeSecretData & setPartialSecret(Page::const_span partialSecret) { + data.setChallenge(partialSecret); + return *this; + } + + /// @} + + /// @name Page number + /// @brief Page number for Binding Data. + /// @{ + + /// Get page number. + int pageNum() const { return data.pageNum(); } + + /// Set page number. + ComputeSecretData & setPageNum(int pageNum) { + data.setPageNum(pageNum); + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get mutable MAN ID. + Core::ManId::span manId() { return data.manId(); } + + /// Get immutable MAN ID. + Core::ManId::const_span manId() const { return data.manId(); } + + /// Set MAN ID. + ComputeSecretData & setManId(Core::ManId::const_span manId) { + data.setManId(manId); + return *this; + } + + /// @} + +private: + PageAuthenticationData data; +}; + +/// Format encryption or decryption HMAC input data. +class DS28C36::EncryptionHmacData { +public: + typedef Core::array_span<uint_least8_t, EncryptionChallenge::size + + Core::RomId::size + 1 + + Core::ManId::size> + Result; + + EncryptionHmacData() : result_() {} + + /// Formatted data result. + Result::const_span result() const { return result_; } + + /// @name Encryption Challenge + /// @brief Random challenge used to prevent replay attacks. + /// @{ + + /// Get mutable Encryption Challenge. + EncryptionChallenge::span encryptionChallenge() { + return make_span(result_) + .subspan<encryptionChallengeIdx, EncryptionChallenge::size>(); + } + + /// Get immutable Encryption Challenge. + EncryptionChallenge::const_span encryptionChallenge() const { + return const_cast<EncryptionHmacData &>(*this).encryptionChallenge(); + } + + /// Set Encryption Challenge. + EncryptionHmacData & + setEncryptionChallenge(EncryptionChallenge::const_span encryptionChallenge) { + copy(encryptionChallenge, this->encryptionChallenge()); + return *this; + } + + /// @} + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { + return make_span(result_).subspan<romIdIdx, Core::RomId::size>(); + } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { + return const_cast<EncryptionHmacData &>(*this).romId(); + } + + /// Set ROM ID. + EncryptionHmacData & setRomId(Core::RomId::const_span romId) { + copy(romId, this->romId()); + return *this; + } + + /// Set ROM ID for use in anonymous mode. + MaximInterfaceDevices_EXPORT EncryptionHmacData & setAnonymousRomId(); + + /// @} + + /// @name Page number + /// @brief Number of the page to use data from. + /// @{ + + /// Get page number. + int pageNum() const { return result_[pageNumIdx]; } + + /// Set page number. + EncryptionHmacData & setPageNum(int pageNum) { + result_[pageNumIdx] = pageNum; + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get mutable MAN ID. + Core::ManId::span manId() { + return make_span(result_).subspan<manIdIdx, Core::ManId::size>(); + } + + /// Get immutable MAN ID. + Core::ManId::const_span manId() const { + return const_cast<EncryptionHmacData &>(*this).manId(); + } + + /// Set MAN ID. + EncryptionHmacData & setManId(Core::ManId::const_span manId) { + copy(manId, this->manId()); + return *this; + } + + /// @} + +private: + typedef Result::span::index_type index; + + static const index encryptionChallengeIdx = 0; + static const index romIdIdx = + encryptionChallengeIdx + EncryptionChallenge::size; + static const index pageNumIdx = romIdIdx + Core::RomId::size; + static const index manIdIdx = pageNumIdx + 1; + + Result::array result_; +}; + +/// Access fields in the ROM Options page. +class DS28C36::RomOptions { +public: + explicit RomOptions(Page::span page) : page(page) {} + + bool romBlockDisable() const { + return page[romBlockDisableIdx] == enabledValue; + } + + RomOptions & setRomBlockDisable(bool romBlockDisable) { + page[romBlockDisableIdx] = (romBlockDisable ? enabledValue : 0); + return *this; + } + + bool anonymous() const { return page[anonymousIdx] == enabledValue; } + + RomOptions & setAnonymous(bool anonymous) { + page[anonymousIdx] = (anonymous ? enabledValue : 0); + return *this; + } + + Core::ManId::const_span manId() const { + return page.subspan<22, Core::ManId::size>(); + } + + Core::RomId::const_span romId() const { + return page.subspan<24, Core::RomId::size>(); + } + +private: + static const Page::span::index_type romBlockDisableIdx = 0; + static const Page::span::index_type anonymousIdx = 1; + static const Page::span::value_type enabledValue = 0xAA; + + Page::span page; +}; + +/// Access fields in the GPIO Control page. +class DS28C36::GpioControl { +public: + explicit GpioControl(Page::span page) : page(page) {} + + bool pioaConducting() const { + return page[pioaConductingIdx] == pioConductingValue; + } + + GpioControl & setPioaConducting(bool pioaConducting) { + page[pioaConductingIdx] = (pioaConducting ? pioConductingValue : 0x55); + return *this; + } + + bool piobConducting() const { + return page[piobConductingIdx] == pioConductingValue; + } + + GpioControl & setPiobConducting(bool piobConducting) { + page[piobConductingIdx] = (piobConducting ? pioConductingValue : 0x55); + return *this; + } + + bool pioaLevel() const { return page[2] == pioLevelValue; } + + bool piobLevel() const { return page[3] == pioLevelValue; } + +private: + static const Page::span::index_type pioaConductingIdx = 0; + static const Page::span::index_type piobConductingIdx = 1; + static const Page::span::value_type pioConductingValue = 0xAA; + static const Page::span::value_type pioLevelValue = 0x55; + + Page::span page; +}; + +} // namespace MaximInterfaceDevices + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS28C39.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,341 @@ +/******************************************************************************* +* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include <stddef.h> +#include <algorithm> +#include <MaximInterfaceCore/Error.hpp> +#include "DS28C39.hpp" + +namespace MaximInterfaceDevices { + +using namespace Core; +using std::copy; + +static const int readMemoryTimeMs = 30; +static const int writeMemoryTimeMs = 65; +static const int writeStateTimeMs = 15; +static const int generateEccKeyPairTimeMs = 200; +static const int generateEcdsaSignatureTimeMs = 130; +static const int trngOnDemandCheckTimeMs = 20; +static const int trngGenerationTimeMs = 10; +static const int verifyEcdsaSignatureTimeMs = 180; + +const int DS28C39::authorityPublicKeyXPage; +const int DS28C39::authorityPublicKeyYPage; +const int DS28C39::writePublicKeyXPage; +const int DS28C39::writePublicKeyYPage; +const int DS28C39::memoryPages; + +error_code DS28C39::writeMemory(int pageNum, Page::const_span page) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t request[2 + Page::size]; + request[0] = 0x96; + request[1] = pageNum; + copy(page.begin(), page.end(), request + 2); + return runCommand(request, writeMemoryTimeMs); +} + +error_code DS28C39::readMemory(int pageNum, Page::span page) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t buffer[1 + Page::size]; + buffer[0] = 0x44; + buffer[1] = pageNum; + span<uint_least8_t> response(buffer); + const error_code result = + runCommand(make_span(buffer, 2), readMemoryTimeMs, response); + if (!result) { + copy(response.begin(), response.end(), page.begin()); + } + return result; +} + +error_code DS28C39::readStatus(bool entropyHealthTest, Status & status) { + int delay = readMemoryTimeMs; + if (entropyHealthTest) { + delay += trngOnDemandCheckTimeMs; + } + uint_least8_t buffer[Status::PageProtectionList::csize + RomId::size + + ManId::size + Status::RomVersion::csize + 2]; + buffer[0] = 0xAA; + buffer[1] = entropyHealthTest ? 0x01 : 0x00; + span<uint_least8_t> response(buffer); + error_code result = runCommand(make_span(buffer, 2), delay, response); + if (!result) { + span<uint_least8_t>::const_iterator responseIt = response.begin(); + for (Status::PageProtectionList::iterator it = + status.pageProtection.begin(); + it != status.pageProtection.end(); ++it) { + *it = *responseIt; + ++responseIt; + } + span<uint_least8_t>::const_iterator responseItEnd = + responseIt + status.romId.size(); + copy(responseIt, responseItEnd, status.romId.begin()); + responseIt = responseItEnd; + responseItEnd = responseIt + status.manId.size(); + copy(responseIt, responseItEnd, status.manId.begin()); + responseIt = responseItEnd; + responseItEnd = responseIt + status.romVersion.size(); + copy(responseIt, responseItEnd, status.romVersion.begin()); + responseIt = responseItEnd; + switch (*responseIt) { + case Status::TestNotPerformed: + case Status::EntropyHealthy: + case Status::EntropyNotHealthy: + status.entropyHealthTestStatus = + static_cast<Status::EntropyHealthTestStatus>(*responseIt); + break; + + default: + result = make_error_code(InvalidResponseError); + break; + } + } + return result; +} + +error_code DS28C39::setPageProtection(int pageNum, + const PageProtection & protection) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + const uint_least8_t request[] = { + 0xC3, static_cast<uint_least8_t>(pageNum), + static_cast<uint_least8_t>(protection.to_ulong())}; + return runCommand(request, writeStateTimeMs); +} + +error_code +DS28C39::computeAndReadPageAuthentication(int pageNum, bool anonymous, + Page::const_span challenge, + Ecc256::Signature::span signature) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + const size_t requestSize = 2 + Page::size; + const size_t responseSize = 1 + 2 * Ecc256::Scalar::size; + uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)]; + buffer[0] = 0xA5; + buffer[1] = pageNum | (anonymous ? 0xE0 : 0x00); + copy(challenge.begin(), challenge.end(), buffer + 2); + span<uint_least8_t> response(buffer, responseSize); + const error_code result = runCommand(make_span(buffer, requestSize), + generateEcdsaSignatureTimeMs, response); + if (!result) { + span<uint_least8_t>::const_iterator begin = response.begin(); + span<uint_least8_t>::const_iterator end = begin + signature.s.size(); + copy(begin, end, signature.s.begin()); + begin = end; + end = begin + signature.r.size(); + copy(begin, end, signature.r.begin()); + } + return result; +} + +error_code DS28C39::disableDevice() { + const uint_least8_t request[] = {0x33, 0x9E, 0xA7, 0x49, 0xFB, + 0x10, 0x62, 0x0A, 0x26}; + return runCommand(request, writeStateTimeMs); +} + +error_code +DS28C39::readDevicePublicKey(Ecc256::PublicKey::span devicePublicKey) { + uint_least8_t buffer[1 + 2 * Ecc256::Scalar::size]; + buffer[0] = 0xCB; + span<uint_least8_t> response(buffer); + const error_code result = + runCommand(make_span(buffer, 1), generateEccKeyPairTimeMs, response); + if (!result) { + span<uint_least8_t>::const_iterator begin = response.begin(); + span<uint_least8_t>::const_iterator end = begin + devicePublicKey.x.size(); + copy(begin, end, devicePublicKey.x.begin()); + begin = end; + end = begin + devicePublicKey.y.size(); + copy(begin, end, devicePublicKey.y.begin()); + } + return result; +} + +error_code DS28C39::readRng(span<uint_least8_t> data) { + const span<uint_least8_t>::index_type maxDataSize = 64; + if ((data.size() < 1) || (data.size() > maxDataSize)) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t buffer[1 + maxDataSize]; + buffer[0] = 0xD2; + buffer[1] = static_cast<uint_least8_t>(data.size() - 1); + span<uint_least8_t> response(buffer, 1 + data.size()); + const error_code result = + runCommand(make_span(buffer, 2), trngGenerationTimeMs, response); + if (!result) { + copy(response.begin(), response.end(), data.begin()); + } + return result; +} + +error_code +DS28C39::authenticatePublicKey(Ecc256::Signature::const_span certificate, + span<const uint_least8_t> customization) { + static const span<const uint_least8_t>::index_type maxCustomizationSize = 32; + static const span<const uint_least8_t>::index_type signatureSize = + 2 * Ecc256::Scalar::size; + + if (customization.size() < 1 || customization.size() > maxCustomizationSize) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t request[1 + signatureSize + maxCustomizationSize]; + uint_least8_t * requestIt = request; + *requestIt++ = 0x59; + requestIt = copy(certificate.r.begin(), certificate.r.end(), requestIt); + requestIt = copy(certificate.s.begin(), certificate.s.end(), requestIt); + requestIt = copy(customization.begin(), customization.end(), requestIt); + return runCommand(make_span(request, requestIt), verifyEcdsaSignatureTimeMs); +} + +error_code +DS28C39::authenticatedWriteMemory(int pageNum, Page::const_span page, + Ecc256::Signature::const_span signature) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t request[2 + Page::size + 2 * Ecc256::Scalar::size]; + uint_least8_t * requestIt = request; + *requestIt++ = 0x89; + *requestIt++ = pageNum; + requestIt = copy(page.begin(), page.end(), requestIt); + requestIt = copy(signature.r.begin(), signature.r.end(), requestIt); + copy(signature.s.begin(), signature.s.end(), requestIt); + return runCommand(request, verifyEcdsaSignatureTimeMs + writeMemoryTimeMs); +} + +error_code DS28C39::runCommand(span<const uint_least8_t> request, int delayTime, + span<uint_least8_t> & response) { + const span<const uint_least8_t>::index_type responseInputSize = + response.size(); + error_code result = doRunCommand(request, delayTime, response); + if (result) { + return result; + } + if (response.empty()) { + return make_error_code(InvalidResponseError); + } + // Parse command result byte. + switch (response[0]) { + case 0xAA: + // Success response. + if (response.size() != responseInputSize) { + result = make_error_code(InvalidResponseError); + } + break; + + case 0x00: + result = make_error_code(AuthenticationError); + break; + + default: + result.assign(response[0], errorCategory()); + break; + } + response = response.subspan(1); + return result; +} + +error_code DS28C39::runCommand(span<const uint_least8_t> request, + int delayTime) { + uint_least8_t buffer; + span<uint_least8_t> response(&buffer, 1); + return runCommand(request, delayTime, response); +} + +const error_category & DS28C39::errorCategory() { + static class : public error_category { + public: + virtual const char * name() const { return "DS28C39"; } + + virtual std::string message(int condition) const { + switch (condition) { + case InvalidOperationError: + return "Invalid Operation Error"; + + case InvalidParameterError: + return "Invalid Parameter Error"; + + case InvalidSequenceError: + return "Invalid Sequence Error"; + + case InternalError: + return "Internal Error"; + + case DeviceDisabledError: + return "Device Disabled Error"; + + case AuthenticationError: + return "Authentication Error"; + + case InvalidResponseError: + return "Invalid Response Error"; + } + return defaultErrorMessage(condition); + } + } instance; + return instance; +} + +error_code readRomIdAndManId(DS28C39 & ds28c39, Core::RomId::span romId, + Core::ManId::span manId) { + DS28C39::Status status; + const error_code result = ds28c39.readStatus(false, status); + if (!result) { + copy(make_span(status.romId), romId); + copy(make_span(status.manId), manId); + } + return result; +} + +DS28C39::PageAuthenticationData & +DS28C39::PageAuthenticationData::setAnonymousRomId() { + std::fill(romId().begin(), romId().end(), 0xFF); + return *this; +} + +} // namespace MaximInterfaceDevices
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS28C39.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,444 @@ +/******************************************************************************* +* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceDevices_DS28C39 +#define MaximInterfaceDevices_DS28C39 + +#include <stdint.h> +#include <MaximInterfaceCore/Algorithm.hpp> +#include <MaximInterfaceCore/array_span.hpp> +#include <MaximInterfaceCore/Ecc256.hpp> +#include <MaximInterfaceCore/FlagSet.hpp> +#include <MaximInterfaceCore/ManId.hpp> +#include <MaximInterfaceCore/RomId.hpp> +#include <MaximInterfaceCore/RunCommand.hpp> +#include <MaximInterfaceCore/system_error.hpp> +#include "Config.hpp" + +namespace MaximInterfaceDevices { + +class DS28C39 { +public: + /// Device command results. + enum ErrorValue { + InvalidOperationError = 0x55, + InvalidParameterError = 0x77, + InvalidSequenceError = 0x33, + InternalError = 0x22, + DeviceDisabledError = 0x88, + AuthenticationError = 0x100, + InvalidResponseError ///< Command response does not match expected format. + }; + + /// @name Device memory pages + /// @{ + + static const int authorityPublicKeyXPage = 5; + static const int authorityPublicKeyYPage = 6; + static const int writePublicKeyXPage = 7; + static const int writePublicKeyYPage = 8; + + /// @} + + static const int memoryPages = 9; + + /// Holds a device memory page. + typedef Core::array_span<uint_least8_t, 32> Page; + + // Format page authentication input data. + class PageAuthenticationData; + + // Format authenticated write input data. + class WriteAuthenticationData; + + /// Page protection types. + enum PageProtectionType { + RP = 0x01, ///< Read protection. + WP = 0x02, ///< Write protection. + EM = 0x04, ///< EPROM emulation mode. + ECW = 0x10 ///< Authenticated write. + }; + typedef Core::FlagSet<PageProtectionType, 5> PageProtection; + + struct Status { + enum EntropyHealthTestStatus { + TestNotPerformed = 0xFF, + EntropyHealthy = 0xAA, + EntropyNotHealthy = 0xDD + }; + + typedef Core::array<PageProtection, memoryPages - 2> PageProtectionList; + typedef Core::array<uint_least8_t, 2> RomVersion; + + PageProtectionList pageProtection; + Core::RomId::array romId; + Core::ManId::array manId; + RomVersion romVersion; + EntropyHealthTestStatus entropyHealthTestStatus; + }; + + explicit DS28C39(const Core::RunCommand & runCommand) + : doRunCommand(runCommand) {} + + void setRunCommand(const Core::RunCommand & runCommand) { + doRunCommand = runCommand; + } + + /// @brief Write memory with no protection. + /// @param pageNum Number of page to write. + /// @param page Data to write. + MaximInterfaceDevices_EXPORT Core::error_code + writeMemory(int pageNum, Page::const_span page); + + /// @brief Read memory with no protection. + /// @param pageNum Number of page to read. + /// @param[out] page Data that was read. + MaximInterfaceDevices_EXPORT Core::error_code readMemory(int pageNum, + Page::span page); + + /// @brief + /// Reads the current status of the device and optionally performs an + /// entropy health test. + /// @param entropyHealthTest True to perform an entropy health test. + /// @param[out] status Status that was read. + MaximInterfaceDevices_EXPORT Core::error_code + readStatus(bool entropyHealthTest, Status & status); + + /// @brief Set the protection settings of a page. + /// @param pageNum Number of page to write. + /// @param protection Protection to write. + MaximInterfaceDevices_EXPORT Core::error_code + setPageProtection(int pageNum, const PageProtection & protection); + + /// @brief Compute and read page authentication with ECDSA. + /// @param pageNum Number of page to authenticate. + /// @param anonymous True to disable use of ROM ID in computation. + /// @param challenge Random challenge used to prevent replay attacks. + /// @param[out] signature Computed page signature. + MaximInterfaceDevices_EXPORT Core::error_code + computeAndReadPageAuthentication(int pageNum, bool anonymous, + Page::const_span challenge, + Core::Ecc256::Signature::span signature); + + /// Permanently disable the device. + MaximInterfaceDevices_EXPORT Core::error_code disableDevice(); + + /// @brief Generate the device's ECDSA public key from the PUF private key. + /// @param[out] devicePublicKey Device Public Key + MaximInterfaceDevices_EXPORT Core::error_code + readDevicePublicKey(Core::Ecc256::PublicKey::span devicePublicKey); + + /// @brief Read a block of random data from the RNG. + /// @param[out] data Random data from RNG with length from 1 to 64. + MaximInterfaceDevices_EXPORT Core::error_code + readRng(Core::span<uint_least8_t> data); + + /// @brief + /// Authenticate a public key for authenticated writes using the + /// Authority Public Key. + /// @param certificate + /// Certificate to use for authentication of the Write Public Key. + /// @param customization + /// Certificate customization with length from 1 to 32. + MaximInterfaceDevices_EXPORT Core::error_code + authenticatePublicKey(Core::Ecc256::Signature::const_span certificate, + Core::span<const uint_least8_t> customization); + + /// @brief Write with ECDSA authentication using the Write Public Key. + /// @param pageNum Number of page to write. + /// @param page Data to write. + /// @param signature Signature to use for authentication of page data. + MaximInterfaceDevices_EXPORT Core::error_code + authenticatedWriteMemory(int pageNum, Page::const_span page, + Core::Ecc256::Signature::const_span signature); + + MaximInterfaceDevices_EXPORT static const Core::error_category & + errorCategory(); + +protected: + MaximInterfaceDevices_EXPORT Core::error_code + runCommand(Core::span<const uint_least8_t> request, int delayTime, + Core::span<uint_least8_t> & response); + + MaximInterfaceDevices_EXPORT Core::error_code + runCommand(Core::span<const uint_least8_t> request, int delayTime); + +private: + Core::RunCommand doRunCommand; +}; + +inline Core::error_code make_error_code(DS28C39::ErrorValue e) { + return Core::error_code(e, DS28C39::errorCategory()); +} + +/// @brief Read the device ROM ID and MAN ID using the Read Status command. +/// @param ds28c39 Device to read. +/// @param[out] romId Read ROM ID valid when operation is successful. +/// @param[out] manId Read MAN ID valid when operation is successful. +MaximInterfaceDevices_EXPORT Core::error_code +readRomIdAndManId(DS28C39 & ds28c39, Core::RomId::span romId, + Core::ManId::span manId); + +/// Format page authentication input data. +class DS28C39::PageAuthenticationData { +public: + typedef Core::array_span<uint_least8_t, Core::RomId::size + 2 * Page::size + + 1 + Core::ManId::size> + Result; + + PageAuthenticationData() : result_() {} + + /// Formatted data result. + Result::const_span result() const { return result_; } + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { + return make_span(result_).subspan<romIdIdx, Core::RomId::size>(); + } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { + return const_cast<PageAuthenticationData &>(*this).romId(); + } + + /// Set ROM ID. + PageAuthenticationData & setRomId(Core::RomId::const_span romId) { + copy(romId, this->romId()); + return *this; + } + + /// Set ROM ID for use in anonymous mode. + MaximInterfaceDevices_EXPORT PageAuthenticationData & setAnonymousRomId(); + + /// @} + + /// @name Page + /// @brief Data from a device memory page. + /// @{ + + /// Get mutable page. + Page::span page() { + return make_span(result_).subspan<pageIdx, Page::size>(); + } + + /// Get immutable page. + Page::const_span page() const { + return const_cast<PageAuthenticationData &>(*this).page(); + } + + /// Set page. + PageAuthenticationData & setPage(Page::const_span page) { + copy(page, this->page()); + return *this; + } + + /// @} + + /// @name Challenge + /// @brief Random challenge used to prevent replay attacks. + /// @{ + + /// Get mutable Challenge. + Page::span challenge() { + return make_span(result_).subspan<challengeIdx, Page::size>(); + } + + /// Get immutable Challenge. + Page::const_span challenge() const { + return const_cast<PageAuthenticationData &>(*this).challenge(); + } + + /// Set Challenge. + PageAuthenticationData & setChallenge(Page::const_span challenge) { + copy(challenge, this->challenge()); + return *this; + } + + /// @} + + /// @name Page number + /// @brief Number of the page to use data from. + /// @{ + + /// Get page number. + int pageNum() const { return result_[pageNumIdx]; } + + /// Set page number. + PageAuthenticationData & setPageNum(int pageNum) { + result_[pageNumIdx] = pageNum; + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get mutable MAN ID. + Core::ManId::span manId() { + return make_span(result_).subspan<manIdIdx, Core::ManId::size>(); + } + + /// Get immutable MAN ID. + Core::ManId::const_span manId() const { + return const_cast<PageAuthenticationData &>(*this).manId(); + } + + /// Set MAN ID. + PageAuthenticationData & setManId(Core::ManId::const_span manId) { + copy(manId, this->manId()); + return *this; + } + + /// @} + +private: + typedef Result::span::index_type index; + + static const index romIdIdx = 0; + static const index pageIdx = romIdIdx + Core::RomId::size; + static const index challengeIdx = pageIdx + Page::size; + static const index pageNumIdx = challengeIdx + Page::size; + static const index manIdIdx = pageNumIdx + 1; + + Result::array result_; +}; + +/// Format authenticated write input data. +class DS28C39::WriteAuthenticationData { +public: + typedef PageAuthenticationData::Result Result; + + WriteAuthenticationData() : data() { setPageNum(0); } + + /// Formatted data result. + Result::const_span result() const { return data.result(); } + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { return data.romId(); } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { return data.romId(); } + + /// Set ROM ID. + WriteAuthenticationData & setRomId(Core::RomId::const_span romId) { + data.setRomId(romId); + return *this; + } + + /// @} + + /// @name Old page + /// @brief Existing data contained in the page. + /// @{ + + /// Get mutable old page. + Page::span oldPage() { return data.page(); } + + /// Get immutable old page. + Page::const_span oldPage() const { return data.page(); } + + /// Set old page. + WriteAuthenticationData & setOldPage(Page::const_span oldPage) { + data.setPage(oldPage); + return *this; + } + + /// @} + + /// @name New page + /// @brief New data to write to the page. + /// @{ + + /// Get mutable new page. + Page::span newPage() { return data.challenge(); } + + /// Get immutable new page. + Page::const_span newPage() const { return data.challenge(); } + + /// Set new page. + WriteAuthenticationData & setNewPage(Page::const_span newPage) { + data.setChallenge(newPage); + return *this; + } + + /// @} + + /// @name Page number + /// @brief Page number for write operation. + /// @{ + + /// Get page number. + int pageNum() const { return data.pageNum() & 0x7F; } + + /// Set page number. + WriteAuthenticationData & setPageNum(int pageNum) { + data.setPageNum(pageNum | 0x80); + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get mutable MAN ID. + Core::ManId::span manId() { return data.manId(); } + + /// Get immutable MAN ID. + Core::ManId::const_span manId() const { return data.manId(); } + + /// Set MAN ID. + WriteAuthenticationData & setManId(Core::ManId::const_span manId) { + data.setManId(manId); + return *this; + } + + /// @} + +private: + PageAuthenticationData data; +}; + +} // namespace MaximInterfaceDevices + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS28C40.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,655 @@ +/******************************************************************************* +* Copyright (C) 2019 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include <stddef.h> +#include <algorithm> +#include <MaximInterfaceCore/Error.hpp> +#include "DS28C40.hpp" + +namespace MaximInterfaceDevices { + +using namespace Core; +using std::copy; + +static const int readMemoryTimeMs = 2; +static const int writeMemoryTimeMs = 150; +static const int writeStateTimeMs = 15; +static const int generateEccKeyPairTimeMs = 500; +static const int generateEcdsaSignatureTimeMs = 50; +static const int computeTimeMs = 4; +static const int verifyEcdsaTimeMs = 160; +static const int trngGenerationTimeMs = 50; +static const int trngOnDemandCheckTimeMs = 50; + +static const uint_least8_t computeAndReadPageAuthenticationCmd = 0xA5; +static const uint_least8_t readRngCmd = 0xD2; + +const int DS28C40::publicKeyAxPage; +const int DS28C40::publicKeyAyPage; +const int DS28C40::publicKeyBxPage; +const int DS28C40::publicKeyByPage; +const int DS28C40::authorityPublicKeyAxPage; +const int DS28C40::authorityPublicKeyAyPage; +const int DS28C40::authorityPublicKeyBxPage; +const int DS28C40::authorityPublicKeyByPage; +const int DS28C40::privateKeyAPage; +const int DS28C40::privateKeyBPage; +const int DS28C40::secretAPage; +const int DS28C40::secretBPage; +const int DS28C40::romOptionsPage; +const int DS28C40::gpioControlPage; +const int DS28C40::publicKeySxPage; +const int DS28C40::publicKeySyPage; + +const int DS28C40::memoryPages; +const int DS28C40::protectionBlocks; + +error_code DS28C40::writeMemory(int pageNum, Page::const_span page) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t request[2 + Page::size]; + request[0] = 0x96; + request[1] = pageNum; + copy(page.begin(), page.end(), request + 2); + return runCommand(request, writeMemoryTimeMs); +} + +error_code DS28C40::readMemory(int pageNum, Page::span page) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t buffer[1 + Page::size]; + buffer[0] = 0x44; + buffer[1] = pageNum; + span<uint_least8_t> response(buffer); + const error_code result = + runCommand(make_span(buffer, 2), readMemoryTimeMs, response); + if (!result) { + copy(response.begin(), response.end(), page.begin()); + } + return result; +} + +error_code +DS28C40::encryptedReadMemory(int pageNum, KeySecret secret, + EncryptionChallenge::span encryptionChallenge, + Page::span encryptedPage) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + const size_t requestSize = 3; + const size_t responseSize = 1 + EncryptionChallenge::size + Page::size; + uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)]; + buffer[0] = 0x4B; + buffer[1] = pageNum; + buffer[2] = secret; + span<uint_least8_t> response(buffer, responseSize); + const error_code result = + runCommand(make_span(buffer, requestSize), + readMemoryTimeMs + computeTimeMs, response); + if (!result) { + span<uint_least8_t>::const_iterator begin = response.begin(); + span<uint_least8_t>::const_iterator end = + begin + encryptionChallenge.size(); + copy(begin, end, encryptionChallenge.begin()); + begin = end; + end = begin + encryptedPage.size(); + copy(begin, end, encryptedPage.begin()); + } + return result; +} + +error_code DS28C40::readBlockProtection(int blockNumber, + Optional<KeySecret> & keySecret, + BlockProtection & protection) { + if (blockNumber < 0 || blockNumber >= protectionBlocks) { + return make_error_code(InvalidParameterError); + } + + const size_t requestSize = 2; + const size_t responseSize = 3; + uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)]; + buffer[0] = 0xAA; + buffer[1] = blockNumber; + span<uint_least8_t> response(buffer, responseSize); + const error_code result = + runCommand(make_span(buffer, requestSize), readMemoryTimeMs, response); + if (result) { + return result; + } + if ((response[0] & 0x3F) != blockNumber) { + return make_error_code(InvalidResponseError); + } + switch (response[0] >> 6) { + case 0: + keySecret = none; + break; + case 1: + keySecret = KeySecretA; + break; + case 2: + keySecret = KeySecretB; + break; + default: + return make_error_code(InvalidResponseError); + } + if ((response[1] & 0x20) != 0) { + return make_error_code(InvalidResponseError); + } + protection = response[1]; + return error_code(); +} + +error_code DS28C40::setBlockProtection(int blockNum, KeySecret keySecret, + const BlockProtection & protection) { + if (blockNum < 0 || blockNum >= protectionBlocks || keySecret == KeySecretS) { + return make_error_code(InvalidParameterError); + } + + const uint_least8_t request[] = { + 0xC3, + static_cast<uint_least8_t>((keySecret == KeySecretB ? 0x80 : 0x40) | + blockNum), + static_cast<uint_least8_t>(protection.to_ulong())}; + return runCommand(request, writeStateTimeMs); +} + +error_code +DS28C40::computeAndReadPageAuthentication(int pageNum, KeySecret key, + Page::const_span challenge, + Ecc256::Signature::span signature) { + if (pageNum < 0 || pageNum >= memoryPages || key == KeySecretS) { + return make_error_code(InvalidParameterError); + } + + const size_t requestSize = 3 + Page::size; + const size_t responseSize = 1 + 2 * Ecc256::Scalar::size; + uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)]; + buffer[0] = computeAndReadPageAuthenticationCmd; + buffer[1] = pageNum; + buffer[2] = key + 3; + copy(challenge.begin(), challenge.end(), buffer + 3); + span<uint_least8_t> response(buffer, responseSize); + const error_code result = runCommand(make_span(buffer, requestSize), + generateEcdsaSignatureTimeMs, response); + if (!result) { + span<uint_least8_t>::const_iterator begin = response.begin(); + span<uint_least8_t>::const_iterator end = begin + signature.s.size(); + copy(begin, end, signature.s.begin()); + begin = end; + end = begin + signature.r.size(); + copy(begin, end, signature.r.begin()); + } + return result; +} + +error_code DS28C40::computeAndReadPageAuthentication(int pageNum, + KeySecret secret, + Page::const_span challenge, + Page::span hmac) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + const size_t requestSize = 3 + Page::size; + const size_t responseSize = 1 + Page::size; + uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)]; + buffer[0] = computeAndReadPageAuthenticationCmd; + buffer[1] = pageNum; + buffer[2] = secret; + copy(challenge.begin(), challenge.end(), buffer + 3); + span<uint_least8_t> response(buffer, responseSize); + const error_code result = + runCommand(make_span(buffer, requestSize), computeTimeMs, response); + if (!result) { + copy(response.begin(), response.end(), hmac.begin()); + } + return result; +} + +error_code DS28C40::computeMultiblockHash(bool firstBlock, bool lastBlock, + span<const uint_least8_t> data) { + const span<const uint_least8_t>::index_type maxDataSize = 64; + + if (data.size() < 1 || data.size() > maxDataSize) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t buffer[2 + maxDataSize]; + buffer[0] = 0x33; + buffer[1] = 0; + if (firstBlock) { + buffer[1] |= 0x40; + } + if (lastBlock) { + buffer[1] |= 0x80; + } + copy(data.begin(), data.end(), buffer + 2); + return runCommand(make_span(buffer, 2 + data.size()), computeTimeMs); +} + +error_code DS28C40::verifyEcdsaSignature( + KeySecret key, bool authorityKey, GpioState gpioState, + Ecc256::Signature::const_span signature, span<const uint_least8_t> data) { + return verifyEcdsaSignature(key, authorityKey, DataInput, gpioState, + signature, data); +} + +error_code DS28C40::verifyEcdsaSignature( + KeySecret key, bool authorityKey, GpioState gpioState, + Ecc256::Signature::const_span signature, Page::const_span hash) { + return verifyEcdsaSignature(key, authorityKey, HashInput, gpioState, + signature, hash); +} + +error_code +DS28C40::verifyEcdsaSignature(KeySecret key, bool authorityKey, + GpioState gpioState, + Ecc256::Signature::const_span signature) { + return verifyEcdsaSignature(key, authorityKey, THASH, gpioState, signature, + span<const uint_least8_t>()); +} + +error_code DS28C40::verifyEcdsaSignature( + KeySecret key, bool authorityKey, HashType hashType, GpioState gpioState, + Ecc256::Signature::const_span signature, span<const uint_least8_t> buffer) { + const span<const uint_least8_t>::index_type maxBufferSize = 61; + + if (buffer.size() > maxBufferSize) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t request[2 + 2 * Ecc256::Scalar::size + maxBufferSize]; + uint_least8_t * requestIt = request; + *requestIt++ = 0x59; + switch (key) { + case KeySecretA: + if (authorityKey) { + *requestIt = 2; + } else { + *requestIt = 0; + } + break; + case KeySecretB: + if (authorityKey) { + *requestIt = 3; + } else { + *requestIt = 1; + } + break; + case KeySecretS: + if (!authorityKey) { + *requestIt = 4; + break; + } + // else: Go to default case. + default: + return make_error_code(InvalidParameterError); + } + *requestIt |= hashType << 3; + if (gpioState != Unchanged) { + *requestIt |= 0x40; + } + if (gpioState == Conducting) { + *requestIt |= 0x20; + } + requestIt = copy(signature.r.begin(), signature.r.end(), ++requestIt); + requestIt = copy(signature.s.begin(), signature.s.end(), requestIt); + requestIt = copy(buffer.begin(), buffer.end(), requestIt); + return runCommand(make_span(request, requestIt), + verifyEcdsaTimeMs + + (hashType == DataInput ? computeTimeMs : 0)); +} + +error_code DS28C40::authenticateEcdsaPublicKey( + KeySecret key, Ecc256::Signature::const_span cert, + span<const uint_least8_t> certCustomization) { + return authenticateEcdsaPublicKey(key, true, cert, certCustomization, NULL); +} + +error_code DS28C40::authenticateEcdsaPublicKey( + KeySecret key, bool authWrites, Ecc256::Signature::const_span cert, + span<const uint_least8_t> certCustomization, + span<const uint_least8_t> ecdhCustomization) { + return authenticateEcdsaPublicKey(key, authWrites, cert, certCustomization, + &ecdhCustomization); +} + +error_code DS28C40::authenticateEcdsaPublicKey( + KeySecret key, bool authWrites, Ecc256::Signature::const_span cert, + span<const uint_least8_t> certCustomization, + const span<const uint_least8_t> * ecdhCustomization) { + const span<const uint_least8_t>::index_type minCustomizationSize = 1; + const span<const uint_least8_t>::index_type maxCertCustomizationSize = 32; + const span<const uint_least8_t>::index_type maxEcdhCustomizationSize = 48; + const span<const uint_least8_t>::index_type maxTotalCustomizationSize = 60; + + if (!(certCustomization.size() >= minCustomizationSize && + certCustomization.size() <= maxCertCustomizationSize && + (!ecdhCustomization || + (ecdhCustomization->size() >= minCustomizationSize && + ecdhCustomization->size() <= maxEcdhCustomizationSize && + certCustomization.size() + ecdhCustomization->size() <= + maxTotalCustomizationSize)))) { + return make_error_code(InvalidParameterError); + } + + if (key == KeySecretS) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t + request[2 + 2 * Ecc256::Scalar::size + maxTotalCustomizationSize]; + uint_least8_t * requestIt = request; + *requestIt++ = 0xA8; + *requestIt++ = static_cast<uint_least8_t>( + ((certCustomization.size() - 1) << 3) | (key << 2) | + ((ecdhCustomization != NULL) << 1) | (authWrites << 0)); + requestIt = copy(cert.r.begin(), cert.r.end(), requestIt); + requestIt = copy(cert.s.begin(), cert.s.end(), requestIt); + requestIt = + copy(certCustomization.begin(), certCustomization.end(), requestIt); + int delay = verifyEcdsaTimeMs; + if (ecdhCustomization) { + const span<const uint_least8_t>::index_type certCustomizationPaddingSize = + maxCertCustomizationSize - certCustomization.size(); + std::fill_n(requestIt, certCustomizationPaddingSize, 0); + requestIt += certCustomizationPaddingSize; + requestIt = + copy(ecdhCustomization->begin(), ecdhCustomization->end(), requestIt); + delay += verifyEcdsaTimeMs; + } + return runCommand(make_span(request, requestIt), delay); +} + +error_code DS28C40::authenticatedEcdsaWriteMemory( + int pageNum, bool useKeyS, Page::const_span newPageData, + Ecc256::Signature::const_span signature) { + return authenticatedEcdsaWriteMemory(pageNum, useKeyS, newPageData, signature, + NULL); +} + +error_code DS28C40::authenticatedEcdsaWriteMemory( + int pageNum, bool useKeyS, Page::const_span newPageData, + Ecc256::Signature::const_span signature, + EncryptionChallenge::const_span challenge) { + return authenticatedEcdsaWriteMemory(pageNum, useKeyS, newPageData, signature, + &challenge); +} + +error_code DS28C40::authenticatedEcdsaWriteMemory( + int pageNum, bool useKeyS, Page::const_span newPageData, + Ecc256::Signature::const_span signature, + const EncryptionChallenge::const_span * challenge) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t request[2 + Page::size + 2 * Ecc256::Scalar::size + + EncryptionChallenge::size]; + uint_least8_t * requestIt = request; + *requestIt++ = 0x89; + *requestIt = pageNum; + if (useKeyS) { + *requestIt |= 0x80; + } + requestIt = copy(newPageData.begin(), newPageData.end(), ++requestIt); + requestIt = copy(signature.r.begin(), signature.r.end(), requestIt); + requestIt = copy(signature.s.begin(), signature.s.end(), requestIt); + int delay = verifyEcdsaTimeMs + writeMemoryTimeMs; + if (challenge) { + requestIt = copy(challenge->begin(), challenge->end(), requestIt); + delay += computeTimeMs; + } + return runCommand(make_span(request, requestIt), delay); +} + +error_code DS28C40::authenticatedSha256WriteMemory(int pageNum, bool useSecretS, + Page::const_span newPageData, + Page::const_span hmac) { + return authenticatedSha256WriteMemory(pageNum, useSecretS, newPageData, hmac, + NULL); +} + +error_code DS28C40::authenticatedSha256WriteMemory( + int pageNum, bool useSecretS, Page::const_span newPageData, + Page::const_span hmac, EncryptionChallenge::const_span challenge) { + return authenticatedSha256WriteMemory(pageNum, useSecretS, newPageData, hmac, + &challenge); +} + +error_code DS28C40::authenticatedSha256WriteMemory( + int pageNum, bool useSecretS, Page::const_span newPageData, + Page::const_span hmac, const EncryptionChallenge::const_span * challenge) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t request[3 + 2 * Page::size + EncryptionChallenge::size]; + uint_least8_t * requestIt = request; + *requestIt++ = 0x99; + *requestIt++ = pageNum; + *requestIt++ = useSecretS ? 2 : 0; + requestIt = copy(newPageData.begin(), newPageData.end(), requestIt); + requestIt = copy(hmac.begin(), hmac.end(), requestIt); + int delay = writeMemoryTimeMs + computeTimeMs; + if (challenge) { + requestIt = copy(challenge->begin(), challenge->end(), requestIt); + delay += computeTimeMs; + } + return runCommand(make_span(request, requestIt), delay); +} + +error_code +DS28C40::computeAndWriteSha256Secret(int pageNum, KeySecret masterSecret, + KeySecret destinationSecret, + Page::const_span partialSecret) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t request[3 + Page::size]; + request[0] = 0x3C; + request[1] = pageNum; + request[2] = (destinationSecret << 2) | masterSecret; + copy(partialSecret.begin(), partialSecret.end(), request + 3); + return runCommand(request, writeMemoryTimeMs + computeTimeMs); +} + +error_code DS28C40::generateEcc256KeyPair(KeySecret key) { + if (key == KeySecretS) { + return make_error_code(InvalidParameterError); + } + + const uint_least8_t request[] = {0xCB, key == KeySecretB}; + return runCommand(request, generateEccKeyPairTimeMs); +} + +error_code DS28C40::readRng(span<uint_least8_t> data) { + const span<uint_least8_t>::index_type maxDataSize = 64; + if ((data.size() < 1) || (data.size() > maxDataSize)) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t buffer[1 + maxDataSize]; + buffer[0] = readRngCmd; + buffer[1] = static_cast<uint_least8_t>(data.size() - 1); + span<uint_least8_t> response(buffer, 1 + data.size()); + const error_code result = + runCommand(make_span(buffer, 2), trngGenerationTimeMs, response); + if (!result) { + copy(response.begin(), response.end(), data.begin()); + } + return result; +} + +error_code DS28C40::entropyHealthTest() { + const uint_least8_t request[] = {readRngCmd, 0x80}; + return runCommand(request, trngOnDemandCheckTimeMs); +} + +error_code DS28C40::runCommand(span<const uint_least8_t> request, int delayTime, + span<uint_least8_t> & response) { + const span<const uint_least8_t>::index_type responseInputSize = + response.size(); + error_code result = doRunCommand(request, delayTime, response); + if (result) { + return result; + } + if (response.empty()) { + return make_error_code(InvalidResponseError); + } + // Parse command result byte. + switch (response[0]) { + case 0xAA: + // Success response. + if (response.size() != responseInputSize) { + result = make_error_code(InvalidResponseError); + } + break; + + case 0x00: + result = make_error_code(AuthenticationError); + break; + + default: + result.assign(response[0], errorCategory()); + break; + } + response = response.subspan(1); + return result; +} + +error_code DS28C40::runCommand(span<const uint_least8_t> request, + int delayTime) { + uint_least8_t buffer; + span<uint_least8_t> response(&buffer, 1); + return runCommand(request, delayTime, response); +} + +const error_category & DS28C40::errorCategory() { + static class : public error_category { + public: + virtual const char * name() const { return "DS28C40"; } + + virtual std::string message(int condition) const { + switch (condition) { + case InvalidOperationError: + return "Invalid Operation Error"; + + case InvalidParameterError: + return "Invalid Parameter Error"; + + case InvalidSequenceError: + return "Invalid Sequence Error"; + + case AuthenticationError: + return "Authentication Error"; + + case InternalError: + return "Internal Error"; + + case DeviceDisabledError: + return "Device Disabled Error"; + + case InvalidResponseError: + return "Invalid Response Error"; + } + return defaultErrorMessage(condition); + } + } instance; + return instance; +} + +error_code computeMultiblockHash(DS28C40 & device, + span<const uint_least8_t> data) { + error_code result; + span<const uint_least8_t>::index_type dataIdx = 0; + while (dataIdx < data.size() && !result) { + const span<const uint_least8_t>::index_type remainingSize = + data.size() - dataIdx; + const span<const uint_least8_t>::index_type chunkSize = + std::min<span<const uint_least8_t>::index_type>(remainingSize, 64); + result = + device.computeMultiblockHash(dataIdx == 0, remainingSize == chunkSize, + data.subspan(dataIdx, chunkSize)); + dataIdx += chunkSize; + } + return result; +} + +error_code readRomIdAndManId(DS28C40 & device, RomId::span romId, + ManId::span manId) { + DS28C40::Page::array page; + error_code result = device.readMemory(DS28C40::romOptionsPage, page); + if (!result) { + const DS28C40::RomOptions romOptions(page); + copy(romOptions.romId(), romId); + copy(romOptions.manId(), manId); + } + return result; +} + +static void setAnonymous(RomId::span romId) { + std::fill(romId.begin(), romId.end(), 0xFF); +} + +DS28C40::PageAuthenticationData & +DS28C40::PageAuthenticationData::setAnonymousRomId() { + setAnonymous(romId()); + return *this; +} + +DS28C40::ComputeSecretData::ComputeSecretData() : data() { + setPageNum(0); + setManId(ManId::array()); +} + +DS28C40::ComputeSecretData & +DS28C40::ComputeSecretData::setManId(ManId::const_span manId) { + ManId::array validatedManId; + copy(manId, make_span(validatedManId)); + validatedManId[1] |= 0x80; + data.setManId(validatedManId); + return *this; +} + +DS28C40::DecryptionHmacData & DS28C40::DecryptionHmacData::setAnonymousRomId() { + setAnonymous(romId()); + return *this; +} + +} // namespace MaximInterfaceDevices
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS28C40.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,983 @@ +/******************************************************************************* +* Copyright (C) 2019 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceDevices_DS28C40 +#define MaximInterfaceDevices_DS28C40 + +#include <stdint.h> +#include <MaximInterfaceCore/Algorithm.hpp> +#include <MaximInterfaceCore/array_span.hpp> +#include <MaximInterfaceCore/Ecc256.hpp> +#include <MaximInterfaceCore/FlagSet.hpp> +#include <MaximInterfaceCore/ManId.hpp> +#include <MaximInterfaceCore/Optional.hpp> +#include <MaximInterfaceCore/RomId.hpp> +#include <MaximInterfaceCore/RunCommand.hpp> +#include <MaximInterfaceCore/system_error.hpp> +#include "Config.hpp" + +namespace MaximInterfaceDevices { + +class DS28C40 { +public: + /// Device command results. + enum ErrorValue { + InternalError = 0x22, + InvalidSequenceError = 0x33, + InvalidOperationError = 0x55, + InvalidParameterError = 0x77, + DeviceDisabledError = 0x88, + AuthenticationError = 0x100, + InvalidResponseError ///< Command response does not match expected format. + }; + + /// @name Device memory pages + /// @{ + + static const int publicKeyAxPage = 28; + static const int publicKeyAyPage = 29; + static const int publicKeyBxPage = 30; + static const int publicKeyByPage = 31; + static const int authorityPublicKeyAxPage = 32; + static const int authorityPublicKeyAyPage = 33; + static const int authorityPublicKeyBxPage = 34; + static const int authorityPublicKeyByPage = 35; + static const int privateKeyAPage = 36; + static const int privateKeyBPage = 37; + static const int secretAPage = 38; + static const int secretBPage = 39; + static const int romOptionsPage = 40; + static const int gpioControlPage = 41; + static const int publicKeySxPage = 42; + static const int publicKeySyPage = 43; + + /// @} + + static const int memoryPages = 44; + static const int protectionBlocks = 9; + + /// Key or secret to use for operation. + enum KeySecret { KeySecretA = 0, KeySecretB = 1, KeySecretS = 2 }; + + /// Available PIO states when verifying an ECDSA signature. + enum GpioState { Unchanged, Conducting, HighImpedance }; + + /// Holds a device memory page. + typedef Core::array_span<uint_least8_t, 32> Page; + + /// Challenge for an encrypted device memory page. + typedef Core::array_span<uint_least8_t, 8> EncryptionChallenge; + + // Format page authentication input data. + class PageAuthenticationData; + + // Format authenticated write input data. + class WriteAuthenticationData; + + // Format compute secret input data. + class ComputeSecretData; + + // Format decryption HMAC input data. + class DecryptionHmacData; + + // Format encryption HMAC input data. + class EncryptionHmacData; + + // Access fields in the ROM Options page. + class RomOptions; + + // Access fields in the GPIO Control page. + class GpioControl; + + /// Page protection types. + enum BlockProtectionType { + RP = 0x01, ///< Read protection. + WP = 0x02, ///< Write protection. + EM = 0x04, ///< EPROM emulation mode. + APH = 0x08, ///< Authentication Write Protection HMAC + EPH = 0x10, ///< Encryption and Authentication Write Protection HMAC + ECH = 0x40, ///< Encryption and write using shared key from ECDH + ECW = 0x80 ///< Authentication Write Protection ECDSA + }; + typedef Core::FlagSet<BlockProtectionType, 8> BlockProtection; + + explicit DS28C40(const Core::RunCommand & runCommand) + : doRunCommand(runCommand) {} + + void setRunCommand(const Core::RunCommand & runCommand) { + doRunCommand = runCommand; + } + + /// @brief Write memory with no protection. + /// @param pageNum Number of page to write. + /// @param page Data to write. + MaximInterfaceDevices_EXPORT Core::error_code + writeMemory(int pageNum, Page::const_span page); + + /// @brief Read memory with no protection. + /// @param pageNum Number of page to read. + /// @param[out] page Data that was read. + MaximInterfaceDevices_EXPORT Core::error_code readMemory(int pageNum, + Page::span page); + + /// @brief Read memory with encryption. + /// @param pageNum Number of page to read from. + /// @param secret Secret to use for encryption. + /// @param[out] challenge Encryption challenge that was read. + /// @param[out] encryptedPage Encrypted page data that was read. + MaximInterfaceDevices_EXPORT Core::error_code + encryptedReadMemory(int pageNum, KeySecret secret, + EncryptionChallenge::span challenge, + Page::span encryptedPage); + + /// @brief Read the protection settings of a block. + /// @param blockNum Number of block to read. + /// @param[out] keySecret Secret key set on the block or empty if not set. + /// @param[out] protection Protection that was read. + MaximInterfaceDevices_EXPORT Core::error_code + readBlockProtection(int blockNum, Core::Optional<KeySecret> & keySecret, + BlockProtection & protection); + + /// @brief Set the protection settings of a block. + /// @param blockNum Number of block to write. + /// @param keySecret Secret/Key A or B. + /// @param protection Protection to write. + MaximInterfaceDevices_EXPORT Core::error_code + setBlockProtection(int blockNum, KeySecret keySecret, + const BlockProtection & protection); + + /// @brief Compute and read page authentication with ECDSA. + /// @param pageNum Number of page to authenticate. + /// @param key + /// Private key to use for authentication. + /// Key S cannot be used with this command. + /// @param challenge Random challenge used to prevent replay attacks. + /// @param[out] signature Computed page signature. + MaximInterfaceDevices_EXPORT Core::error_code + computeAndReadPageAuthentication(int pageNum, KeySecret key, + Page::const_span challenge, + Core::Ecc256::Signature::span signature); + + /// @brief Compute and read page authentication with HMAC. + /// @param pageNum Number of page to authenticate. + /// @param secret + /// Secret to use for authentication. + /// Secret S cannot be used with this command. + /// @param challenge Random challenge used to prevent replay attacks. + /// @param[out] hmac Computed page HMAC. + MaximInterfaceDevices_EXPORT Core::error_code + computeAndReadPageAuthentication(int pageNum, KeySecret secret, + Page::const_span challenge, Page::span hmac); + + /// @brief Compute a hash over multiple blocks. + /// @param firstBlock True if this is the first block being hashed. + /// @param lastBlock True if this is the last block being hashed. + /// @param data + /// Data block to hash. Should be 64 bytes unless this is the last block. + MaximInterfaceDevices_EXPORT Core::error_code + computeMultiblockHash(bool firstBlock, bool lastBlock, + Core::span<const uint_least8_t> data); + + /// @brief Verify ECDSA signature with data input. + /// @param key Public key to use for verification. + /// @param authorityKey Use the authority key instead of the standard key. + /// @param gpioState New state of the GPIO pin if verification successful. + /// @param signature Signature to verify. + /// @param data Data to verify with length from 1 to 64. + MaximInterfaceDevices_EXPORT Core::error_code + verifyEcdsaSignature(KeySecret key, bool authorityKey, GpioState gpioState, + Core::Ecc256::Signature::const_span signature, + Core::span<const uint_least8_t> data); + + /// @brief Verify ECDSA signature with hash input. + /// @param key Public key to use for verification. + /// @param authorityKey Use the authority key instead of the standard key. + /// @param gpioState New state of the GPIO pin if verification successful. + /// @param signature Signature to verify. + /// @param hash Hash of data to verify. + MaximInterfaceDevices_EXPORT Core::error_code + verifyEcdsaSignature(KeySecret key, bool authorityKey, GpioState gpioState, + Core::Ecc256::Signature::const_span signature, + Page::const_span hash); + + /// @brief + /// Verify ECDSA signature with THASH input from Compute Multiblock Hash. + /// @param key Public key to use for verification. + /// @param authorityKey Use the authority key instead of the standard key. + /// @param gpioState New state of the GPIO pin if verification successful. + /// @param signature Signature to verify. + MaximInterfaceDevices_EXPORT Core::error_code + verifyEcdsaSignature(KeySecret key, bool authorityKey, GpioState gpioState, + Core::Ecc256::Signature::const_span signature); + + /// @brief Authenticate a public key for authenticated writes. + /// @param key + /// Authority key to use for authentication. Key A or B can be selected. + /// @param cert Certificate to use for authentication of Public Key S. + /// @param certCustomization + /// Certificate customization with length from 1 to 32. + MaximInterfaceDevices_EXPORT Core::error_code + authenticateEcdsaPublicKey(KeySecret key, + Core::Ecc256::Signature::const_span cert, + Core::span<const uint_least8_t> certCustomization); + + /// @brief + /// Authenticate a public key for ECDH and optionally authenticated writes. + /// @param key + /// Keys to use for authentication and ECDH key exchange. + /// Key A or B can be selected. + /// @param authWrites True to select authentication for writes. + /// @param cert Certificate to use for authentication of Public Key S. + /// @param certCustomization + /// Certificate customization with length from 1 to 32. + /// @param ecdhCustomization ECDH customization with length from 1 to 48. + /// @note The maximum total customization length is 60 bytes. + MaximInterfaceDevices_EXPORT Core::error_code + authenticateEcdsaPublicKey(KeySecret key, bool authWrites, + Core::Ecc256::Signature::const_span cert, + Core::span<const uint_least8_t> certCustomization, + Core::span<const uint_least8_t> ecdhCustomization); + + /// @brief Write with ECDSA authentication. + /// @param pageNum Number of page to write. + /// @param useKeyS + /// Use Public Key S instead of the authority key set in the block protection. + /// @param newPageData Data to write. + /// @param signature Signature to use for authentication of page data. + MaximInterfaceDevices_EXPORT Core::error_code + authenticatedEcdsaWriteMemory(int pageNum, bool useKeyS, + Page::const_span newPageData, + Core::Ecc256::Signature::const_span signature); + + /// @brief Write with ECDSA authentication and encryption. + /// @param pageNum Number of page to write. + /// @param useKeyS + /// Use Public Key S instead of the authority key set in the block protection. + /// @param newPageData Encrypted data to write. + /// @param signature Signature to use for authentication of page data. + /// @param challenge Challenge to use for decryption of page data. + MaximInterfaceDevices_EXPORT Core::error_code + authenticatedEcdsaWriteMemory(int pageNum, bool useKeyS, + Page::const_span newPageData, + Core::Ecc256::Signature::const_span signature, + EncryptionChallenge::const_span challenge); + + /// @brief Write with SHA-256 HMAC authentication. + /// @param pageNum Number of page to write. + /// @param useSecretS + /// Use Secret S instead of the secret set in the block protection. + /// @param newPageData Data to write. + /// @param hmac HMAC to use for authentication of page data. + MaximInterfaceDevices_EXPORT Core::error_code + authenticatedSha256WriteMemory(int pageNum, bool useSecretS, + Page::const_span newPageData, + Page::const_span hmac); + + /// @brief Write with SHA-256 HMAC authentication and encryption. + /// @param pageNum Number of page to write. + /// @param useSecretS + /// Use Secret S instead of the secret set in the block protection. + /// @param newPageData Data to write. + /// @param hmac HMAC to use for authentication of page data. + /// @param challenge Challenge to use for decryption of page data. + MaximInterfaceDevices_EXPORT Core::error_code authenticatedSha256WriteMemory( + int pageNum, bool useSecretS, Page::const_span newPageData, + Page::const_span hmac, EncryptionChallenge::const_span challenge); + + /// @brief Compute a derivative SHA-256 secret from an existing secret. + /// @param pageNum Number of page to use in computation. + /// @param masterSecret Master secret to use in computation. + /// @param destinationSecret + /// Destination secret to receive the computation result. + /// @param partialSecret Partial secret to use in computation. + MaximInterfaceDevices_EXPORT Core::error_code + computeAndWriteSha256Secret(int pageNum, KeySecret masterSecret, + KeySecret destinationSecret, + Page::const_span partialSecret); + + /// @brief Generate a new ECDSA key pair. + /// @param key Key to generate. Key S cannot be used with this command. + MaximInterfaceDevices_EXPORT Core::error_code + generateEcc256KeyPair(KeySecret key); + + /// @brief Read a block of random data from the RNG. + /// @param[out] data Random data from RNG with length from 1 to 64. + MaximInterfaceDevices_EXPORT Core::error_code + readRng(Core::span<uint_least8_t> data); + + /// Run entropy health test on the RNG. + MaximInterfaceDevices_EXPORT Core::error_code entropyHealthTest(); + + MaximInterfaceDevices_EXPORT static const Core::error_category & + errorCategory(); + +private: + enum HashType { HashInput, DataInput, THASH }; + + Core::error_code + verifyEcdsaSignature(KeySecret key, bool authorityKey, HashType hashType, + GpioState gpioState, + Core::Ecc256::Signature::const_span signature, + Core::span<const uint_least8_t> buffer); + + Core::error_code authenticateEcdsaPublicKey( + KeySecret key, bool authWrites, Core::Ecc256::Signature::const_span cert, + Core::span<const uint_least8_t> certCustomization, + const Core::span<const uint_least8_t> * ecdhCustomization); + + Core::error_code authenticatedEcdsaWriteMemory( + int pageNum, bool useKeyS, Page::const_span newPageData, + Core::Ecc256::Signature::const_span signature, + const EncryptionChallenge::const_span * challenge); + + Core::error_code authenticatedSha256WriteMemory( + int pageNum, bool useSecretS, Page::const_span newPageData, + Page::const_span hmac, const EncryptionChallenge::const_span * challenge); + + Core::error_code runCommand(Core::span<const uint_least8_t> request, + int delayTime, + Core::span<uint_least8_t> & response); + + Core::error_code runCommand(Core::span<const uint_least8_t> request, + int delayTime); + + Core::RunCommand doRunCommand; +}; + +inline Core::error_code make_error_code(DS28C40::ErrorValue e) { + return Core::error_code(e, DS28C40::errorCategory()); +} + +/// @brief +/// Hash arbitrary length data with successive Compute Multiblock Hash commands. +/// @param device Device for computation. +/// @param data Data to hash. +MaximInterfaceDevices_EXPORT Core::error_code +computeMultiblockHash(DS28C40 & device, Core::span<const uint_least8_t> data); + +/// @brief +/// Read the device ROM ID and MAN ID using the Read Memory command on the +/// ROM Options page. +/// @param device Device to read. +/// @param[out] romId Read ROM ID valid when operation is successful. +/// @param[out] manId Read MAN ID valid when operation is successful. +MaximInterfaceDevices_EXPORT Core::error_code +readRomIdAndManId(DS28C40 & device, Core::RomId::span romId, + Core::ManId::span manId); + +/// Format page authentication input data. +class DS28C40::PageAuthenticationData { +public: + typedef Core::array_span<uint_least8_t, Core::RomId::size + 2 * Page::size + + 1 + Core::ManId::size> + Result; + + PageAuthenticationData() : result_() {} + + /// Formatted data result. + Result::const_span result() const { return result_; } + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { + return make_span(result_).subspan<romIdIdx, Core::RomId::size>(); + } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { + return const_cast<PageAuthenticationData &>(*this).romId(); + } + + /// Set ROM ID. + PageAuthenticationData & setRomId(Core::RomId::const_span romId) { + copy(romId, this->romId()); + return *this; + } + + /// Set ROM ID for use in anonymous mode. + MaximInterfaceDevices_EXPORT PageAuthenticationData & setAnonymousRomId(); + + /// @} + + /// @name Page + /// @brief Data from a device memory page. + /// @{ + + /// Get mutable page. + Page::span page() { + return make_span(result_).subspan<pageIdx, Page::size>(); + } + + /// Get immutable page. + Page::const_span page() const { + return const_cast<PageAuthenticationData &>(*this).page(); + } + + /// Set page. + PageAuthenticationData & setPage(Page::const_span page) { + copy(page, this->page()); + return *this; + } + + /// @} + + /// @name Challenge + /// @brief Random challenge used to prevent replay attacks. + /// @{ + + /// Get mutable Challenge. + Page::span challenge() { + return make_span(result_).subspan<challengeIdx, Page::size>(); + } + + /// Get immutable Challenge. + Page::const_span challenge() const { + return const_cast<PageAuthenticationData &>(*this).challenge(); + } + + /// Set Challenge. + PageAuthenticationData & setChallenge(Page::const_span challenge) { + copy(challenge, this->challenge()); + return *this; + } + + /// @} + + /// @name Page number + /// @brief Number of the page to use data from. + /// @{ + + /// Get page number. + int pageNum() const { return result_[pageNumIdx]; } + + /// Set page number. + PageAuthenticationData & setPageNum(int pageNum) { + result_[pageNumIdx] = pageNum; + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get mutable MAN ID. + Core::ManId::span manId() { + return make_span(result_).subspan<manIdIdx, Core::ManId::size>(); + } + + /// Get immutable MAN ID. + Core::ManId::const_span manId() const { + return const_cast<PageAuthenticationData &>(*this).manId(); + } + + /// Set MAN ID. + PageAuthenticationData & setManId(Core::ManId::const_span manId) { + copy(manId, this->manId()); + return *this; + } + + /// @} + +private: + typedef Result::span::index_type index; + + static const index romIdIdx = 0; + static const index pageIdx = romIdIdx + Core::RomId::size; + static const index challengeIdx = pageIdx + Page::size; + static const index pageNumIdx = challengeIdx + Page::size; + static const index manIdIdx = pageNumIdx + 1; + + Result::array result_; +}; + +/// Format authenticated write input data. +class DS28C40::WriteAuthenticationData { +public: + typedef PageAuthenticationData::Result Result; + + WriteAuthenticationData() : data() { setPageNum(0); } + + /// Formatted data result. + Result::const_span result() const { return data.result(); } + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { return data.romId(); } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { return data.romId(); } + + /// Set ROM ID. + WriteAuthenticationData & setRomId(Core::RomId::const_span romId) { + data.setRomId(romId); + return *this; + } + + /// Set ROM ID for use in anonymous mode. + WriteAuthenticationData & setAnonymousRomId() { + data.setAnonymousRomId(); + return *this; + } + + /// @} + + /// @name Old page + /// @brief Existing data contained in the page. + /// @{ + + /// Get mutable old page. + Page::span oldPage() { return data.page(); } + + /// Get immutable old page. + Page::const_span oldPage() const { return data.page(); } + + /// Set old page. + WriteAuthenticationData & setOldPage(Page::const_span oldPage) { + data.setPage(oldPage); + return *this; + } + + /// @} + + /// @name New page + /// @brief New data to write to the page. + /// @{ + + /// Get mutable new page. + Page::span newPage() { return data.challenge(); } + + /// Get immutable new page. + Page::const_span newPage() const { return data.challenge(); } + + /// Set new page. + WriteAuthenticationData & setNewPage(Page::const_span newPage) { + data.setChallenge(newPage); + return *this; + } + + /// @} + + /// @name Page number + /// @brief Page number for write operation. + /// @{ + + /// Get page number. + int pageNum() const { return data.pageNum() & 0x7F; } + + /// Set page number. + WriteAuthenticationData & setPageNum(int pageNum) { + data.setPageNum(pageNum | 0x80); + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get mutable MAN ID. + Core::ManId::span manId() { return data.manId(); } + + /// Get immutable MAN ID. + Core::ManId::const_span manId() const { return data.manId(); } + + /// Set MAN ID. + WriteAuthenticationData & setManId(Core::ManId::const_span manId) { + data.setManId(manId); + return *this; + } + + /// @} + +private: + PageAuthenticationData data; +}; + +/// Format compute secret input data. +class DS28C40::ComputeSecretData { +public: + typedef PageAuthenticationData::Result Result; + + MaximInterfaceDevices_EXPORT ComputeSecretData(); + + /// Formatted data result. + Result::const_span result() const { return data.result(); } + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { return data.romId(); } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { return data.romId(); } + + /// Set ROM ID. + ComputeSecretData & setRomId(Core::RomId::const_span romId) { + data.setRomId(romId); + return *this; + } + + /// @} + + /// @name Binding Data + /// @brief Binding Data contained in the selected page. + /// @{ + + /// Get mutable Binding Data. + Page::span bindingData() { return data.page(); } + + /// Get immutable Binding Data. + Page::const_span bindingData() const { return data.page(); } + + /// Set Binding Data. + ComputeSecretData & setBindingData(Page::const_span bindingData) { + data.setPage(bindingData); + return *this; + } + + /// @} + + /// @name Partial Secret + /// @brief Partial Secret used for customization. + /// @{ + + /// Get mutable Partial Secret. + Page::span partialSecret() { return data.challenge(); } + + /// Get immutable Partial Secret. + Page::const_span partialSecret() const { return data.challenge(); } + + /// Set Partial Secret. + ComputeSecretData & setPartialSecret(Page::const_span partialSecret) { + data.setChallenge(partialSecret); + return *this; + } + + /// @} + + /// @name Page number + /// @brief Page number for Binding Data. + /// @{ + + /// Get page number. + int pageNum() const { return data.pageNum() & 0x3F; } + + /// Set page number. + ComputeSecretData & setPageNum(int pageNum) { + data.setPageNum(pageNum | 0xC0); + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get immutable MAN ID. + Core::ManId::const_span manId() const { return data.manId(); } + + /// Set MAN ID. + MaximInterfaceDevices_EXPORT ComputeSecretData & + setManId(Core::ManId::const_span manId); + + /// @} + +private: + PageAuthenticationData data; +}; + +/// Format decryption HMAC input data. +class DS28C40::DecryptionHmacData { +public: + typedef Core::array_span<uint_least8_t, EncryptionChallenge::size + + Core::RomId::size + 1 + + Core::ManId::size> + Result; + + DecryptionHmacData() : result_() {} + + /// Formatted data result. + Result::const_span result() const { return result_; } + + /// @name Encryption Challenge + /// @brief Random challenge used to prevent replay attacks. + /// @{ + + /// Get mutable Encryption Challenge. + EncryptionChallenge::span encryptionChallenge() { + return make_span(result_) + .subspan<encryptionChallengeIdx, EncryptionChallenge::size>(); + } + + /// Get immutable Encryption Challenge. + EncryptionChallenge::const_span encryptionChallenge() const { + return const_cast<DecryptionHmacData &>(*this).encryptionChallenge(); + } + + /// Set Encryption Challenge. + DecryptionHmacData & + setEncryptionChallenge(EncryptionChallenge::const_span encryptionChallenge) { + copy(encryptionChallenge, this->encryptionChallenge()); + return *this; + } + + /// @} + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { + return make_span(result_).subspan<romIdIdx, Core::RomId::size>(); + } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { + return const_cast<DecryptionHmacData &>(*this).romId(); + } + + /// Set ROM ID. + DecryptionHmacData & setRomId(Core::RomId::const_span romId) { + copy(romId, this->romId()); + return *this; + } + + /// Set ROM ID for use in anonymous mode. + MaximInterfaceDevices_EXPORT DecryptionHmacData & setAnonymousRomId(); + + /// @} + + /// @name Page number + /// @brief Number of the page to use data from. + /// @{ + + /// Get page number. + int pageNum() const { return result_[pageNumIdx]; } + + /// Set page number. + DecryptionHmacData & setPageNum(int pageNum) { + result_[pageNumIdx] = pageNum; + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get mutable MAN ID. + Core::ManId::span manId() { + return make_span(result_).subspan<manIdIdx, Core::ManId::size>(); + } + + /// Get immutable MAN ID. + Core::ManId::const_span manId() const { + return const_cast<DecryptionHmacData &>(*this).manId(); + } + + /// Set MAN ID. + DecryptionHmacData & setManId(Core::ManId::const_span manId) { + copy(manId, this->manId()); + return *this; + } + + /// @} + +private: + typedef Result::span::index_type index; + + static const index encryptionChallengeIdx = 0; + static const index romIdIdx = + encryptionChallengeIdx + EncryptionChallenge::size; + static const index pageNumIdx = romIdIdx + Core::RomId::size; + static const index manIdIdx = pageNumIdx + 1; + + Result::array result_; +}; + +/// Format encryption HMAC input data. +class DS28C40::EncryptionHmacData { +public: + typedef DecryptionHmacData::Result Result; + + EncryptionHmacData() : data() { setPageNum(0); } + + /// Formatted data result. + Result::const_span result() const { return data.result(); } + + /// @name Encryption Challenge + /// @brief Random challenge used to prevent replay attacks. + /// @{ + + /// Get mutable Encryption Challenge. + EncryptionChallenge::span encryptionChallenge() { + return data.encryptionChallenge(); + } + + /// Get immutable Encryption Challenge. + EncryptionChallenge::const_span encryptionChallenge() const { + return data.encryptionChallenge(); + } + + /// Set Encryption Challenge. + EncryptionHmacData & + setEncryptionChallenge(EncryptionChallenge::const_span encryptionChallenge) { + data.setEncryptionChallenge(encryptionChallenge); + return *this; + } + + /// @} + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { return data.romId(); } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { return data.romId(); } + + /// Set ROM ID. + EncryptionHmacData & setRomId(Core::RomId::const_span romId) { + data.setRomId(romId); + return *this; + } + + /// Set ROM ID for use in anonymous mode. + EncryptionHmacData & setAnonymousRomId() { + data.setAnonymousRomId(); + return *this; + } + + /// @} + + /// @name Page number + /// @brief Number of the page to use data from. + /// @{ + + /// Get page number. + int pageNum() const { return data.pageNum() & 0x7F; } + + /// Set page number. + EncryptionHmacData & setPageNum(int pageNum) { + data.setPageNum(pageNum | 0x80); + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get mutable MAN ID. + Core::ManId::span manId() { return data.manId(); } + + /// Get immutable MAN ID. + Core::ManId::const_span manId() const { return data.manId(); } + + /// Set MAN ID. + EncryptionHmacData & setManId(Core::ManId::const_span manId) { + data.setManId(manId); + return *this; + } + + /// @} + +private: + DecryptionHmacData data; +}; + +/// Access fields in the ROM Options page. +class DS28C40::RomOptions { +public: + explicit RomOptions(Page::span page) : page(page) {} + + bool anonymous() const { return page[anonymousIdx] == anonymousValue; } + + void setAnonymous(bool anonymous) { + page[anonymousIdx] = (anonymous ? anonymousValue : 0); + } + + Core::ManId::const_span manId() const { + return page.subspan<22, Core::ManId::size>(); + } + + Core::RomId::const_span romId() const { + return page.subspan<24, Core::RomId::size>(); + } + +private: + static const Page::span::index_type anonymousIdx = 1; + static const Page::span::value_type anonymousValue = 0xAA; + + Page::span page; +}; + +/// Access fields in the GPIO Control page. +class DS28C40::GpioControl { +public: + explicit GpioControl(Page::span page) : page(page) {} + + bool conducting() const { return page[conductingIdx] == conductingValue; } + + void setConducting(bool conducting) { + page[conductingIdx] = (conducting ? conductingValue : 0x55); + } + + bool level() const { return page[2] == 0x55; } + +private: + static const Page::span::index_type conductingIdx = 0; + static const Page::span::value_type conductingValue = 0xAA; + + Page::span page; +}; + +} // namespace MaximInterfaceDevices + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS28E15_22_25.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,653 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include <algorithm> +#include <MaximInterfaceCore/crc.hpp> +#include <MaximInterfaceCore/Error.hpp> +#include "DS28E15_22_25.hpp" + +namespace MaximInterfaceDevices { + +using namespace Core; +using std::copy; + +static const int shaComputationDelayMs = 3; +static const int eepromWriteDelayMs = 10; +static inline int secretEepromWriteDelayMs(bool lowPower) { + return lowPower ? 200 : 100; +} + +static const int ds28e22_25_pagesPerBlock = 2; + +static error_code +writeDataWithCrc(OneWireMaster & master, span<const uint_least8_t> data, + OneWireMaster::Level level = OneWireMaster::NormalLevel, + uint_fast16_t crcStart = 0) { + error_code result = master.writeBlock(data); + if (result) { + return result; + } + uint_least8_t response[2]; + result = master.readByte(response[0]); + if (result) { + return result; + } + result = master.readByteSetLevel(response[1], level); + if (result) { + return result; + } + if (calculateCrc16(calculateCrc16(crcStart, data), response) != 0xB001) { + result = make_error_code(DS28E15_22_25::CrcError); + } + return result; +} + +const int DS28E15_22_25::segmentsPerPage; + +DS28E15_22_25::AuthenticationData & +DS28E15_22_25::AuthenticationData::setAnonymousRomId() { + std::fill(romId().begin(), romId().end(), 0xFF); + return *this; +} + +error_code +DS28E15_22_25::writeCommandWithCrc(Command command, uint_least8_t parameter, + OneWireMaster::Level level) const { + error_code result = selectRom(*master); + if (!result) { + const uint_least8_t data[] = {static_cast<uint_least8_t>(command), + parameter}; + result = writeDataWithCrc(*master, data, level); + } + return result; +} + +static error_code readDataWithCrc(OneWireMaster & master, + span<uint_least8_t> data) { + error_code result = master.readBlock(data); + if (result) { + return result; + } + uint_least8_t response[2]; + result = master.readBlock(response); + if (result) { + return result; + } + if (calculateCrc16(calculateCrc16(data), response) != 0xB001) { + result = make_error_code(DS28E15_22_25::CrcError); + } + return result; +} + +static error_code readCsByte(OneWireMaster & master) { + uint_least8_t response; + error_code result = master.readByte(response); + if (result) { + return result; + } + if (response != 0xAA) { + result = make_error_code(DS28E15_22_25::OperationFailure); + } + return result; +} + +static error_code releaseSequence(OneWireMaster & master, Sleep & sleep, + int delayTimeMs) { + error_code result = master.writeBytePower(0xAA); + if (result) { + return result; + } + sleep(delayTimeMs); + result = master.setLevel(OneWireMaster::NormalLevel); + if (result) { + return result; + } + return readCsByte(master); +} + +DS28E15_22_25::BlockProtection & +DS28E15_22_25::BlockProtection::setBlockNum(int blockNum) { + status &= ~blockNumMask; + status |= (blockNum & blockNumMask); + return *this; +} + +bool DS28E15_22_25::BlockProtection::noProtection() const { + return !readProtection() && !writeProtection() && !eepromEmulation() && + !authProtection(); +} + +DS28E15_22_25::BlockProtection & +DS28E15_22_25::BlockProtection::setReadProtection(bool readProtection) { + if (readProtection) { + status |= readProtectionMask; + } else { + status &= ~readProtectionMask; + } + return *this; +} + +DS28E15_22_25::BlockProtection & +DS28E15_22_25::BlockProtection::setWriteProtection(bool writeProtection) { + if (writeProtection) { + status |= writeProtectionMask; + } else { + status &= ~writeProtectionMask; + } + return *this; +} + +DS28E15_22_25::BlockProtection & +DS28E15_22_25::BlockProtection::setEepromEmulation(bool eepromEmulation) { + if (eepromEmulation) { + status |= eepromEmulationMask; + } else { + status &= ~eepromEmulationMask; + } + return *this; +} + +DS28E15_22_25::BlockProtection & +DS28E15_22_25::BlockProtection::setAuthProtection(bool authProtection) { + if (authProtection) { + status |= authProtectionMask; + } else { + status &= ~authProtectionMask; + } + return *this; +} + +DS28E15_22_25::ProtectionWriteMacData::ProtectionWriteMacData() + : result_(), oldProtection_(), newProtection_() { + setOldProtection(oldProtection_); + setNewProtection(newProtection_); +} + +DS28E15_22_25::ProtectionWriteMacData & +DS28E15_22_25::ProtectionWriteMacData::setOldProtection( + BlockProtection oldProtection) { + result_[oldProtectionIdx] = oldProtection.authProtection() ? 1 : 0; + result_[oldProtectionIdx + 1] = oldProtection.eepromEmulation() ? 1 : 0; + result_[oldProtectionIdx + 2] = oldProtection.writeProtection() ? 1 : 0; + result_[oldProtectionIdx + 3] = oldProtection.readProtection() ? 1 : 0; + oldProtection_ = oldProtection; + return *this; +} + +DS28E15_22_25::ProtectionWriteMacData & +DS28E15_22_25::ProtectionWriteMacData::setNewProtection( + BlockProtection newProtection) { + result_[blockNumIdx] = newProtection.blockNum(); + result_[newProtectionIdx] = newProtection.authProtection() ? 1 : 0; + result_[newProtectionIdx + 1] = newProtection.eepromEmulation() ? 1 : 0; + result_[newProtectionIdx + 2] = newProtection.writeProtection() ? 1 : 0; + result_[newProtectionIdx + 3] = newProtection.readProtection() ? 1 : 0; + newProtection_ = newProtection; + return *this; +} + +error_code +DS28E15_22_25::writeAuthBlockProtection(BlockProtection newProtection, + Page::const_span mac) { + error_code result = + writeCommandWithCrc(AuthWriteBlockProtection, newProtection.statusByte(), + OneWireMaster::StrongLevel); + if (result) { + return result; + } + + sleep->invoke(shaComputationDelayMs); + result = master->setLevel(OneWireMaster::NormalLevel); + if (result) { + return result; + } + + result = writeDataWithCrc(*master, mac); + if (result) { + return result; + } + + result = readCsByte(*master); + if (result) { + return result; + } + + result = releaseSequence(*master, *sleep, eepromWriteDelayMs); + return result; +} + +error_code DS28E15_22_25::writeBlockProtection(BlockProtection protection) { + error_code result = + writeCommandWithCrc(WriteBlockProtection, protection.statusByte()); + if (result) { + return result; + } + + result = releaseSequence(*master, *sleep, eepromWriteDelayMs); + return result; +} + +error_code DS28E15_22_25::doReadBlockProtection(int blockNum, + BlockProtection & protection, + Variant variant) const { + uint_least8_t buffer = blockNum; + if (variant == DS28E22 || variant == DS28E25) { + buffer *= ds28e22_25_pagesPerBlock; + } + error_code result = writeCommandWithCrc(ReadStatus, buffer); + if (!result) { + result = master->readByte(buffer); + if (!result) { + protection.setStatusByte(buffer); + } + } + return result; +} + +error_code DS28E15_22_25::computeReadPageMac(int page_num, bool anon, + Page::span mac) const { + error_code result = + writeCommandWithCrc(ComputePageMac, (anon ? 0xE0 : 0x00) | page_num, + OneWireMaster::StrongLevel); + if (result) { + return result; + } + + sleep->invoke(shaComputationDelayMs * 2); + result = master->setLevel(OneWireMaster::NormalLevel); + if (result) { + return result; + } + + result = readCsByte(*master); + if (result) { + return result; + } + + result = readDataWithCrc(*master, mac); + return result; +} + +error_code DS28E15_22_25::doComputeSecret(int page_num, bool lock, + bool lowPower) { + error_code result = writeCommandWithCrc(ComputeAndLockSecret, + lock ? (0xE0 | page_num) : page_num); + if (result) { + return result; + } + + result = releaseSequence(*master, *sleep, + shaComputationDelayMs * 2 + + secretEepromWriteDelayMs(lowPower)); + return result; +} + +error_code DS28E15_22_25::doWriteScratchpad(Page::const_span data, + Variant variant) { + const uint_least8_t parameter = + (variant == DS28E22 || variant == DS28E25) ? 0x20 : 0x00; + error_code result = writeCommandWithCrc(ReadWriteScratchpad, parameter); + if (result) { + return result; + } + + result = writeDataWithCrc(*master, data); + return result; +} + +error_code DS28E15_22_25::doReadScratchpad(Page::span data, + Variant variant) const { + const uint_least8_t parameter = + (variant == DS28E22 || variant == DS28E25) ? 0x2F : 0x0F; + error_code result = writeCommandWithCrc(ReadWriteScratchpad, parameter); + if (result) { + return result; + } + + result = readDataWithCrc(*master, data); + return result; +} + +error_code DS28E15_22_25::doLoadSecret(bool lock, bool lowPower) { + error_code result = + writeCommandWithCrc(LoadAndLockSecret, lock ? 0xE0 : 0x00); + if (result) { + return result; + } + + result = releaseSequence(*master, *sleep, secretEepromWriteDelayMs(lowPower)); + return result; +} + +error_code DS28E15_22_25::readPage(int page, Page::span rdbuf) const { + error_code result = writeCommandWithCrc(ReadMemory, page); + if (result) { + return result; + } + + result = continueReadPage(rdbuf); + return result; +} + +error_code DS28E15_22_25::continueReadPage(Page::span rdbuf) const { + return readDataWithCrc(*master, rdbuf); +} + +error_code DS28E15_22_25::doWriteAuthSegment(Segment::const_span newData, + Page::const_span mac, + Variant variant, bool continuing) { + // CRC gets calculated with CS byte when continuing on DS28E22 and DS28E25. + const uint_fast16_t crcStart = + ((variant == DS28E22 || variant == DS28E25) && continuing) + ? calculateCrc16(0xAA) + : 0; + error_code result = + writeDataWithCrc(*master, newData, OneWireMaster::StrongLevel, crcStart); + if (result) { + return result; + } + + sleep->invoke(shaComputationDelayMs); + result = master->setLevel(OneWireMaster::NormalLevel); + if (result) { + return result; + } + + result = writeDataWithCrc(*master, mac); + if (result) { + return result; + } + + result = readCsByte(*master); + if (result) { + return result; + } + + result = releaseSequence(*master, *sleep, eepromWriteDelayMs); + return result; +} + +error_code DS28E15_22_25::doWriteAuthSegment(int pageNum, int segmentNum, + Segment::const_span newData, + Page::const_span mac, + Variant variant) { + error_code result = + writeCommandWithCrc(AuthWriteMemory, (segmentNum << 5) | pageNum); + if (result) { + return result; + } + + result = doWriteAuthSegment(newData, mac, variant, false); + return result; +} + +error_code DS28E15_22_25::doContinueWriteAuthSegment( + Segment::const_span newData, Page::const_span mac, Variant variant) { + return doWriteAuthSegment(newData, mac, variant, true); +} + +error_code DS28E15_22_25::readSegment(int page, int segment, + Segment::span data) const { + error_code result = writeCommandWithCrc(ReadMemory, (segment << 5) | page); + if (result) { + return result; + } + + result = continueReadSegment(data); + return result; +} + +error_code DS28E15_22_25::continueReadSegment(Segment::span data) const { + return master->readBlock(data); +} + +error_code DS28E15_22_25::writeSegment(int page, int block, + Segment::const_span data) { + error_code result = writeCommandWithCrc(WriteMemory, (block << 5) | page); + if (result) { + return result; + } + + result = continueWriteSegment(data); + return result; +} + +error_code DS28E15_22_25::continueWriteSegment(Segment::const_span data) { + error_code result = writeDataWithCrc(*master, data); + if (result) { + return result; + } + + result = releaseSequence(*master, *sleep, eepromWriteDelayMs); + return result; +} + +error_code +DS28E15_22_25::doReadAllBlockProtection(span<BlockProtection> protection, + Variant variant) const { + error_code result = writeCommandWithCrc(ReadStatus, 0); + if (!result) { + if (variant == DS28E22 || variant == DS28E25) { + // Need to read extra data on DS28E22 to get CRC16. + uint_least8_t buf[DS28E25::memoryPages]; + result = readDataWithCrc(*master, buf); + if (!result) { + const int blocks = ((variant == DS28E22) ? DS28E22::memoryPages + : DS28E25::memoryPages) / + ds28e22_25_pagesPerBlock; + for (span<BlockProtection>::index_type i = 0; + i < std::min<span<BlockProtection>::index_type>(protection.size(), + blocks); + ++i) { + protection[i].setStatusByte( + (buf[i * ds28e22_25_pagesPerBlock] & 0xF0) | // Upper nibble + ((buf[i * ds28e22_25_pagesPerBlock] & 0x0F) / + ds28e22_25_pagesPerBlock)); // Lower nibble + } + } + } else { // DS28E15 + uint_least8_t buf[DS28E15::protectionBlocks]; + result = readDataWithCrc(*master, buf); + if (!result) { + for (span<BlockProtection>::index_type i = 0; + i < std::min<span<BlockProtection>::index_type>( + protection.size(), DS28E15::protectionBlocks); + ++i) { + protection[i].setStatusByte(buf[i]); + } + } + } + } + return result; +} + +const error_category & DS28E15_22_25::errorCategory() { + static class : public error_category { + public: + virtual const char * name() const { return "DS28E15_22_25"; } + + virtual std::string message(int condition) const { + switch (condition) { + case CrcError: + return "CRC Error"; + + case OperationFailure: + return "Operation Failure"; + + default: + return defaultErrorMessage(condition); + } + } + } instance; + return instance; +} + +error_code DS28E15_22_25::loadSecret(bool lock) { + // Use worst-case low power timing if the device type is not known. + return doLoadSecret(lock, true); +} + +error_code DS28E15_22_25::computeSecret(int pageNum, bool lock) { + // Use worst-case low power timing if the device type is not known. + return doComputeSecret(pageNum, lock, true); +} + +error_code DS28E15_22_25::readPersonality(Personality & personality) const { + error_code result = writeCommandWithCrc(ReadStatus, 0xE0); + if (!result) { + uint_least8_t data[4]; + result = readDataWithCrc(*master, data); + if (!result) { + personality.PB1 = data[0]; + personality.PB2 = data[1]; + personality.manId[0] = data[2]; + personality.manId[1] = data[3]; + } + } + return result; +} + +const int DS28EL15::memoryPages; +const int DS28EL15::protectionBlocks; + +error_code DS28EL15::writeScratchpad(Page::const_span data) { + return doWriteScratchpad(data, DS28E15); +} + +error_code DS28EL15::readScratchpad(Page::span data) const { + return doReadScratchpad(data, DS28E15); +} + +error_code DS28EL15::readBlockProtection(int blockNum, + BlockProtection & protection) const { + return doReadBlockProtection(blockNum, protection, DS28E15); +} + +error_code DS28EL15::writeAuthSegment(int pageNum, int segmentNum, + Segment::const_span newData, + Page::const_span mac) { + return doWriteAuthSegment(pageNum, segmentNum, newData, mac, DS28E15); +} + +error_code DS28EL15::continueWriteAuthSegment(Segment::const_span newData, + Page::const_span mac) { + return doContinueWriteAuthSegment(newData, mac, DS28E15); +} + +error_code DS28EL15::readAllBlockProtection( + span<BlockProtection, protectionBlocks> protection) const { + return doReadAllBlockProtection(protection, DS28E15); +} + +error_code DS28E15::loadSecret(bool lock) { return doLoadSecret(lock, false); } + +error_code DS28E15::computeSecret(int pageNum, bool lock) { + return doComputeSecret(pageNum, lock, false); +} + +const int DS28EL22::memoryPages; +const int DS28EL22::protectionBlocks; + +error_code DS28EL22::writeScratchpad(Page::const_span data) { + return doWriteScratchpad(data, DS28E22); +} + +error_code DS28EL22::readScratchpad(Page::span data) const { + return doReadScratchpad(data, DS28E22); +} + +error_code DS28EL22::readBlockProtection(int blockNum, + BlockProtection & protection) const { + return doReadBlockProtection(blockNum, protection, DS28E22); +} + +error_code DS28EL22::writeAuthSegment(int pageNum, int segmentNum, + Segment::const_span newData, + Page::const_span mac) { + return doWriteAuthSegment(pageNum, segmentNum, newData, mac, DS28E22); +} + +error_code DS28EL22::continueWriteAuthSegment(Segment::const_span newData, + Page::const_span mac) { + return doContinueWriteAuthSegment(newData, mac, DS28E22); +} + +error_code DS28EL22::readAllBlockProtection( + span<BlockProtection, protectionBlocks> protection) const { + return doReadAllBlockProtection(protection, DS28E22); +} + +error_code DS28E22::loadSecret(bool lock) { return doLoadSecret(lock, false); } + +error_code DS28E22::computeSecret(int pageNum, bool lock) { + return doComputeSecret(pageNum, lock, false); +} + +const int DS28EL25::memoryPages; +const int DS28EL25::protectionBlocks; + +error_code DS28EL25::writeScratchpad(Page::const_span data) { + return doWriteScratchpad(data, DS28E25); +} + +error_code DS28EL25::readScratchpad(Page::span data) const { + return doReadScratchpad(data, DS28E25); +} + +error_code DS28EL25::readBlockProtection(int blockNum, + BlockProtection & protection) const { + return doReadBlockProtection(blockNum, protection, DS28E25); +} + +error_code DS28EL25::writeAuthSegment(int pageNum, int segmentNum, + Segment::const_span newData, + Page::const_span mac) { + return doWriteAuthSegment(pageNum, segmentNum, newData, mac, DS28E25); +} + +error_code DS28EL25::continueWriteAuthSegment(Segment::const_span newData, + Page::const_span mac) { + return doContinueWriteAuthSegment(newData, mac, DS28E25); +} + +error_code DS28EL25::readAllBlockProtection( + span<BlockProtection, protectionBlocks> protection) const { + return doReadAllBlockProtection(protection, DS28E25); +} + +error_code DS28E25::loadSecret(bool lock) { return doLoadSecret(lock, false); } + +error_code DS28E25::computeSecret(int pageNum, bool lock) { + return doComputeSecret(pageNum, lock, false); +} + +} // namespace MaximInterfaceDevices
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS28E15_22_25.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,909 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceDevices_DS28E15_22_25 +#define MaximInterfaceDevices_DS28E15_22_25 + +#include <stdint.h> +#include <MaximInterfaceCore/Algorithm.hpp> +#include <MaximInterfaceCore/array_span.hpp> +#include <MaximInterfaceCore/ManId.hpp> +#include <MaximInterfaceCore/OneWireMaster.hpp> +#include <MaximInterfaceCore/RomId.hpp> +#include <MaximInterfaceCore/SelectRom.hpp> +#include <MaximInterfaceCore/Sleep.hpp> +#include "Config.hpp" + +namespace MaximInterfaceDevices { + +/// @brief +/// Interface to the DS28E15/22/25 series of authenticators +/// including low power variants. +class DS28E15_22_25 { +public: + enum ErrorValue { CrcError = 1, OperationFailure }; + + /// Holds the contents of a device memory segment. + typedef Core::array_span<uint_least8_t, 4> Segment; + + /// Holds the contents of a device memory page. + typedef Core::array_span<uint_least8_t, 32> Page; + + /// Number of segments per page. + static const int segmentsPerPage = Page::size / Segment::size; + + /// Container for the device personality. + struct Personality { + uint_least8_t PB1; + uint_least8_t PB2; + Core::ManId::array manId; + + bool secretLocked() const { return PB2 & 0x01; } + }; + + // Represents the status of a memory protection block. + class BlockProtection; + + // Format data to hash for an Authenticated Write to a memory segment. + class SegmentWriteMacData; + + // Format data to hash for an Authenticated Write to a memory protection block. + class ProtectionWriteMacData; + + // Format data to hash for device authentication or computing the next secret + // from the existing secret. + class AuthenticationData; + + void setSleep(Core::Sleep & sleep) { this->sleep = &sleep; } + + void setMaster(Core::OneWireMaster & master) { this->master = &master; } + + void setSelectRom(const Core::SelectRom & selectRom) { + this->selectRom = selectRom; + } + + // Const member functions should not affect the state of the memory, + // block protection, or secret on the device. + + /// @brief Read memory segment using the Read Memory command on the device. + /// @param pageNum Page number for read operation. + /// @param segmentNum Segment number within page for read operation. + /// @param[out] data Buffer to read data from the segment into. + MaximInterfaceDevices_EXPORT Core::error_code + readSegment(int pageNum, int segmentNum, Segment::span data) const; + + /// @brief Continue an in-progress readSegment operation. + /// @note A CRC16 will encountered after reading the last segment of a page. + /// @param[out] data Buffer to read data from the segment into. + MaximInterfaceDevices_EXPORT Core::error_code + continueReadSegment(Segment::span data) const; + + /// @brief Write memory segment using the Write Memory command. + /// @note 1-Wire ROM selection should have already occurred. + /// @param pageNum Page number for write operation. + /// @param segmentNum Segment number within page for write operation. + /// @param[in] data Data to write to the memory segment. + MaximInterfaceDevices_EXPORT Core::error_code + writeSegment(int pageNum, int segmentNum, Segment::const_span data); + + /// @brief Continue an in-progress Write Memory command. + /// @param[in] data Data to write to the memory segment. + MaximInterfaceDevices_EXPORT Core::error_code + continueWriteSegment(Segment::const_span data); + + /// @brief Read memory page using the Read Memory command on the device. + /// @param pageNum Page number for write operation. + /// @param[out] rdbuf Buffer to read data from the page into. + MaximInterfaceDevices_EXPORT Core::error_code + readPage(int pageNum, Page::span rdbuf) const; + + /// @brief Continue an in-progress readPageOperation. + /// @param[out] rdbuf Buffer to read data from the page into. + MaximInterfaceDevices_EXPORT Core::error_code + continueReadPage(Page::span rdbuf) const; + + /// @brief + /// Perform a Compute Page MAC command on the device. + /// Read back the MAC and verify the CRC16. + /// @param pageNum Page number to use for the computation. + /// @param anon True to compute in anonymous mode where ROM ID is not used. + /// @param[out] mac The device computed MAC. + MaximInterfaceDevices_EXPORT Core::error_code + computeReadPageMac(int pageNum, bool anon, Page::span mac) const; + + /// @brief + /// Update the status of a memory protection block using the + /// Write Page Protection command. + /// @param protection + /// Desired protection status for the block. + /// It is not possible to disable existing protections. + MaximInterfaceDevices_EXPORT Core::error_code + writeBlockProtection(BlockProtection protection); + + /// @brief + /// Update the status of a memory protection block using the + /// Authenticated Write Page Protection command. + /// @param newProtection New protection status to write. + /// @param[in] mac Write MAC computed for this operation. + MaximInterfaceDevices_EXPORT Core::error_code + writeAuthBlockProtection(BlockProtection newProtection, Page::const_span mac); + + /// @brief Perform Load and Lock Secret command on the device. + /// @note The secret should already be stored in the scratchpad on the device. + /// @param lock + /// Prevent further changes to the secret on the device after loading. + MaximInterfaceDevices_EXPORT Core::error_code loadSecret(bool lock); + + /// @brief Perform a Compute and Lock Secret command on the device. + /// @param pageNum Page number to use as the binding data. + /// @param lock + /// Prevent further changes to the secret on the device after computing. + MaximInterfaceDevices_EXPORT Core::error_code computeSecret(int pageNum, + bool lock); + + /// @brief Read the personality bytes using the Read Status command. + /// @param[out] personality Receives personality read from device. + MaximInterfaceDevices_EXPORT Core::error_code + readPersonality(Personality & personality) const; + + MaximInterfaceDevices_EXPORT static const Core::error_category & + errorCategory(); + +protected: + enum Variant { DS28E15, DS28E22, DS28E25 }; + + DS28E15_22_25(Core::Sleep & sleep, Core::OneWireMaster & master, + const Core::SelectRom & selectRom) + : selectRom(selectRom), master(&master), sleep(&sleep) {} + + ~DS28E15_22_25() {} + + Core::error_code doWriteScratchpad(Page::const_span data, Variant variant); + + Core::error_code doReadScratchpad(Page::span data, Variant variant) const; + + Core::error_code doReadBlockProtection(int blockNum, + BlockProtection & protection, + Variant variant) const; + + Core::error_code doWriteAuthSegment(int pageNum, int segmentNum, + Segment::const_span newData, + Page::const_span mac, Variant variant); + + Core::error_code doContinueWriteAuthSegment(Segment::const_span newData, + Page::const_span mac, + Variant variant); + + Core::error_code + doReadAllBlockProtection(Core::span<BlockProtection> protection, + Variant variant) const; + + Core::error_code doLoadSecret(bool lock, bool lowPower); + + Core::error_code doComputeSecret(int pageNum, bool lock, bool lowPower); + +private: + enum Command { + WriteMemory = 0x55, + ReadMemory = 0xF0, + LoadAndLockSecret = 0x33, + ComputeAndLockSecret = 0x3C, + ReadWriteScratchpad = 0x0F, + ComputePageMac = 0xA5, + ReadStatus = 0xAA, + WriteBlockProtection = 0xC3, + AuthWriteMemory = 0x5A, + AuthWriteBlockProtection = 0xCC, + }; + + Core::error_code doWriteAuthSegment(Segment::const_span newData, + Page::const_span mac, Variant variant, + bool continuing); + + Core::error_code + writeCommandWithCrc(Command command, uint_least8_t parameter, + Core::OneWireMaster::Level level = + Core::OneWireMaster::NormalLevel) const; + + Core::SelectRom selectRom; + Core::OneWireMaster * master; + Core::Sleep * sleep; +}; + +inline Core::error_code make_error_code(DS28E15_22_25::ErrorValue e) { + return Core::error_code(e, DS28E15_22_25::errorCategory()); +} + +/// Interface to the DS28EL15 (low power) authenticator. +class DS28EL15 : public DS28E15_22_25 { +public: + // DS28E15_22_25 traits + static const int memoryPages = 2; + static const int protectionBlocks = 4; + + DS28EL15(Core::Sleep & sleep, Core::OneWireMaster & master, + const Core::SelectRom & selectRom) + : DS28E15_22_25(sleep, master, selectRom) {} + + /// @brief Perform Write Scratchpad operation on the device. + /// @param[in] data Data to write to the scratchpad. + MaximInterfaceDevices_EXPORT Core::error_code + writeScratchpad(Page::const_span data); + + /// @brief Perform a Read Scratchpad operation on the device. + /// @param[out] data Buffer to read data from the scratchpad into. + MaximInterfaceDevices_EXPORT Core::error_code + readScratchpad(Page::span data) const; + + /// @brief + /// Read the status of a memory protection block using the Read Status command. + /// @param blockNum Block number to to read status of. + /// @param[out] protection Receives protection status read from device. + MaximInterfaceDevices_EXPORT Core::error_code + readBlockProtection(int blockNum, BlockProtection & protection) const; + + /// @brief Write memory segment using the Authenticated Write Memory command. + /// @param pageNum Page number for write operation. + /// @param segmentNum Segment number within page for write operation. + /// @param[in] newData New data to write to the segment. + /// @param[in] mac Write MAC computed for this operation. + MaximInterfaceDevices_EXPORT Core::error_code + writeAuthSegment(int pageNum, int segmentNum, Segment::const_span newData, + Page::const_span mac); + + /// @brief Continue an in-progress Authenticated Write Memory command. + /// @param[in] newData New data to write to the segment. + /// @param[in] mac Write MAC computed for this operation. + MaximInterfaceDevices_EXPORT Core::error_code + continueWriteAuthSegment(Segment::const_span newData, Page::const_span mac); + + /// @brief + /// Read the status of all memory protection blocks using the Read Status command. + /// @param[out] protection Receives protection statuses read from device. + MaximInterfaceDevices_EXPORT Core::error_code readAllBlockProtection( + Core::span<BlockProtection, protectionBlocks> protection) const; +}; + +/// Interface to the DS28E15 authenticator. +class DS28E15 : public DS28EL15 { +public: + DS28E15(Core::Sleep & sleep, Core::OneWireMaster & master, + const Core::SelectRom & selectRom) + : DS28EL15(sleep, master, selectRom) {} + + /// @brief Perform Load and Lock Secret command on the device. + /// @note The secret should already be stored in the scratchpad on the device. + /// @param lock + /// Prevent further changes to the secret on the device after loading. + MaximInterfaceDevices_EXPORT Core::error_code loadSecret(bool lock); + + /// @brief Perform a Compute and Lock Secret command on the device. + /// @param pageNum Page number to use as the binding data. + /// @param lock + /// Prevent further changes to the secret on the device after computing. + MaximInterfaceDevices_EXPORT Core::error_code computeSecret(int pageNum, + bool lock); +}; + +/// Interface to the DS28EL22 (low power) authenticator. +class DS28EL22 : public DS28E15_22_25 { +public: + // DS28E15_22_25 traits + static const int memoryPages = 8; + static const int protectionBlocks = 4; + + DS28EL22(Core::Sleep & sleep, Core::OneWireMaster & master, + const Core::SelectRom & selectRom) + : DS28E15_22_25(sleep, master, selectRom) {} + + /// @brief Perform Write Scratchpad operation on the device. + /// @param[in] data Data to write to the scratchpad. + MaximInterfaceDevices_EXPORT Core::error_code + writeScratchpad(Page::const_span data); + + /// @brief Perform a Read Scratchpad operation on the device. + /// @param[out] data Buffer to read data from the scratchpad into. + MaximInterfaceDevices_EXPORT Core::error_code + readScratchpad(Page::span data) const; + + /// @brief + /// Read the status of a memory protection block using the Read Status command. + /// @param blockNum Block number to to read status of. + /// @param[out] protection Receives protection status read from device. + MaximInterfaceDevices_EXPORT Core::error_code + readBlockProtection(int blockNum, BlockProtection & protection) const; + + /// @brief Write memory segment using the Authenticated Write Memory command. + /// @param pageNum Page number for write operation. + /// @param segmentNum Segment number within page for write operation. + /// @param[in] newData New data to write to the segment. + /// @param[in] mac Write MAC computed for this operation. + MaximInterfaceDevices_EXPORT Core::error_code + writeAuthSegment(int pageNum, int segmentNum, Segment::const_span newData, + Page::const_span mac); + + /// @brief Continue an in-progress Authenticated Write Memory command. + /// @param[in] newData New data to write to the segment. + /// @param[in] mac Write MAC computed for this operation. + MaximInterfaceDevices_EXPORT Core::error_code + continueWriteAuthSegment(Segment::const_span newData, Page::const_span mac); + + /// @brief + /// Read the status of all memory protection blocks using the Read Status command. + /// @param[out] protection Receives protection statuses read from device. + MaximInterfaceDevices_EXPORT Core::error_code readAllBlockProtection( + Core::span<BlockProtection, protectionBlocks> protection) const; +}; + +/// Interface to the DS28E22 authenticator. +class DS28E22 : public DS28EL22 { +public: + DS28E22(Core::Sleep & sleep, Core::OneWireMaster & master, + const Core::SelectRom & selectRom) + : DS28EL22(sleep, master, selectRom) {} + + /// @brief Perform Load and Lock Secret command on the device. + /// @note The secret should already be stored in the scratchpad on the device. + /// @param lock + /// Prevent further changes to the secret on the device after loading. + MaximInterfaceDevices_EXPORT Core::error_code loadSecret(bool lock); + + /// @brief Perform a Compute and Lock Secret command on the device. + /// @param pageNum Page number to use as the binding data. + /// @param lock + /// Prevent further changes to the secret on the device after computing. + MaximInterfaceDevices_EXPORT Core::error_code computeSecret(int pageNum, + bool lock); +}; + +/// Interface to the DS28EL25 (low power) authenticator. +class DS28EL25 : public DS28E15_22_25 { +public: + // DS28E15_22_25 traits + static const int memoryPages = 16; + static const int protectionBlocks = 8; + + DS28EL25(Core::Sleep & sleep, Core::OneWireMaster & master, + const Core::SelectRom & selectRom) + : DS28E15_22_25(sleep, master, selectRom) {} + + /// @brief Perform Write Scratchpad operation on the device. + /// @param[in] data Data to write to the scratchpad. + MaximInterfaceDevices_EXPORT Core::error_code + writeScratchpad(Page::const_span data); + + /// @brief Perform a Read Scratchpad operation on the device. + /// @param[out] data Buffer to read data from the scratchpad into. + MaximInterfaceDevices_EXPORT Core::error_code + readScratchpad(Page::span data) const; + + /// @brief + /// Read the status of a memory protection block using the Read Status command. + /// @param blockNum Block number to to read status of. + /// @param[out] protection Receives protection status read from device. + MaximInterfaceDevices_EXPORT Core::error_code + readBlockProtection(int blockNum, BlockProtection & protection) const; + + /// Write memory segment using the Authenticated Write Memory command. + /// @param pageNum Page number for write operation. + /// @param segmentNum Segment number within page for write operation. + /// @param[in] newData New data to write to the segment. + /// @param[in] mac Write MAC computed for this operation. + MaximInterfaceDevices_EXPORT Core::error_code + writeAuthSegment(int pageNum, int segmentNum, Segment::const_span newData, + Page::const_span mac); + + /// @brief Continue an in-progress Authenticated Write Memory command. + /// @param[in] newData New data to write to the segment. + /// @param[in] mac Write MAC computed for this operation. + MaximInterfaceDevices_EXPORT Core::error_code + continueWriteAuthSegment(Segment::const_span newData, Page::const_span mac); + + /// @brief + /// Read the status of all memory protection blocks using the Read Status command. + /// @param[out] protection Receives protection statuses read from device. + MaximInterfaceDevices_EXPORT Core::error_code readAllBlockProtection( + Core::span<BlockProtection, protectionBlocks> protection) const; +}; + +/// Interface to the DS28E25 authenticator. +class DS28E25 : public DS28EL25 { +public: + DS28E25(Core::Sleep & sleep, Core::OneWireMaster & master, + const Core::SelectRom & selectRom) + : DS28EL25(sleep, master, selectRom) {} + + /// @brief Perform Load and Lock Secret command on the device. + /// @note The secret should already be stored in the scratchpad on the device. + /// @param lock Prevent further changes to the secret on the device after loading. + MaximInterfaceDevices_EXPORT Core::error_code loadSecret(bool lock); + + /// @brief Perform a Compute and Lock Secret command on the device. + /// @param pageNum Page number to use as the binding data. + /// @param lock + /// Prevent further changes to the secret on the device after computing. + MaximInterfaceDevices_EXPORT Core::error_code computeSecret(int pageNum, + bool lock); +}; + +/// Represents the status of a memory protection block. +class DS28E15_22_25::BlockProtection { +public: + explicit BlockProtection(uint_least8_t status = 0x00) : status(status) {} + + /// Get the byte representation used by the device. + uint_least8_t statusByte() const { return status; } + + /// Set the byte representation used by the device. + BlockProtection & setStatusByte(uint_least8_t status) { + this->status = status; + return *this; + } + + /// Get the Block Number which is indexed from zero. + int blockNum() const { return (status & blockNumMask); } + + /// Set the Block Number which is indexed from zero. + MaximInterfaceDevices_EXPORT BlockProtection & setBlockNum(int blockNum); + + /// @brief Get the Read Protection status. + /// @returns True if Read Protection is enabled. + bool readProtection() const { + return ((status & readProtectionMask) == readProtectionMask); + } + + /// Set the Read Protection status. + MaximInterfaceDevices_EXPORT BlockProtection & + setReadProtection(bool readProtection); + + /// @brief Get the Write Protection status. + /// @returns True if Write Protection is enabled. + bool writeProtection() const { + return ((status & writeProtectionMask) == writeProtectionMask); + } + + /// Set the Write Protection status. + MaximInterfaceDevices_EXPORT BlockProtection & + setWriteProtection(bool writeProtection); + + /// @brief Get the EEPROM Emulation Mode status. + /// @returns True if EEPROM Emulation Mode is enabled. + bool eepromEmulation() const { + return ((status & eepromEmulationMask) == eepromEmulationMask); + } + + /// Set the EEPROM Emulation Mode status. + MaximInterfaceDevices_EXPORT BlockProtection & + setEepromEmulation(bool eepromEmulation); + + /// @brief Get the Authentication Protection status. + /// @returns True if Authentication Protection is enabled. + bool authProtection() const { + return ((status & authProtectionMask) == authProtectionMask); + } + + /// Set the Authentication Protection status. + MaximInterfaceDevices_EXPORT BlockProtection & + setAuthProtection(bool authProtection); + + /// @brief Check if no protection options are enabled. + /// @returns True if no protection options are enabled. + MaximInterfaceDevices_EXPORT bool noProtection() const; + +private: + static const unsigned int readProtectionMask = 0x80, + writeProtectionMask = 0x40, + eepromEmulationMask = 0x20, + authProtectionMask = 0x10, blockNumMask = 0x0F; + uint_least8_t status; +}; + +inline bool operator==(DS28E15_22_25::BlockProtection lhs, + DS28E15_22_25::BlockProtection rhs) { + return lhs.statusByte() == rhs.statusByte(); +} + +inline bool operator!=(DS28E15_22_25::BlockProtection lhs, + DS28E15_22_25::BlockProtection rhs) { + return !operator==(lhs, rhs); +} + +/// Format data to hash for an Authenticated Write to a memory segment. +class DS28E15_22_25::SegmentWriteMacData { +public: + typedef Core::array_span<uint_least8_t, 20> Result; + + SegmentWriteMacData() : result_() {} + + /// Formatted data result. + Result::const_span result() const { return result_; } + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { + return make_span(result_).subspan<romIdIdx, Core::RomId::size>(); + } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { + return const_cast<SegmentWriteMacData &>(*this).romId(); + } + + /// Set ROM ID. + SegmentWriteMacData & setRomId(Core::RomId::const_span romId) { + copy(romId, this->romId()); + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get mutable MAN ID. + Core::ManId::span manId() { + return make_span(result_).subspan<manIdIdx, Core::ManId::size>(); + } + + /// Get immutable MAN ID. + Core::ManId::const_span manId() const { + return const_cast<SegmentWriteMacData &>(*this).manId(); + } + + /// Set MAN ID. + SegmentWriteMacData & setManId(Core::ManId::const_span manId) { + copy(manId, this->manId()); + return *this; + } + + /// @} + + /// @name Page number + /// @brief Page number for write operation. + /// @{ + + /// Get page number. + int pageNum() const { return result_[pageNumIdx]; } + + /// Set page number. + SegmentWriteMacData & setPageNum(int pageNum) { + result_[pageNumIdx] = pageNum; + return *this; + } + + /// @} + + /// @name Segment number + /// @brief Segment number within page for write operation. + /// @{ + + /// Get segment number. + int segmentNum() const { return result_[segmentNumIdx]; } + + /// Set segment number. + SegmentWriteMacData & setSegmentNum(int segmentNum) { + result_[segmentNumIdx] = segmentNum; + return *this; + } + + /// @} + + /// @name Old data + /// @brief Existing data contained in the segment. + /// @{ + + /// Get mutable old data. + Segment::span oldData() { + return make_span(result_).subspan<oldDataIdx, Segment::size>(); + } + + /// Get immutable old data. + Segment::const_span oldData() const { + return const_cast<SegmentWriteMacData &>(*this).oldData(); + } + + /// Set old data. + SegmentWriteMacData & setOldData(Segment::const_span oldData) { + copy(oldData, this->oldData()); + return *this; + } + + /// @} + + /// @name New data + /// @brief New data to write to the segment. + /// @{ + + /// Get mutable new data. + Segment::span newData() { + return make_span(result_).subspan<newDataIdx, Segment::size>(); + } + + /// Get immutable new data. + Segment::const_span newData() const { + return const_cast<SegmentWriteMacData &>(*this).newData(); + } + + /// Set new data. + SegmentWriteMacData & setNewData(Segment::const_span newData) { + copy(newData, this->newData()); + return *this; + } + + /// @} + +private: + typedef Result::span::index_type index; + + static const index romIdIdx = 0; + static const index manIdIdx = romIdIdx + Core::RomId::size; + static const index pageNumIdx = manIdIdx + Core::ManId::size; + static const index segmentNumIdx = pageNumIdx + 1; + static const index oldDataIdx = segmentNumIdx + 1; + static const index newDataIdx = oldDataIdx + Segment::size; + + Result::array result_; +}; + +/// Format data to hash for an Authenticated Write to a memory protection block. +class DS28E15_22_25::ProtectionWriteMacData { +public: + typedef Core::array_span<uint_least8_t, 20> Result; + + MaximInterfaceDevices_EXPORT ProtectionWriteMacData(); + + /// Formatted data result. + Result::const_span result() const { return result_; } + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { + return make_span(result_).subspan<romIdIdx, Core::RomId::size>(); + } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { + return const_cast<ProtectionWriteMacData &>(*this).romId(); + } + + /// Set ROM ID. + ProtectionWriteMacData & setRomId(Core::RomId::const_span romId) { + copy(romId, this->romId()); + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get mutable MAN ID. + Core::ManId::span manId() { + return make_span(result_).subspan<manIdIdx, Core::ManId::size>(); + } + + /// Get immutable MAN ID. + Core::ManId::const_span manId() const { + return const_cast<ProtectionWriteMacData &>(*this).manId(); + } + + /// Set MAN ID. + ProtectionWriteMacData & setManId(Core::ManId::const_span manId) { + copy(manId, this->manId()); + return *this; + } + + /// @} + + /// @name Old protection + /// @brief Existing protection status in device. + /// @{ + + /// Get old protection. + BlockProtection oldProtection() const { return oldProtection_; } + + /// Set old protection. + MaximInterfaceDevices_EXPORT ProtectionWriteMacData & + setOldProtection(BlockProtection oldProtection); + + /// @} + + /// @name New protection + /// @brief New protection status to write. + /// @{ + + /// Get new protection. + BlockProtection newProtection() const { return newProtection_; } + + /// Set new protection. + MaximInterfaceDevices_EXPORT ProtectionWriteMacData & + setNewProtection(BlockProtection newProtection); + + /// @} + +private: + typedef Result::span::index_type index; + + static const index romIdIdx = 0; + static const index manIdIdx = romIdIdx + Core::RomId::size; + static const index blockNumIdx = manIdIdx + Core::ManId::size; + static const index oldProtectionIdx = blockNumIdx + 2; + static const index newProtectionIdx = oldProtectionIdx + 4; + + Result::array result_; + BlockProtection oldProtection_; + BlockProtection newProtection_; +}; + +/// @brief +/// Format data to hash for device authentication or computing the next secret +/// from the existing secret. +class DS28E15_22_25::AuthenticationData { +public: + typedef Core::array_span<uint_least8_t, 76> Result; + + AuthenticationData() : result_() {} + + /// Formatted data result. + Result::const_span result() const { return result_; } + + /// @name Page + /// @brief Data from a device memory page. + /// @{ + + /// Get mutable page. + Page::span page() { + return make_span(result_).subspan<pageIdx, Page::size>(); + } + + /// Get immutable page. + Page::const_span page() const { + return const_cast<AuthenticationData &>(*this).page(); + } + + /// Set page. + AuthenticationData & setPage(Page::const_span page) { + copy(page, this->page()); + return *this; + } + + /// @} + + /// @name Scratchpad + /// @brief + /// Data from device scratchpad used as a random challenge in device + /// authentication and a partial secret in secret computation. + /// @{ + + /// Get mutable scratchpad. + Page::span scratchpad() { + return make_span(result_).subspan<scratchpadIdx, Page::size>(); + } + + /// Get immutable scratchpad. + Page::const_span scratchpad() const { + return const_cast<AuthenticationData &>(*this).scratchpad(); + } + + /// Set scratchpad. + AuthenticationData & setScratchpad(Page::const_span scratchpad) { + copy(scratchpad, this->scratchpad()); + return *this; + } + + /// @} + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { + return make_span(result_).subspan<romIdIdx, Core::RomId::size>(); + } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { + return const_cast<AuthenticationData &>(*this).romId(); + } + + /// Set ROM ID. + AuthenticationData & setRomId(Core::RomId::const_span romId) { + copy(romId, this->romId()); + return *this; + } + + /// Set ROM ID for use in anonymous mode. + MaximInterfaceDevices_EXPORT AuthenticationData & setAnonymousRomId(); + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get mutable MAN ID. + Core::ManId::span manId() { + return make_span(result_).subspan<manIdIdx, Core::ManId::size>(); + } + + /// Get immutable MAN ID. + Core::ManId::const_span manId() const { + return const_cast<AuthenticationData &>(*this).manId(); + } + + /// Set MAN ID. + AuthenticationData & setManId(Core::ManId::const_span manId) { + copy(manId, this->manId()); + return *this; + } + + /// @} + + /// @name Page number + /// @brief Number of the page to use data from. + /// @{ + + /// Get page number. + int pageNum() const { return result_[pageNumIdx]; } + + /// Set page number. + AuthenticationData & setPageNum(int pageNum) { + result_[pageNumIdx] = pageNum; + return *this; + } + + /// @} + +private: + typedef Result::span::index_type index; + + static const index pageIdx = 0; + static const index scratchpadIdx = pageIdx + Page::size; + static const index romIdIdx = scratchpadIdx + Page::size; + static const index manIdIdx = romIdIdx + Core::RomId::size; + static const index pageNumIdx = manIdIdx + Core::ManId::size; + + Result::array result_; +}; + +} // namespace MaximInterfaceDevices + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS28E16.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,293 @@ +/******************************************************************************* +* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include <stddef.h> +#include <algorithm> +#include <MaximInterfaceCore/Error.hpp> +#include "DS28E16.hpp" + +namespace MaximInterfaceDevices { + +using namespace Core; +using std::copy; +using std::fill; + +static const int readMemoryTimeMs = 5; +static const int writeMemoryTimeMs = 60; +static const int shortWriteMemoryTimeMs = 15; +static const int computationTimeMs = 15; + +const int DS28E16::decrementCounterPage; +const int DS28E16::masterSecretPage; +const int DS28E16::memoryPages; + +error_code DS28E16::writeMemory(int pageNum, Page::const_span page) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t request[2 + Page::size]; + request[0] = 0x96; + request[1] = pageNum; + copy(page.begin(), page.end(), request + 2); + return runCommand(request, writeMemoryTimeMs); +} + +error_code DS28E16::readMemory(int pageNum, Page::span page) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t buffer[1 + Page::size * 2]; + buffer[0] = 0x44; + buffer[1] = pageNum; + span<uint_least8_t> response(buffer); + const error_code result = + runCommand(make_span(buffer, 2), readMemoryTimeMs, response); + if (!result) { + response = response.first(Page::size); + copy(response.begin(), response.end(), page.begin()); + } + return result; +} + +error_code DS28E16::readStatus(Status & status) { + uint_least8_t buffer[1 + Status::PageProtectionList::csize + 2]; + buffer[0] = 0xAA; + span<uint_least8_t> response(buffer); + const error_code result = + runCommand(make_span(buffer, 1), readMemoryTimeMs, response); + if (!result) { + span<uint_least8_t>::const_iterator responseIt = response.begin(); + for (Status::PageProtectionList::iterator it = + status.pageProtection.begin(); + it != status.pageProtection.end(); ++it) { + *it = *responseIt; + ++responseIt; + } + status.manId = *responseIt; + ++responseIt; + status.deviceVersion = *responseIt; + } + return result; +} + +error_code DS28E16::setPageProtection(int pageNum, + const PageProtection & protection) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + const uint_least8_t request[] = { + 0xC3, static_cast<uint_least8_t>(pageNum), + static_cast<uint_least8_t>(protection.to_ulong())}; + return runCommand(request, shortWriteMemoryTimeMs); +} + +error_code +DS28E16::computeAndReadPageAuthentication(int pageNum, bool anonymous, + DoublePage::const_span challenge, + DoublePage::span hmac) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + const size_t requestSize = 3 + DoublePage::size; + const size_t responseSize = 1 + DoublePage::size; + uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)]; + buffer[0] = 0xA5; + buffer[1] = pageNum; + if (anonymous) { + buffer[1] |= 0xE0; + } + buffer[2] = 0x02; + copy(challenge.begin(), challenge.end(), buffer + 3); + span<uint_least8_t> response(buffer, responseSize); + const error_code result = + runCommand(make_span(buffer, requestSize), computationTimeMs, response); + if (!result) { + copy(response.begin(), response.end(), hmac.begin()); + } + return result; +} + +error_code DS28E16::computeSecret(int bindingDataPageNum, + bool constantBindingData, bool anonymous, + DoublePage::const_span partialSecret) { + if (bindingDataPageNum < 0 || bindingDataPageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t request[3 + DoublePage::size]; + request[0] = 0x3C; + request[1] = bindingDataPageNum; + if (constantBindingData) { + request[1] |= 0x04; + } + if (anonymous) { + request[1] |= 0xE0; + } + request[2] = 0x08; + copy(partialSecret.begin(), partialSecret.end(), request + 3); + return runCommand(request, computationTimeMs); +} + +error_code DS28E16::decrementCounter() { + const uint_least8_t request = 0xC9; + return runCommand(make_span(&request, 1), writeMemoryTimeMs); +} + +error_code DS28E16::lockOutDisableDevice() { + const DisableDevicePassword::array password = {}; + return disableDevice(LockOutDisableDevice, password); +} + +error_code +DS28E16::setDisableDevicePassword(DisableDevicePassword::const_span password) { + return disableDevice(SetDisableDevicePassword, password); +} + +error_code DS28E16::disableDevice(DisableDevicePassword::const_span password) { + return disableDevice(DisableDevice, password); +} + +error_code DS28E16::disableDevice(DisableDeviceOperation operation, + DisableDevicePassword::const_span password) { + const uint_least8_t request[] = { + 0x33, static_cast<uint_least8_t>(operation), + password[0], password[1], + 0x71, 0x35, + 0x0E, 0xAC, + 0x95, 0xF8}; + return runCommand(request, shortWriteMemoryTimeMs); +} + +error_code DS28E16::runCommand(span<const uint_least8_t> request, int delayTime, + span<uint_least8_t> & response) { + const span<const uint_least8_t>::index_type responseInputSize = + response.size(); + error_code result = doRunCommand(request, delayTime, response); + if (result) { + return result; + } + if (response.empty()) { + return make_error_code(InvalidResponseError); + } + // Parse command result byte. + switch (response[0]) { + case 0xAA: + // Success response. + if (response.size() != responseInputSize) { + result = make_error_code(InvalidResponseError); + } + break; + + case 0x00: + result = make_error_code(AuthenticationError); + break; + + default: + result.assign(response[0], errorCategory()); + break; + } + response = response.subspan(1); + return result; +} + +error_code DS28E16::runCommand(span<const uint_least8_t> request, + int delayTime) { + uint_least8_t buffer; + span<uint_least8_t> response(&buffer, 1); + return runCommand(request, delayTime, response); +} + +const error_category & DS28E16::errorCategory() { + static class : public error_category { + public: + virtual const char * name() const { return "DS28E16"; } + + virtual std::string message(int condition) const { + switch (condition) { + case InvalidOperationError: + return "Invalid Operation Error"; + + case InvalidParameterError: + return "Invalid Parameter Error"; + + case InvalidSequenceError: + return "Invalid Sequence Error"; + + case InternalError: + return "Internal Error"; + + case DeviceDisabledError: + return "Device Disabled Error"; + + case AuthenticationError: + return "Authentication Error"; + + case InvalidResponseError: + return "Invalid Response Error"; + } + return defaultErrorMessage(condition); + } + } instance; + return instance; +} + +error_code readManId(DS28E16 & device, uint_least8_t & manId) { + DS28E16::Status status; + const error_code result = device.readStatus(status); + if (!result) { + manId = status.manId; + } + return result; +} + +DS28E16::PageAuthenticationData & +DS28E16::PageAuthenticationData::setAnonymousRomId() { + fill(romId().begin(), romId().end(), 0xFF); + return *this; +} + +DS28E16::ComputeSecretData & +DS28E16::ComputeSecretData::setConstantBindingData(bool constantBindingData) { + if (constantBindingData) { + data.setPageNum(data.pageNum() | constantBindingDataMask); + fill(bindingData().begin(), bindingData().end(), 0); + } else { + data.setPageNum(data.pageNum() & ~constantBindingDataMask); + } + return *this; +} + +} // namespace MaximInterfaceDevices
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS28E16.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,458 @@ +/******************************************************************************* +* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceDevices_DS28E16 +#define MaximInterfaceDevices_DS28E16 + +#include <stdint.h> +#include <MaximInterfaceCore/Algorithm.hpp> +#include <MaximInterfaceCore/array_span.hpp> +#include <MaximInterfaceCore/FlagSet.hpp> +#include <MaximInterfaceCore/RomId.hpp> +#include <MaximInterfaceCore/RunCommand.hpp> +#include <MaximInterfaceCore/system_error.hpp> +#include "Config.hpp" + +namespace MaximInterfaceDevices { + +class DS28E16 { +public: + /// Device command results. + enum ErrorValue { + InvalidOperationError = 0x55, + InvalidParameterError = 0x77, + InvalidSequenceError = 0x33, + InternalError = 0x22, + DeviceDisabledError = 0x88, + AuthenticationError = 0x100, + InvalidResponseError ///< Command response does not match expected format. + }; + + /// @name Device memory pages + /// @{ + + static const int decrementCounterPage = 2; + static const int masterSecretPage = 3; + + /// @} + + static const int memoryPages = 4; + + /// Holds a device memory page. + typedef Core::array_span<uint_least8_t, 16> Page; + + /// Holds a Challenge, Partial Secret, or HMAC. + typedef Core::array_span<uint_least8_t, 32> DoublePage; + + /// Holds a password used to disable the device. + typedef Core::array_span<uint_least8_t, 2> DisableDevicePassword; + + // Format page authentication input data. + class PageAuthenticationData; + + // Format compute secret input data. + class ComputeSecretData; + + /// Page protection types. + enum PageProtectionType { + RP = 0x01, ///< Read protection. + WP = 0x02, ///< Write protection. + DC = 0x08 ///< Decrement counter. + }; + typedef Core::FlagSet<PageProtectionType, 4> PageProtection; + + struct Status { + typedef Core::array<PageProtection, memoryPages> PageProtectionList; + + PageProtectionList pageProtection; + uint_least8_t manId; + uint_least8_t deviceVersion; + }; + + explicit DS28E16(const Core::RunCommand & runCommand) + : doRunCommand(runCommand) {} + + void setRunCommand(const Core::RunCommand & runCommand) { + doRunCommand = runCommand; + } + + /// @brief Write memory with no protection. + /// @param pageNum Number of page to write. + /// @param page Data to write. + MaximInterfaceDevices_EXPORT Core::error_code + writeMemory(int pageNum, Page::const_span page); + + /// @brief Read memory with no protection. + /// @param pageNum Number of page to read. + /// @param[out] page Data that was read. + MaximInterfaceDevices_EXPORT Core::error_code readMemory(int pageNum, + Page::span page); + + /// @brief Reads the current status of the device. + /// @param[out] status Status that was read. + MaximInterfaceDevices_EXPORT Core::error_code readStatus(Status & status); + + /// @brief Set the protection settings of a page. + /// @param pageNum Number of page to write. + /// @param protection Protection to write. + MaximInterfaceDevices_EXPORT Core::error_code + setPageProtection(int pageNum, const PageProtection & protection); + + /// @brief Compute and read page authentication with HMAC. + /// @param pageNum Number of page to authenticate. + /// @param anonymous True to disable use of ROM ID in computation. + /// @param challenge Random challenge used to prevent replay attacks. + /// @param[out] hmac Computed page HMAC. + MaximInterfaceDevices_EXPORT Core::error_code + computeAndReadPageAuthentication(int pageNum, bool anonymous, + DoublePage::const_span challenge, + DoublePage::span hmac); + + /// Decrement the decrement-only counter. + MaximInterfaceDevices_EXPORT Core::error_code decrementCounter(); + + /// Set password that will be subsequently used to disable the device. + MaximInterfaceDevices_EXPORT Core::error_code + setDisableDevicePassword(DisableDevicePassword::const_span password); + + /// @brief Lock-out all disable functionality for the device. + /// @note Only allowed prior to setting password. + MaximInterfaceDevices_EXPORT Core::error_code lockOutDisableDevice(); + + /// Permanently disable the device. + MaximInterfaceDevices_EXPORT Core::error_code + disableDevice(DisableDevicePassword::const_span password); + + /// @brief + /// Compute a derivative secret for authentication from the Master Secret. + /// @param bindingDataPageNum Page number for Binding Data. + /// @param constantBindingData + /// Use constant Binding Data instead of Binding Data from the selected page. + /// @param anonymous True to disable use of ROM ID in computation. + /// @param partialSecret Partial secret to use in computation. + /// @note + /// This command should be executed prior to the + /// Compute and Read Page Authentication command. + MaximInterfaceDevices_EXPORT Core::error_code + computeSecret(int bindingDataPageNum, bool constantBindingData, + bool anonymous, DoublePage::const_span partialSecret); + + MaximInterfaceDevices_EXPORT static const Core::error_category & + errorCategory(); + +protected: + MaximInterfaceDevices_EXPORT Core::error_code + runCommand(Core::span<const uint_least8_t> request, int delayTime, + Core::span<uint_least8_t> & response); + + MaximInterfaceDevices_EXPORT Core::error_code + runCommand(Core::span<const uint_least8_t> request, int delayTime); + +private: + enum DisableDeviceOperation { + SetDisableDevicePassword = 0x0F, + LockOutDisableDevice = 0x05, + DisableDevice = 0x00 + }; + + Core::error_code disableDevice(DisableDeviceOperation operation, + DisableDevicePassword::const_span password); + + Core::RunCommand doRunCommand; +}; + +inline Core::error_code make_error_code(DS28E16::ErrorValue e) { + return Core::error_code(e, DS28E16::errorCategory()); +} + +/// @brief Read the device MAN ID using the Read Status command. +/// @param device Device to read. +/// @param[out] manId Read MAN ID valid when operation is successful. +MaximInterfaceDevices_EXPORT Core::error_code readManId(DS28E16 & device, + uint_least8_t & manId); + +/// Format page authentication input data. +class DS28E16::PageAuthenticationData { +public: + typedef Core::array_span<uint_least8_t, Core::RomId::size + 2 * Page::size + + DoublePage::size + 3> + Result; + + PageAuthenticationData() : result_() {} + + /// Formatted data result. + Result::const_span result() const { return result_; } + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { + return make_span(result_).subspan<romIdIdx, Core::RomId::size>(); + } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { + return const_cast<PageAuthenticationData &>(*this).romId(); + } + + /// Set ROM ID. + PageAuthenticationData & setRomId(Core::RomId::const_span romId) { + copy(romId, this->romId()); + return *this; + } + + /// Set ROM ID for use in anonymous mode. + MaximInterfaceDevices_EXPORT PageAuthenticationData & setAnonymousRomId(); + + /// @} + + /// @name Page + /// @brief Data from a device memory page. + /// @{ + + /// Get mutable page. + Page::span page() { + return make_span(result_).subspan<pageIdx, Page::size>(); + } + + /// Get immutable page. + Page::const_span page() const { + return const_cast<PageAuthenticationData &>(*this).page(); + } + + /// Set page. + PageAuthenticationData & setPage(Page::const_span page) { + copy(page, this->page()); + return *this; + } + + /// @} + + /// @name Challenge. + /// @brief Random challenge used to prevent replay attacks. + /// @{ + + /// Get mutable Challenge. + DoublePage::span challenge() { + return make_span(result_).subspan<challengeIdx, DoublePage::size>(); + } + + /// Get immutable Challenge. + DoublePage::const_span challenge() const { + return const_cast<PageAuthenticationData &>(*this).challenge(); + } + + /// Set Challenge. + PageAuthenticationData & setChallenge(DoublePage::const_span challenge) { + copy(challenge, this->challenge()); + return *this; + } + + /// @} + + /// @name Page number + /// @brief Number of the page to use data from. + /// @{ + + /// Get page number. + int pageNum() const { return result_[pageNumIdx]; } + + /// Set page number. + PageAuthenticationData & setPageNum(int pageNum) { + result_[pageNumIdx] = pageNum; + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get mutable MAN ID. + uint_least8_t & manId() { return result_[manIdIdx]; } + + /// Get immutable MAN ID. + uint_least8_t manId() const { + return const_cast<PageAuthenticationData &>(*this).manId(); + } + + /// Set MAN ID. + PageAuthenticationData & setManId(uint_least8_t manId) { + this->manId() = manId; + return *this; + } + + /// @} + +private: + typedef Result::span::index_type index; + + static const index romIdIdx = 0; + static const index pageIdx = romIdIdx + Core::RomId::size; + static const index challengeIdx = pageIdx + 2 * Page::size; + static const index pageNumIdx = challengeIdx + DoublePage::size; + static const index manIdIdx = pageNumIdx + 1; + + Result::array result_; +}; + +/// Format compute secret input data. +class DS28E16::ComputeSecretData { +public: + typedef PageAuthenticationData::Result Result; + + ComputeSecretData() : data() { + data.setPageNum(0x80 | constantBindingDataMask); + } + + /// Formatted data result. + Result::const_span result() const { return data.result(); } + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { return data.romId(); } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { return data.romId(); } + + /// Set ROM ID. + ComputeSecretData & setRomId(Core::RomId::const_span romId) { + data.setRomId(romId); + return *this; + } + + /// @} + + /// @name Binding Data + /// @brief Binding Data contained in the selected page. + /// @{ + + /// Get mutable Binding Data. + Page::span bindingData() { return data.page(); } + + /// Get immutable Binding Data. + Page::const_span bindingData() const { return data.page(); } + + /// Set Binding Data. + ComputeSecretData & setBindingData(Page::const_span bindingData) { + data.setPage(bindingData); + return *this; + } + + /// @} + + /// @name Constant Binding Data + /// @brief + /// Use constant Binding Data instead of Binding Data from the selected page. + /// @{ + + /// Get Constant Binding Data. + bool constantBindingData() const { + return (data.pageNum() & constantBindingDataMask) == + constantBindingDataMask; + } + + /// Set Constant Binding Data. + MaximInterfaceDevices_EXPORT ComputeSecretData & + setConstantBindingData(bool constantBindingData); + + /// @} + + /// @name Partial Secret + /// @brief Partial Secret used for customization. + /// @{ + + /// Get mutable Partial Secret. + DoublePage::span partialSecret() { return data.challenge(); } + + /// Get immutable Partial Secret. + DoublePage::const_span partialSecret() const { return data.challenge(); } + + /// Set Partial Secret. + ComputeSecretData & setPartialSecret(DoublePage::const_span partialSecret) { + data.setChallenge(partialSecret); + return *this; + } + + /// @} + + /// @name Binding Data page number + /// @{ + + /// Get Binding Data page number. + int bindingDataPageNum() const { + return data.pageNum() & bindingDataPageNumMask; + } + + /// Set Binding Data page number. + ComputeSecretData & setBindingDataPageNum(int bindingDataPageNum) { + data.setPageNum((bindingDataPageNum & bindingDataPageNumMask) | + (data.pageNum() & ~bindingDataPageNumMask)); + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get mutable MAN ID. + uint_least8_t & manId() { return data.manId(); } + + /// Get immutable MAN ID. + uint_least8_t manId() const { return data.manId(); } + + /// Set MAN ID. + ComputeSecretData & setManId(uint_least8_t manId) { + data.setManId(manId); + return *this; + } + + /// @} + +private: + static const unsigned int bindingDataPageNumMask = 0x03; + static const unsigned int constantBindingDataMask = 0x04; + + PageAuthenticationData data; +}; + +} // namespace MaximInterfaceDevices + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS28E17.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,272 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include <stddef.h> +#include <MaximInterfaceCore/crc.hpp> +#include <MaximInterfaceCore/Error.hpp> +#include <MaximInterfaceCore/OneWireMaster.hpp> +#include "DS28E17.hpp" + +namespace MaximInterfaceDevices { + +using namespace Core; + +error_code DS28E17::writeDataWithStop(uint_least8_t I2C_addr, + span<const uint_least8_t> data, + uint_least8_t * wr_status) { + return sendPacket(WriteDataWithStopCmd, &I2C_addr, data, + span<uint_least8_t>(), wr_status); +} + +error_code DS28E17::writeDataNoStop(uint_least8_t I2C_addr, + span<const uint_least8_t> data, + uint_least8_t * wr_status) { + return sendPacket(WriteDataNoStopCmd, &I2C_addr, data, span<uint_least8_t>(), + wr_status); +} + +error_code DS28E17::writeDataOnly(span<const uint_least8_t> data, + uint_least8_t * wr_status) { + return sendPacket(WriteDataOnlyCmd, NULL, data, span<uint_least8_t>(), + wr_status); +} + +error_code DS28E17::writeDataOnlyWithStop(span<const uint_least8_t> data, + uint_least8_t * wr_status) { + return sendPacket(WriteDataOnlyWithStopCmd, NULL, data, span<uint_least8_t>(), + wr_status); +} + +error_code DS28E17::writeReadDataWithStop(uint_least8_t I2C_addr, + span<const uint_least8_t> write_data, + span<uint_least8_t> read_data, + uint_least8_t * wr_status) { + return sendPacket(WriteReadDataWithStopCmd, &I2C_addr, write_data, read_data, + wr_status); +} + +error_code DS28E17::readDataWithStop(uint_least8_t I2C_addr, + span<uint_least8_t> data) { + return sendPacket(ReadDataWithStopCmd, &I2C_addr, span<const uint_least8_t>(), + data, NULL); +} + +error_code DS28E17::writeConfigReg(I2CSpeed speed) { + error_code result = selectRom(*master); + if (!result) { + // Send CMD and Data + const uint_least8_t send_block[] = {WriteConfigurationCmd, + static_cast<uint_least8_t>(speed)}; + result = master->writeBlock(send_block); + } + return result; +} + +error_code DS28E17::readConfigReg(I2CSpeed & speed) { + error_code result = selectRom(*master); + if (!result) { + // Send CMD and receive Data + result = master->writeByte(ReadConfigurationCmd); + if (!result) { + uint_least8_t config; + result = master->readByte(config); + if (!result) { + switch (config) { + case Speed100kHz: + case Speed400kHz: + case Speed900kHz: + speed = static_cast<I2CSpeed>(config); + break; + + default: + result = make_error_code(OutOfRangeError); + break; + } + } + } + } + return result; +} + +error_code DS28E17::enableSleepMode() { + error_code result = selectRom(*master); + if (!result) { + // Send CMD + result = master->writeByte(EnableSleepModeCmd); + } + return result; +} + +error_code DS28E17::readDeviceRevision(uint_least8_t & rev) { + error_code result = selectRom(*master); + if (!result) { + // Send CMD and receive Data + result = master->writeByte(ReadDeviceRevisionCmd); + if (!result) { + result = master->readByte(rev); + } + } + return result; +} + +error_code DS28E17::sendPacket(Command command, const uint_least8_t * I2C_addr, + span<const uint_least8_t> write_data, + span<uint_least8_t> read_data, + uint_least8_t * wr_status) { + const int pollLimit = 10000; + const span<const uint_least8_t>::index_type maxDataLen = 255; + + if ((!write_data.empty() && write_data.size() > maxDataLen) || + (!read_data.empty() && read_data.size() > maxDataLen)) { + return make_error_code(OutOfRangeError); + } + + error_code result = selectRom(*master); + if (result) { + return result; + } + uint_fast16_t crc16 = calculateCrc16(command); + result = master->writeByte(command); + if (result) { + return result; + } + if (I2C_addr) { + crc16 = calculateCrc16(crc16, *I2C_addr); + result = master->writeByte(*I2C_addr); + if (result) { + return result; + } + } + if (!write_data.empty()) { + crc16 = calculateCrc16(crc16, static_cast<uint_fast8_t>(write_data.size())); + result = master->writeByte(static_cast<uint_least8_t>(write_data.size())); + if (result) { + return result; + } + crc16 = calculateCrc16(crc16, write_data); + result = master->writeBlock(write_data); + if (result) { + return result; + } + } + if (!read_data.empty()) { + crc16 = calculateCrc16(crc16, static_cast<uint_fast8_t>(read_data.size())); + result = master->writeByte(static_cast<uint_least8_t>(read_data.size())); + if (result) { + return result; + } + } + crc16 ^= 0xFFFFu; + const uint_least8_t crc16Bytes[] = {static_cast<uint_least8_t>(crc16), + static_cast<uint_least8_t>(crc16 >> 8)}; + result = master->writeBlock(crc16Bytes); + if (result) { + return result; + } + // Poll for Zero 1-Wire bit and return if an error occurs + int poll_count = 0; + bool recvbit; + do { + if (poll_count++ < pollLimit) { + return make_error_code(TimeoutError); + } + result = master->readBit(recvbit); + if (result) { + return result; + } + } while (recvbit); + uint_least8_t status; + result = master->readByte(status); + if (result) { + return result; + } + if ((status & 0x1) == 0x1) { + return make_error_code(InvalidCrc16Error); + } + if ((status & 0x2) == 0x2) { + return make_error_code(AddressNackError); + } + if ((status & 0x8) == 0x8) { + return make_error_code(InvalidStartError); + } + if (!write_data.empty()) { + result = master->readByte(status); + if (result) { + return result; + } + if (wr_status) { + *wr_status = status; + } + if (status != 0) { + return make_error_code(WriteNackError); + } + } + if (!read_data.empty()) { + result = master->readBlock(read_data); + } + return result; +} + +const error_category & DS28E17::errorCategory() { + static class : public error_category { + public: + virtual const char * name() const { return "DS28E17"; } + + virtual std::string message(int condition) const { + switch (condition) { + case TimeoutError: + return "Timeout Error"; + + case OutOfRangeError: + return "Out of Range Error"; + + case InvalidCrc16Error: + return "Invalid CRC16 Error"; + + case AddressNackError: + return "Address Nack Error"; + + case InvalidStartError: + return "Invalid Start Error"; + + case WriteNackError: + return "Write Nack Error"; + + default: + return defaultErrorMessage(condition); + } + } + } instance; + return instance; +} + +} // namespace MaximInterfaceDevices
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS28E17.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,208 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceDevices_DS28E17 +#define MaximInterfaceDevices_DS28E17 + +#include <stdint.h> +#include <MaximInterfaceCore/SelectRom.hpp> +#include <MaximInterfaceCore/span.hpp> +#include "Config.hpp" + +namespace MaximInterfaceDevices { + +/// @brief DS28E17 1-Wire®-to-I2C Master Bridge +/// @details The DS28E17 is a 1-Wire slave to I2C master bridge +/// device that interfaces directly to I2C slaves at standard +/// (100kHz max) or fast (400kHz max). Data transfers serially by +/// means of the 1-Wire® protocol, which requires only a single data +/// lead and a ground return. Every DS28E17 is guaranteed to have a +/// unique 64-bit ROM registration number that serves as a node +/// address in the 1-Wire network. Multiple DS28E17 devices can +/// coexist with other devices in the 1-Wire network and be accessed +/// individually without affecting other devices. The DS28E17 allows +/// using complex I2C devices such as display controllers, ADCs, DACs, +/// I2C sensors, etc. in a 1-Wire environment. Each self-timed DS28E17 +/// provides 1-Wire access for a single I2C interface. +class DS28E17 { +public: + enum ErrorValue { + TimeoutError = 1, + OutOfRangeError, + InvalidCrc16Error, + AddressNackError, + InvalidStartError, + WriteNackError + }; + + enum I2CSpeed { Speed100kHz, Speed400kHz, Speed900kHz }; + + DS28E17(Core::OneWireMaster & master, const Core::SelectRom & selectRom) + : selectRom(selectRom), master(&master) {} + + void setMaster(Core::OneWireMaster & master) { this->master = &master; } + + void setSelectRom(const Core::SelectRom & selectRom) { + this->selectRom = selectRom; + } + + /// @brief Write Data With Stop command. + /// @details Output on I2C: S, Address + Write, Write Data [1-255], P + /// @param[in] I2C_addr + /// I2C slave address. The least significant bit of the I2C + /// address is automatically cleared by the command. + /// @param[in] data I2C data to write with length 1-255. + /// @param[out] wr_status + /// Indicates which write byte NACK’d. A value of 00h indicates all bytes + /// were acknowledged by the slave. A non-zero value indicates the byte number + /// that NACK’d. May be set to NULL. + MaximInterfaceDevices_EXPORT Core::error_code + writeDataWithStop(uint_least8_t I2C_addr, + Core::span<const uint_least8_t> data, + uint_least8_t * wr_status = NULL); + + /// @brief Write Data No Stop command. + /// @details Output on I2C: S, Address + Write, Write Data [1-255] + /// @param[in] I2C_addr + /// I2C slave address. The least significant bit of the I2C address + /// is automatically cleared by the command. + /// @param[in] data I2C data to write with length 1-255. + /// @param[out] wr_status + /// Indicates which write byte NACK’d. A value of 00h indicates all bytes + /// were acknowledged by the slave. A non-zero value indicates the byte number + /// that NACK’d. May be set to NULL. + MaximInterfaceDevices_EXPORT Core::error_code + writeDataNoStop(uint_least8_t I2C_addr, Core::span<const uint_least8_t> data, + uint_least8_t * wr_status = NULL); + + /// @brief Write Data Only command. + /// @details Output on I2C: Write Data [1-255] + /// @param[in] data I2C data to write with length 1-255. + /// @param[out] wr_status + /// Indicates which write byte NACK’d. A value of 00h indicates all bytes + /// were acknowledged by the slave. A non-zero value indicates the byte number + /// that NACK’d. May be set to NULL. + MaximInterfaceDevices_EXPORT Core::error_code + writeDataOnly(Core::span<const uint_least8_t> data, + uint_least8_t * wr_status = NULL); + + /// @brief Write Data Only With Stop command. + /// @details Output on I2C: Write Data [1-255], P + /// @param[in] data I2C data to write with length 1-255. + /// @param[out] wr_status + /// Indicates which write byte NACK’d. A value of 00h indicates all bytes + /// were acknowledged by the slave. A non-zero value indicates the byte number + /// that NACK’d. May be set to NULL. + MaximInterfaceDevices_EXPORT Core::error_code + writeDataOnlyWithStop(Core::span<const uint_least8_t> data, + uint_least8_t * wr_status = NULL); + + /// @brief Write, Read Data With Stop command. + /// @details Output on I2C: + /// S, Slave Address + Write, Write Data [1-255], + /// Sr, Address + Read, Read Data [1-255], P (NACK last read byte) + /// @param[in] I2C_addr + /// I2C slave address. The least significant bit of the I2C address + /// is automatically cleared and set by the command. + /// @param[in] write_data I2C data to write with length 1-255. + /// @param[out] read_data I2C data that was read with length 1-255. + /// @param[out] wr_status + /// Indicates which write byte NACK’d. A value of 00h indicates all bytes + /// were acknowledged by the slave. A non-zero value indicates the byte number + /// that NACK’d. May be set to NULL. + MaximInterfaceDevices_EXPORT Core::error_code writeReadDataWithStop( + uint_least8_t I2C_addr, Core::span<const uint_least8_t> write_data, + Core::span<uint_least8_t> read_data, uint_least8_t * wr_status = NULL); + + /// @brief Read Data With Stop command. + /// @details Output on I2C: + /// S, Slave Address + Read, Read Data [1-255], P (NACK last read byte) + /// @param[in] I2C_addr + /// I2C slave address. The least significant bit of the I2C address + /// is automatically set by the command. + /// @param[out] data I2C data that was read with length 1-255. + MaximInterfaceDevices_EXPORT Core::error_code + readDataWithStop(uint_least8_t I2C_addr, Core::span<uint_least8_t> data); + + /// Write to Configuration Register of DS28E17. + MaximInterfaceDevices_EXPORT Core::error_code writeConfigReg(I2CSpeed speed); + + /// @brief Read the Configuration Register of DS28E17. + /// @param[out] speed Speed read from configuration register. + MaximInterfaceDevices_EXPORT Core::error_code readConfigReg(I2CSpeed & speed); + + /// @brief Put the device into a low current mode. + /// @details All 1-Wire communication is ignored until woken up. Immediately + /// after the command, the device monitors the WAKEUP input pin and exits + /// sleep mode on a rising edge. + MaximInterfaceDevices_EXPORT Core::error_code enableSleepMode(); + + /// @brief Read the Device Revision of DS28E17. + /// @details The upper nibble is the major revision, + /// and the lower nibble is the minor revision. + /// @param[out] rev Device Revision. + MaximInterfaceDevices_EXPORT Core::error_code + readDeviceRevision(uint_least8_t & rev); + + MaximInterfaceDevices_EXPORT static const Core::error_category & + errorCategory(); + +private: + enum Command { + WriteDataWithStopCmd = 0x4B, + WriteDataNoStopCmd = 0x5A, + WriteDataOnlyCmd = 0x69, + WriteDataOnlyWithStopCmd = 0x78, + ReadDataWithStopCmd = 0x87, + WriteReadDataWithStopCmd = 0x2D, + WriteConfigurationCmd = 0xD2, + ReadConfigurationCmd = 0xE1, + EnableSleepModeCmd = 0x1E, + ReadDeviceRevisionCmd = 0xC3 + }; + + Core::error_code sendPacket(Command command, const uint_least8_t * I2C_addr, + Core::span<const uint_least8_t> write_data, + Core::span<uint_least8_t> read_data, + uint_least8_t * wr_status); + + Core::SelectRom selectRom; + Core::OneWireMaster * master; +}; + +inline Core::error_code make_error_code(DS28E17::ErrorValue e) { + return Core::error_code(e, DS28E17::errorCategory()); +} + +} // namespace MaximInterfaceDevices + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS28E38.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,302 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include <stddef.h> +#include <algorithm> +#include <MaximInterfaceCore/Error.hpp> +#include "DS28E38.hpp" + +namespace MaximInterfaceDevices { + +using namespace Core; +using std::copy; + +static const int readMemoryTimeMs = 30; +static const int writeMemoryTimeMs = 65; +static const int writeStateTimeMs = 15; +static const int generateEccKeyPairTimeMs = 200; +static const int generateEcdsaSignatureTimeMs = 130; +static const int trngOnDemandCheckTimeMs = 20; +static const int trngGenerationTimeMs = 10; + +const int DS28E38::decrementCounterPage; +const int DS28E38::publicKeyXPage; +const int DS28E38::publicKeyYPage; +const int DS28E38::privateKeyPage; +const int DS28E38::memoryPages; + +error_code DS28E38::writeMemory(int pageNum, Page::const_span page) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t request[2 + Page::size]; + request[0] = 0x96; + request[1] = pageNum; + copy(page.begin(), page.end(), request + 2); + return runCommand(request, writeMemoryTimeMs); +} + +error_code DS28E38::readMemory(int pageNum, Page::span page) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t buffer[1 + Page::size]; + buffer[0] = 0x44; + buffer[1] = pageNum; + span<uint_least8_t> response(buffer); + const error_code result = + runCommand(make_span(buffer, 2), readMemoryTimeMs, response); + if (!result) { + copy(response.begin(), response.end(), page.begin()); + } + return result; +} + +error_code DS28E38::readStatus(bool entropyHealthTest, Status & status) { + int delay = readMemoryTimeMs; + if (entropyHealthTest) { + delay += trngOnDemandCheckTimeMs; + } + uint_least8_t buffer[Status::PageProtectionList::csize + ManId::size + + Status::RomVersion::csize + 2]; + buffer[0] = 0xAA; + buffer[1] = entropyHealthTest ? 0x01 : 0x00; + span<uint_least8_t> response(buffer); + error_code result = runCommand(make_span(buffer, 2), delay, response); + if (!result) { + span<uint_least8_t>::const_iterator responseIt = response.begin(); + for (Status::PageProtectionList::iterator it = + status.pageProtection.begin(); + it != status.pageProtection.end(); ++it) { + *it = *responseIt; + ++responseIt; + } + span<uint_least8_t>::const_iterator responseItEnd = + responseIt + status.manId.size(); + copy(responseIt, responseItEnd, status.manId.begin()); + responseIt = responseItEnd; + responseItEnd = responseIt + status.romVersion.size(); + copy(responseIt, responseItEnd, status.romVersion.begin()); + responseIt = responseItEnd; + switch (*responseIt) { + case Status::TestNotPerformed: + case Status::EntropyHealthy: + case Status::EntropyNotHealthy: + status.entropyHealthTestStatus = + static_cast<Status::EntropyHealthTestStatus>(*responseIt); + break; + + default: + result = make_error_code(InvalidResponseError); + break; + } + } + return result; +} + +error_code DS28E38::setPageProtection(int pageNum, + const PageProtection & protection) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + int delay = writeStateTimeMs; + if (pageNum == decrementCounterPage) { + delay += writeMemoryTimeMs; + } + const uint_least8_t request[] = { + 0xC3, static_cast<uint_least8_t>(pageNum), + static_cast<uint_least8_t>(protection.to_ulong())}; + return runCommand(request, delay); +} + +error_code +DS28E38::computeAndReadPageAuthentication(int pageNum, bool anonymous, + Page::const_span challenge, + Ecc256::Signature::span signature) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + const size_t requestSize = 2 + Page::size; + const size_t responseSize = 1 + 2 * Ecc256::Scalar::size; + uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)]; + buffer[0] = 0xA5; + buffer[1] = pageNum | (anonymous ? 0xE0 : 0x00); + copy(challenge.begin(), challenge.end(), buffer + 2); + span<uint_least8_t> response(buffer, responseSize); + const error_code result = runCommand(make_span(buffer, requestSize), + generateEcdsaSignatureTimeMs, response); + if (!result) { + span<uint_least8_t>::const_iterator begin = response.begin(); + span<uint_least8_t>::const_iterator end = begin + signature.s.size(); + copy(begin, end, signature.s.begin()); + begin = end; + end = begin + signature.r.size(); + copy(begin, end, signature.r.begin()); + } + return result; +} + +error_code DS28E38::decrementCounter() { + const uint_least8_t request = 0xC9; + return runCommand(make_span(&request, 1), writeMemoryTimeMs); +} + +error_code DS28E38::disableDevice() { + const uint_least8_t request[] = {0x33, 0x9E, 0xA7, 0x49, 0xFB, + 0x10, 0x62, 0x0A, 0x26}; + return runCommand(request, writeStateTimeMs); +} + +error_code DS28E38::generateEcc256KeyPair(bool privateKeyPuf, + bool writeProtectEnable) { + int delay = generateEccKeyPairTimeMs; + if (writeProtectEnable) { + delay += writeStateTimeMs; + } + uint_least8_t request[] = {0xCB, 0x00}; + if (privateKeyPuf) { + request[1] |= 0x01; + } + if (writeProtectEnable) { + request[1] |= 0x80; + } + return runCommand(request, delay); +} + +error_code DS28E38::readRng(span<uint_least8_t> data) { + const span<uint_least8_t>::index_type maxDataSize = 64; + if ((data.size() < 1) || (data.size() > maxDataSize)) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t buffer[1 + maxDataSize]; + buffer[0] = 0xD2; + buffer[1] = static_cast<uint_least8_t>(data.size() - 1); + span<uint_least8_t> response(buffer, 1 + data.size()); + const error_code result = + runCommand(make_span(buffer, 2), trngGenerationTimeMs, response); + if (!result) { + copy(response.begin(), response.end(), data.begin()); + } + return result; +} + +error_code DS28E38::runCommand(span<const uint_least8_t> request, int delayTime, + span<uint_least8_t> & response) { + const span<const uint_least8_t>::index_type responseInputSize = + response.size(); + error_code result = doRunCommand(request, delayTime, response); + if (result) { + return result; + } + if (response.empty()) { + return make_error_code(InvalidResponseError); + } + // Parse command result byte. + switch (response[0]) { + case 0xAA: + // Success response. + if (response.size() != responseInputSize) { + result = make_error_code(InvalidResponseError); + } + break; + + case 0x00: + result = make_error_code(InvalidResponseError); + break; + + default: + result.assign(response[0], errorCategory()); + break; + } + response = response.subspan(1); + return result; +} + +error_code DS28E38::runCommand(span<const uint_least8_t> request, + int delayTime) { + uint_least8_t buffer; + span<uint_least8_t> response(&buffer, 1); + return runCommand(request, delayTime, response); +} + +const error_category & DS28E38::errorCategory() { + static class : public error_category { + public: + virtual const char * name() const { return "DS28E38"; } + + virtual std::string message(int condition) const { + switch (condition) { + case InvalidOperationError: + return "Invalid Operation Error"; + + case InvalidParameterError: + return "Invalid Parameter Error"; + + case InvalidSequenceError: + return "Invalid Sequence Error"; + + case InternalError: + return "Internal Error"; + + case DeviceDisabledError: + return "Device Disabled Error"; + + case InvalidResponseError: + return "Invalid Response Error"; + } + return defaultErrorMessage(condition); + } + } instance; + return instance; +} + +error_code readManId(DS28E38 & ds28e38, ManId::span manId) { + DS28E38::Status status; + const error_code result = ds28e38.readStatus(false, status); + if (!result) { + copy(make_span(status.manId), manId); + } + return result; +} + +DS28E38::PageAuthenticationData & +DS28E38::PageAuthenticationData::setAnonymousRomId() { + std::fill(romId().begin(), romId().end(), 0xFF); + return *this; +} + +} // namespace MaximInterfaceDevices
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS28E38.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,323 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceDevices_DS28E38 +#define MaximInterfaceDevices_DS28E38 + +#include <stdint.h> +#include <MaximInterfaceCore/Algorithm.hpp> +#include <MaximInterfaceCore/array_span.hpp> +#include <MaximInterfaceCore/Ecc256.hpp> +#include <MaximInterfaceCore/FlagSet.hpp> +#include <MaximInterfaceCore/ManId.hpp> +#include <MaximInterfaceCore/RomId.hpp> +#include <MaximInterfaceCore/RunCommand.hpp> +#include <MaximInterfaceCore/system_error.hpp> +#include "Config.hpp" + +namespace MaximInterfaceDevices { + +class DS28E38 { +public: + /// Device command results. + enum ErrorValue { + InvalidOperationError = 0x55, + InvalidParameterError = 0x77, + InvalidSequenceError = 0x33, + InternalError = 0x22, + DeviceDisabledError = 0x88, + InvalidResponseError = + 0x100 ///< Command response does not match expected format. + }; + + /// @name Device memory pages + /// @{ + + static const int decrementCounterPage = 3; + static const int publicKeyXPage = 4; + static const int publicKeyYPage = 5; + static const int privateKeyPage = 6; + + /// @} + + static const int memoryPages = 7; + + /// Holds a device memory page. + typedef Core::array_span<uint_least8_t, 32> Page; + + // Format page authentication input data. + class PageAuthenticationData; + + /// Page protection types. + enum PageProtectionType { + RP = 0x01, ///< Read protection. + WP = 0x02, ///< Write protection. + EM = 0x04, ///< EPROM emulation mode. + DC = 0x08, ///< Decrement counter. + PF = 0x10 ///< PUF used as private key. + }; + typedef Core::FlagSet<PageProtectionType, 5> PageProtection; + + struct Status { + enum EntropyHealthTestStatus { + TestNotPerformed = 0xFF, + EntropyHealthy = 0xAA, + EntropyNotHealthy = 0xDD + }; + + typedef Core::array<PageProtection, memoryPages> PageProtectionList; + typedef Core::array<uint_least8_t, 2> RomVersion; + + PageProtectionList pageProtection; + Core::ManId::array manId; + RomVersion romVersion; + EntropyHealthTestStatus entropyHealthTestStatus; + }; + + explicit DS28E38(const Core::RunCommand & runCommand) + : doRunCommand(runCommand) {} + + void setRunCommand(const Core::RunCommand & runCommand) { + doRunCommand = runCommand; + } + + /// @brief Write memory with no protection. + /// @param pageNum Number of page to write. + /// @param page Data to write. + MaximInterfaceDevices_EXPORT Core::error_code + writeMemory(int pageNum, Page::const_span page); + + /// @brief Read memory with no protection. + /// @param pageNum Number of page to read. + /// @param[out] page Data that was read. + MaximInterfaceDevices_EXPORT Core::error_code readMemory(int pageNum, + Page::span page); + + /// @brief + /// Reads the current status of the device and optionally performs an + /// entropy health test. + /// @param entropyHealthTest True to perform an entropy health test. + /// @param[out] status Status that was read. + MaximInterfaceDevices_EXPORT Core::error_code + readStatus(bool entropyHealthTest, Status & status); + + /// @brief Set the protection settings of a page. + /// @param pageNum Number of page to write. + /// @param protection Protection to write. + MaximInterfaceDevices_EXPORT Core::error_code + setPageProtection(int pageNum, const PageProtection & protection); + + /// @brief Compute and read page authentication with ECDSA. + /// @param pageNum Number of page to authenticate. + /// @param anonymous True to disable use of ROM ID in computation. + /// @param challenge Random challenge used to prevent replay attacks. + /// @param[out] signature Computed page signature. + MaximInterfaceDevices_EXPORT Core::error_code + computeAndReadPageAuthentication(int pageNum, bool anonymous, + Page::const_span challenge, + Core::Ecc256::Signature::span signature); + + /// Decrement the decrement-only counter. + MaximInterfaceDevices_EXPORT Core::error_code decrementCounter(); + + /// Permanently disable the device. + MaximInterfaceDevices_EXPORT Core::error_code disableDevice(); + + /// @brief Generate a new ECDSA public key from an existing private key. + /// @param privateKeyPuf True if PUF is used as the private key. + /// @param writeProtectEnable True to lock the key against further writes. + MaximInterfaceDevices_EXPORT Core::error_code + generateEcc256KeyPair(bool privateKeyPuf, bool writeProtectEnable); + + /// @brief Read a block of random data from the RNG. + /// @param[out] data Random data from RNG with length from 1 to 64. + MaximInterfaceDevices_EXPORT Core::error_code + readRng(Core::span<uint_least8_t> data); + + MaximInterfaceDevices_EXPORT static const Core::error_category & + errorCategory(); + +protected: + MaximInterfaceDevices_EXPORT Core::error_code + runCommand(Core::span<const uint_least8_t> request, int delayTime, + Core::span<uint_least8_t> & response); + + MaximInterfaceDevices_EXPORT Core::error_code + runCommand(Core::span<const uint_least8_t> request, int delayTime); + +private: + Core::RunCommand doRunCommand; +}; + +inline Core::error_code make_error_code(DS28E38::ErrorValue e) { + return Core::error_code(e, DS28E38::errorCategory()); +} + +/// @brief Read the device MAN ID using the Read Status command. +/// @param ds28e38 Device to read. +/// @param[out] manId Read MAN ID valid when operation is successful. +MaximInterfaceDevices_EXPORT Core::error_code +readManId(DS28E38 & ds28e38, Core::ManId::span manId); + +/// Format page authentication input data. +class DS28E38::PageAuthenticationData { +public: + typedef Core::array_span<uint_least8_t, Core::RomId::size + 2 * Page::size + + 1 + Core::ManId::size> + Result; + + PageAuthenticationData() : result_() {} + + /// Formatted data result. + Result::const_span result() const { return result_; } + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { + return make_span(result_).subspan<romIdIdx, Core::RomId::size>(); + } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { + return const_cast<PageAuthenticationData &>(*this).romId(); + } + + /// Set ROM ID. + PageAuthenticationData & setRomId(Core::RomId::const_span romId) { + copy(romId, this->romId()); + return *this; + } + + /// Set ROM ID for use in anonymous mode. + MaximInterfaceDevices_EXPORT PageAuthenticationData & setAnonymousRomId(); + + /// @} + + /// @name Page + /// @brief Data from a device memory page. + /// @{ + + /// Get mutable page. + Page::span page() { + return make_span(result_).subspan<pageIdx, Page::size>(); + } + + /// Get immutable page. + Page::const_span page() const { + return const_cast<PageAuthenticationData &>(*this).page(); + } + + /// Set page. + PageAuthenticationData & setPage(Page::const_span page) { + copy(page, this->page()); + return *this; + } + + /// @} + + /// @name Challenge + /// @brief Random challenge used to prevent replay attacks. + /// @{ + + /// Get mutable Challenge. + Page::span challenge() { + return make_span(result_).subspan<challengeIdx, Page::size>(); + } + + /// Get immutable Challenge. + Page::const_span challenge() const { + return const_cast<PageAuthenticationData &>(*this).challenge(); + } + + /// Set Challenge. + PageAuthenticationData & setChallenge(Page::const_span challenge) { + copy(challenge, this->challenge()); + return *this; + } + + /// @} + + /// @name Page number + /// @brief Number of the page to use data from. + /// @{ + + /// Get page number. + int pageNum() const { return result_[pageNumIdx]; } + + /// Set page number. + PageAuthenticationData & setPageNum(int pageNum) { + result_[pageNumIdx] = pageNum; + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get mutable MAN ID. + Core::ManId::span manId() { + return make_span(result_).subspan<manIdIdx, Core::ManId::size>(); + } + + /// Get immutable MAN ID. + Core::ManId::const_span manId() const { + return const_cast<PageAuthenticationData &>(*this).manId(); + } + + /// Set MAN ID. + PageAuthenticationData & setManId(Core::ManId::const_span manId) { + copy(manId, this->manId()); + return *this; + } + + /// @} + +private: + typedef Result::span::index_type index; + + static const index romIdIdx = 0; + static const index pageIdx = romIdIdx + Core::RomId::size; + static const index challengeIdx = pageIdx + Page::size; + static const index pageNumIdx = challengeIdx + Page::size; + static const index manIdIdx = pageNumIdx + 1; + + Result::array result_; +}; + +} // namespace MaximInterfaceDevices + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS28E39.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,346 @@ +/******************************************************************************* +* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include <stddef.h> +#include <algorithm> +#include <MaximInterfaceCore/Error.hpp> +#include "DS28E39.hpp" + +namespace MaximInterfaceDevices { + +using namespace Core; +using std::copy; + +static const int readMemoryTimeMs = 30; +static const int writeMemoryTimeMs = 65; +static const int writeStateTimeMs = 15; +static const int generateEccKeyPairTimeMs = 200; +static const int generateEcdsaSignatureTimeMs = 130; +static const int trngOnDemandCheckTimeMs = 20; +static const int trngGenerationTimeMs = 10; +static const int verifyEcdsaSignatureTimeMs = 180; + +const int DS28E39::decrementCounterPage; +const int DS28E39::authorityPublicKeyXPage; +const int DS28E39::authorityPublicKeyYPage; +const int DS28E39::writePublicKeyXPage; +const int DS28E39::writePublicKeyYPage; +const int DS28E39::memoryPages; + +error_code DS28E39::writeMemory(int pageNum, Page::const_span page) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t request[2 + Page::size]; + request[0] = 0x96; + request[1] = pageNum; + copy(page.begin(), page.end(), request + 2); + return runCommand(request, writeMemoryTimeMs); +} + +error_code DS28E39::readMemory(int pageNum, Page::span page) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t buffer[1 + Page::size]; + buffer[0] = 0x44; + buffer[1] = pageNum; + span<uint_least8_t> response(buffer); + const error_code result = + runCommand(make_span(buffer, 2), readMemoryTimeMs, response); + if (!result) { + copy(response.begin(), response.end(), page.begin()); + } + return result; +} + +error_code DS28E39::readStatus(bool entropyHealthTest, Status & status) { + int delay = readMemoryTimeMs; + if (entropyHealthTest) { + delay += trngOnDemandCheckTimeMs; + } + uint_least8_t buffer[Status::PageProtectionList::csize + ManId::size + + Status::RomVersion::csize + 2]; + buffer[0] = 0xAA; + buffer[1] = entropyHealthTest ? 0x01 : 0x00; + span<uint_least8_t> response(buffer); + error_code result = runCommand(make_span(buffer, 2), delay, response); + if (!result) { + span<uint_least8_t>::const_iterator responseIt = response.begin(); + for (Status::PageProtectionList::iterator it = + status.pageProtection.begin(); + it != status.pageProtection.end(); ++it) { + *it = *responseIt; + ++responseIt; + } + span<uint_least8_t>::const_iterator responseItEnd = + responseIt + status.manId.size(); + copy(responseIt, responseItEnd, status.manId.begin()); + responseIt = responseItEnd; + responseItEnd = responseIt + status.romVersion.size(); + copy(responseIt, responseItEnd, status.romVersion.begin()); + responseIt = responseItEnd; + switch (*responseIt) { + case Status::TestNotPerformed: + case Status::EntropyHealthy: + case Status::EntropyNotHealthy: + status.entropyHealthTestStatus = + static_cast<Status::EntropyHealthTestStatus>(*responseIt); + break; + + default: + result = make_error_code(InvalidResponseError); + break; + } + } + return result; +} + +error_code DS28E39::setPageProtection(int pageNum, + const PageProtection & protection) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + int delay = writeStateTimeMs; + if (pageNum == decrementCounterPage) { + delay += writeMemoryTimeMs; + } + const uint_least8_t request[] = { + 0xC3, static_cast<uint_least8_t>(pageNum), + static_cast<uint_least8_t>(protection.to_ulong())}; + return runCommand(request, delay); +} + +error_code +DS28E39::computeAndReadPageAuthentication(int pageNum, bool anonymous, + Page::const_span challenge, + Ecc256::Signature::span signature) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + const size_t requestSize = 2 + Page::size; + const size_t responseSize = 1 + 2 * Ecc256::Scalar::size; + uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)]; + buffer[0] = 0xA5; + buffer[1] = pageNum | (anonymous ? 0xE0 : 0x00); + copy(challenge.begin(), challenge.end(), buffer + 2); + span<uint_least8_t> response(buffer, responseSize); + const error_code result = runCommand(make_span(buffer, requestSize), + generateEcdsaSignatureTimeMs, response); + if (!result) { + span<uint_least8_t>::const_iterator begin = response.begin(); + span<uint_least8_t>::const_iterator end = begin + signature.s.size(); + copy(begin, end, signature.s.begin()); + begin = end; + end = begin + signature.r.size(); + copy(begin, end, signature.r.begin()); + } + return result; +} + +error_code DS28E39::decrementCounter() { + const uint_least8_t request = 0xC9; + return runCommand(make_span(&request, 1), writeMemoryTimeMs); +} + +error_code DS28E39::disableDevice() { + const uint_least8_t request[] = {0x33, 0x9E, 0xA7, 0x49, 0xFB, + 0x10, 0x62, 0x0A, 0x26}; + return runCommand(request, writeStateTimeMs); +} + +error_code +DS28E39::readDevicePublicKey(Ecc256::PublicKey::span devicePublicKey) { + uint_least8_t buffer[1 + 2 * Ecc256::Scalar::size]; + buffer[0] = 0xCB; + span<uint_least8_t> response(buffer); + const error_code result = + runCommand(make_span(buffer, 1), generateEccKeyPairTimeMs, response); + if (!result) { + span<uint_least8_t>::const_iterator begin = response.begin(); + span<uint_least8_t>::const_iterator end = begin + devicePublicKey.x.size(); + copy(begin, end, devicePublicKey.x.begin()); + begin = end; + end = begin + devicePublicKey.y.size(); + copy(begin, end, devicePublicKey.y.begin()); + } + return result; +} + +error_code DS28E39::readRng(span<uint_least8_t> data) { + const span<uint_least8_t>::index_type maxDataSize = 64; + if ((data.size() < 1) || (data.size() > maxDataSize)) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t buffer[1 + maxDataSize]; + buffer[0] = 0xD2; + buffer[1] = static_cast<uint_least8_t>(data.size() - 1); + span<uint_least8_t> response(buffer, 1 + data.size()); + const error_code result = + runCommand(make_span(buffer, 2), trngGenerationTimeMs, response); + if (!result) { + copy(response.begin(), response.end(), data.begin()); + } + return result; +} + +error_code +DS28E39::authenticatePublicKey(Ecc256::Signature::const_span certificate, + span<const uint_least8_t> customization) { + static const span<const uint_least8_t>::index_type maxCustomizationSize = 32; + static const span<const uint_least8_t>::index_type signatureSize = + 2 * Ecc256::Scalar::size; + + if (customization.size() < 1 || customization.size() > maxCustomizationSize) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t request[1 + signatureSize + maxCustomizationSize]; + uint_least8_t * requestIt = request; + *requestIt++ = 0x59; + requestIt = copy(certificate.r.begin(), certificate.r.end(), requestIt); + requestIt = copy(certificate.s.begin(), certificate.s.end(), requestIt); + requestIt = copy(customization.begin(), customization.end(), requestIt); + return runCommand(make_span(request, requestIt), verifyEcdsaSignatureTimeMs); +} + +error_code +DS28E39::authenticatedWriteMemory(int pageNum, Page::const_span page, + Ecc256::Signature::const_span signature) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t request[2 + Page::size + 2 * Ecc256::Scalar::size]; + uint_least8_t * requestIt = request; + *requestIt++ = 0x89; + *requestIt++ = pageNum; + requestIt = copy(page.begin(), page.end(), requestIt); + requestIt = copy(signature.r.begin(), signature.r.end(), requestIt); + copy(signature.s.begin(), signature.s.end(), requestIt); + return runCommand(request, verifyEcdsaSignatureTimeMs + writeMemoryTimeMs); +} + +error_code DS28E39::runCommand(span<const uint_least8_t> request, int delayTime, + span<uint_least8_t> & response) { + const span<const uint_least8_t>::index_type responseInputSize = + response.size(); + error_code result = doRunCommand(request, delayTime, response); + if (result) { + return result; + } + if (response.empty()) { + return make_error_code(InvalidResponseError); + } + // Parse command result byte. + switch (response[0]) { + case 0xAA: + // Success response. + if (response.size() != responseInputSize) { + result = make_error_code(InvalidResponseError); + } + break; + + case 0x00: + result = make_error_code(AuthenticationError); + break; + + default: + result.assign(response[0], errorCategory()); + break; + } + response = response.subspan(1); + return result; +} + +error_code DS28E39::runCommand(span<const uint_least8_t> request, + int delayTime) { + uint_least8_t buffer; + span<uint_least8_t> response(&buffer, 1); + return runCommand(request, delayTime, response); +} + +const error_category & DS28E39::errorCategory() { + static class : public error_category { + public: + virtual const char * name() const { return "DS28E39"; } + + virtual std::string message(int condition) const { + switch (condition) { + case InvalidOperationError: + return "Invalid Operation Error"; + + case InvalidParameterError: + return "Invalid Parameter Error"; + + case InvalidSequenceError: + return "Invalid Sequence Error"; + + case InternalError: + return "Internal Error"; + + case DeviceDisabledError: + return "Device Disabled Error"; + + case AuthenticationError: + return "Authentication Error"; + + case InvalidResponseError: + return "Invalid Response Error"; + } + return defaultErrorMessage(condition); + } + } instance; + return instance; +} + +error_code readManId(DS28E39 & ds28e39, ManId::span manId) { + DS28E39::Status status; + const error_code result = ds28e39.readStatus(false, status); + if (!result) { + copy(make_span(status.manId), manId); + } + return result; +} + +DS28E39::PageAuthenticationData & +DS28E39::PageAuthenticationData::setAnonymousRomId() { + std::fill(romId().begin(), romId().end(), 0xFF); + return *this; +} + +} // namespace MaximInterfaceDevices
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS28E39.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,446 @@ +/******************************************************************************* +* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceDevices_DS28E39 +#define MaximInterfaceDevices_DS28E39 + +#include <stdint.h> +#include <MaximInterfaceCore/Algorithm.hpp> +#include <MaximInterfaceCore/array_span.hpp> +#include <MaximInterfaceCore/Ecc256.hpp> +#include <MaximInterfaceCore/FlagSet.hpp> +#include <MaximInterfaceCore/ManId.hpp> +#include <MaximInterfaceCore/RomId.hpp> +#include <MaximInterfaceCore/RunCommand.hpp> +#include <MaximInterfaceCore/system_error.hpp> +#include "Config.hpp" + +namespace MaximInterfaceDevices { + +class DS28E39 { +public: + /// Device command results. + enum ErrorValue { + InvalidOperationError = 0x55, + InvalidParameterError = 0x77, + InvalidSequenceError = 0x33, + InternalError = 0x22, + DeviceDisabledError = 0x88, + AuthenticationError = 0x100, + InvalidResponseError ///< Command response does not match expected format. + }; + + /// @name Device memory pages + /// @{ + + static const int decrementCounterPage = 4; + static const int authorityPublicKeyXPage = 5; + static const int authorityPublicKeyYPage = 6; + static const int writePublicKeyXPage = 7; + static const int writePublicKeyYPage = 8; + + /// @} + + static const int memoryPages = 9; + + /// Holds a device memory page. + typedef Core::array_span<uint_least8_t, 32> Page; + + // Format page authentication input data. + class PageAuthenticationData; + + // Format authenticated write input data. + class WriteAuthenticationData; + + /// Page protection types. + enum PageProtectionType { + RP = 0x01, ///< Read protection. + WP = 0x02, ///< Write protection. + EM = 0x04, ///< EPROM emulation mode. + DC = 0x08, ///< Decrement counter. + ECW = 0x10 ///< Authenticated write. + }; + typedef Core::FlagSet<PageProtectionType, 5> PageProtection; + + struct Status { + enum EntropyHealthTestStatus { + TestNotPerformed = 0xFF, + EntropyHealthy = 0xAA, + EntropyNotHealthy = 0xDD + }; + + typedef Core::array<PageProtection, memoryPages - 2> PageProtectionList; + typedef Core::array<uint_least8_t, 2> RomVersion; + + PageProtectionList pageProtection; + Core::ManId::array manId; + RomVersion romVersion; + EntropyHealthTestStatus entropyHealthTestStatus; + }; + + explicit DS28E39(const Core::RunCommand & runCommand) + : doRunCommand(runCommand) {} + + void setRunCommand(const Core::RunCommand & runCommand) { + doRunCommand = runCommand; + } + + /// @brief Write memory with no protection. + /// @param pageNum Number of page to write. + /// @param page Data to write. + MaximInterfaceDevices_EXPORT Core::error_code + writeMemory(int pageNum, Page::const_span page); + + /// @brief Read memory with no protection. + /// @param pageNum Number of page to read. + /// @param[out] page Data that was read. + MaximInterfaceDevices_EXPORT Core::error_code readMemory(int pageNum, + Page::span page); + + /// @brief + /// Reads the current status of the device and optionally performs an + /// entropy health test. + /// @param entropyHealthTest True to perform an entropy health test. + /// @param[out] status Status that was read. + MaximInterfaceDevices_EXPORT Core::error_code + readStatus(bool entropyHealthTest, Status & status); + + /// @brief Set the protection settings of a page. + /// @param pageNum Number of page to write. + /// @param protection Protection to write. + MaximInterfaceDevices_EXPORT Core::error_code + setPageProtection(int pageNum, const PageProtection & protection); + + /// @brief Compute and read page authentication with ECDSA. + /// @param pageNum Number of page to authenticate. + /// @param anonymous True to disable use of ROM ID in computation. + /// @param challenge Random challenge used to prevent replay attacks. + /// @param[out] signature Computed page signature. + MaximInterfaceDevices_EXPORT Core::error_code + computeAndReadPageAuthentication(int pageNum, bool anonymous, + Page::const_span challenge, + Core::Ecc256::Signature::span signature); + + /// Decrement the decrement-only counter. + MaximInterfaceDevices_EXPORT Core::error_code decrementCounter(); + + /// Permanently disable the device. + MaximInterfaceDevices_EXPORT Core::error_code disableDevice(); + + /// @brief Generate the device's ECDSA public key from the PUF private key. + /// @param[out] devicePublicKey Device Public Key + MaximInterfaceDevices_EXPORT Core::error_code + readDevicePublicKey(Core::Ecc256::PublicKey::span devicePublicKey); + + /// @brief Read a block of random data from the RNG. + /// @param[out] data Random data from RNG with length from 1 to 64. + MaximInterfaceDevices_EXPORT Core::error_code + readRng(Core::span<uint_least8_t> data); + + /// @brief + /// Authenticate a public key for authenticated writes using the + /// Authority Public Key. + /// @param certificate + /// Certificate to use for authentication of the Write Public Key. + /// @param customization + /// Certificate customization with length from 1 to 32. + MaximInterfaceDevices_EXPORT Core::error_code + authenticatePublicKey(Core::Ecc256::Signature::const_span certificate, + Core::span<const uint_least8_t> customization); + + /// @brief Write with ECDSA authentication using the Write Public Key. + /// @param pageNum Number of page to write. + /// @param page Data to write. + /// @param signature Signature to use for authentication of page data. + MaximInterfaceDevices_EXPORT Core::error_code + authenticatedWriteMemory(int pageNum, Page::const_span page, + Core::Ecc256::Signature::const_span signature); + + MaximInterfaceDevices_EXPORT static const Core::error_category & + errorCategory(); + +protected: + MaximInterfaceDevices_EXPORT Core::error_code + runCommand(Core::span<const uint_least8_t> request, int delayTime, + Core::span<uint_least8_t> & response); + + MaximInterfaceDevices_EXPORT Core::error_code + runCommand(Core::span<const uint_least8_t> request, int delayTime); + +private: + Core::RunCommand doRunCommand; +}; + +inline Core::error_code make_error_code(DS28E39::ErrorValue e) { + return Core::error_code(e, DS28E39::errorCategory()); +} + +/// @brief Read the device MAN ID using the Read Status command. +/// @param ds28e39 Device to read. +/// @param[out] manId Read MAN ID valid when operation is successful. +MaximInterfaceDevices_EXPORT Core::error_code +readManId(DS28E39 & ds28e39, Core::ManId::span manId); + +/// Format page authentication input data. +class DS28E39::PageAuthenticationData { +public: + typedef Core::array_span<uint_least8_t, Core::RomId::size + 2 * Page::size + + 1 + Core::ManId::size> + Result; + + PageAuthenticationData() : result_() {} + + /// Formatted data result. + Result::const_span result() const { return result_; } + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { + return make_span(result_).subspan<romIdIdx, Core::RomId::size>(); + } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { + return const_cast<PageAuthenticationData &>(*this).romId(); + } + + /// Set ROM ID. + PageAuthenticationData & setRomId(Core::RomId::const_span romId) { + copy(romId, this->romId()); + return *this; + } + + /// Set ROM ID for use in anonymous mode. + MaximInterfaceDevices_EXPORT PageAuthenticationData & setAnonymousRomId(); + + /// @} + + /// @name Page + /// @brief Data from a device memory page. + /// @{ + + /// Get mutable page. + Page::span page() { + return make_span(result_).subspan<pageIdx, Page::size>(); + } + + /// Get immutable page. + Page::const_span page() const { + return const_cast<PageAuthenticationData &>(*this).page(); + } + + /// Set page. + PageAuthenticationData & setPage(Page::const_span page) { + copy(page, this->page()); + return *this; + } + + /// @} + + /// @name Challenge + /// @brief Random challenge used to prevent replay attacks. + /// @{ + + /// Get mutable Challenge. + Page::span challenge() { + return make_span(result_).subspan<challengeIdx, Page::size>(); + } + + /// Get immutable Challenge. + Page::const_span challenge() const { + return const_cast<PageAuthenticationData &>(*this).challenge(); + } + + /// Set Challenge. + PageAuthenticationData & setChallenge(Page::const_span challenge) { + copy(challenge, this->challenge()); + return *this; + } + + /// @} + + /// @name Page number + /// @brief Number of the page to use data from. + /// @{ + + /// Get page number. + int pageNum() const { return result_[pageNumIdx]; } + + /// Set page number. + PageAuthenticationData & setPageNum(int pageNum) { + result_[pageNumIdx] = pageNum; + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get mutable MAN ID. + Core::ManId::span manId() { + return make_span(result_).subspan<manIdIdx, Core::ManId::size>(); + } + + /// Get immutable MAN ID. + Core::ManId::const_span manId() const { + return const_cast<PageAuthenticationData &>(*this).manId(); + } + + /// Set MAN ID. + PageAuthenticationData & setManId(Core::ManId::const_span manId) { + copy(manId, this->manId()); + return *this; + } + + /// @} + +private: + typedef Result::span::index_type index; + + static const index romIdIdx = 0; + static const index pageIdx = romIdIdx + Core::RomId::size; + static const index challengeIdx = pageIdx + Page::size; + static const index pageNumIdx = challengeIdx + Page::size; + static const index manIdIdx = pageNumIdx + 1; + + Result::array result_; +}; + +/// Format authenticated write input data. +class DS28E39::WriteAuthenticationData { +public: + typedef PageAuthenticationData::Result Result; + + WriteAuthenticationData() : data() { setPageNum(0); } + + /// Formatted data result. + Result::const_span result() const { return data.result(); } + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { return data.romId(); } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { return data.romId(); } + + /// Set ROM ID. + WriteAuthenticationData & setRomId(Core::RomId::const_span romId) { + data.setRomId(romId); + return *this; + } + + /// @} + + /// @name Old page + /// @brief Existing data contained in the page. + /// @{ + + /// Get mutable old page. + Page::span oldPage() { return data.page(); } + + /// Get immutable old page. + Page::const_span oldPage() const { return data.page(); } + + /// Set old page. + WriteAuthenticationData & setOldPage(Page::const_span oldPage) { + data.setPage(oldPage); + return *this; + } + + /// @} + + /// @name New page + /// @brief New data to write to the page. + /// @{ + + /// Get mutable new page. + Page::span newPage() { return data.challenge(); } + + /// Get immutable new page. + Page::const_span newPage() const { return data.challenge(); } + + /// Set new page. + WriteAuthenticationData & setNewPage(Page::const_span newPage) { + data.setChallenge(newPage); + return *this; + } + + /// @} + + /// @name Page number + /// @brief Page number for write operation. + /// @{ + + /// Get page number. + int pageNum() const { return data.pageNum() & 0x7F; } + + /// Set page number. + WriteAuthenticationData & setPageNum(int pageNum) { + data.setPageNum(pageNum | 0x80); + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get mutable MAN ID. + Core::ManId::span manId() { return data.manId(); } + + /// Get immutable MAN ID. + Core::ManId::const_span manId() const { return data.manId(); } + + /// Set MAN ID. + WriteAuthenticationData & setManId(Core::ManId::const_span manId) { + data.setManId(manId); + return *this; + } + + /// @} + +private: + PageAuthenticationData data; +}; + +} // namespace MaximInterfaceDevices + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS28E83_DS28E84.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,678 @@ +/******************************************************************************* +* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include <stddef.h> +#include <algorithm> +#include <MaximInterfaceCore/Error.hpp> +#include "DS28E83_DS28E84.hpp" + +namespace MaximInterfaceDevices { + +using namespace Core; +using std::copy; + +static const int readMemoryTimeMs = 2; +static const int writeMemoryTimeMs = 100; +static const int writeStateTimeMs = 15; +static const int generateEccKeyPairTimeMs = 350; +static const int generateEcdsaSignatureTimeMs = 80; +static const int computeTimeMs = 4; +static const int verifyEcdsaTimeMs = 160; +static const int trngGenerationTimeMs = 40; +static const int trngOnDemandCheckTimeMs = 65; + +static const uint_least8_t computeAndReadPageAuthenticationCmd = 0xA5; +static const uint_least8_t readRngCmd = 0xD2; + +static const int memoryPages = + MaximInterfaceCore_MAX(DS28E83::memoryPages, DS28E84::memoryPages); +static const int protectionBlocks = MaximInterfaceCore_MAX( + DS28E83::protectionBlocks, DS28E84::protectionBlocks); + +const int DS28E83_DS28E84::publicKeyAxPage; +const int DS28E83_DS28E84::publicKeyAyPage; +const int DS28E83_DS28E84::publicKeyBxPage; +const int DS28E83_DS28E84::publicKeyByPage; +const int DS28E83_DS28E84::authorityPublicKeyAxPage; +const int DS28E83_DS28E84::authorityPublicKeyAyPage; +const int DS28E83_DS28E84::authorityPublicKeyBxPage; +const int DS28E83_DS28E84::authorityPublicKeyByPage; +const int DS28E83_DS28E84::privateKeyAPage; +const int DS28E83_DS28E84::privateKeyBPage; +const int DS28E83_DS28E84::secretAPage; +const int DS28E83_DS28E84::secretBPage; +const int DS28E83_DS28E84::romOptionsPage; +const int DS28E83_DS28E84::gpioControlPage; +const int DS28E83_DS28E84::publicKeySxPage; +const int DS28E83_DS28E84::publicKeySyPage; + +const int DS28E83::memoryPages; +const int DS28E83::protectionBlocks; + +const int DS28E84::publicKeySxBackupPage; +const int DS28E84::publicKeySyBackupPage; +const int DS28E84::decrementCounterPage; +const int DS28E84::memoryPages; +const int DS28E84::protectionBlocks; + +error_code DS28E83_DS28E84::writeMemory(int pageNum, Page::const_span page) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t request[2 + Page::size]; + request[0] = 0x96; + request[1] = pageNum; + copy(page.begin(), page.end(), request + 2); + return runCommand(request, writeMemoryTimeMs); +} + +error_code DS28E83_DS28E84::readMemory(int pageNum, Page::span page) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t buffer[1 + Page::size]; + buffer[0] = 0x44; + buffer[1] = pageNum; + span<uint_least8_t> response(buffer); + const error_code result = + runCommand(make_span(buffer, 2), readMemoryTimeMs, response); + if (!result) { + copy(response.begin(), response.end(), page.begin()); + } + return result; +} + +error_code DS28E83_DS28E84::encryptedReadMemory( + int pageNum, KeySecret secret, + EncryptionChallenge::span encryptionChallenge, Page::span encryptedPage) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + const size_t requestSize = 3; + const size_t responseSize = 1 + EncryptionChallenge::size + Page::size; + uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)]; + buffer[0] = 0x4B; + buffer[1] = pageNum; + buffer[2] = secret; + span<uint_least8_t> response(buffer, responseSize); + const error_code result = + runCommand(make_span(buffer, requestSize), + readMemoryTimeMs + computeTimeMs, response); + if (!result) { + span<uint_least8_t>::const_iterator begin = response.begin(); + span<uint_least8_t>::const_iterator end = + begin + encryptionChallenge.size(); + copy(begin, end, encryptionChallenge.begin()); + begin = end; + end = begin + encryptedPage.size(); + copy(begin, end, encryptedPage.begin()); + } + return result; +} + +error_code DS28E83_DS28E84::readBlockProtection(int blockNumber, + Optional<KeySecret> & keySecret, + BlockProtection & protection) { + if (blockNumber < 0 || blockNumber >= protectionBlocks) { + return make_error_code(InvalidParameterError); + } + + const size_t requestSize = 2; + const size_t responseSize = 3; + uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)]; + buffer[0] = 0xAA; + buffer[1] = blockNumber; + span<uint_least8_t> response(buffer, responseSize); + const error_code result = + runCommand(make_span(buffer, requestSize), readMemoryTimeMs, response); + if (result) { + return result; + } + if ((response[0] & 0x3F) != blockNumber) { + return make_error_code(InvalidResponseError); + } + switch (response[0] >> 6) { + case 0: + keySecret = none; + break; + case 1: + keySecret = KeySecretA; + break; + case 2: + keySecret = KeySecretB; + break; + default: + return make_error_code(InvalidResponseError); + } + if ((response[1] & 0x20) != 0) { + return make_error_code(InvalidResponseError); + } + protection = response[1]; + return error_code(); +} + +error_code +DS28E83_DS28E84::setBlockProtection(int blockNum, KeySecret keySecret, + const BlockProtection & protection) { + if (blockNum < 0 || blockNum >= protectionBlocks || keySecret == KeySecretS) { + return make_error_code(InvalidParameterError); + } + + const uint_least8_t request[] = { + 0xC3, + static_cast<uint_least8_t>((keySecret == KeySecretB ? 0x80 : 0x40) | + blockNum), + static_cast<uint_least8_t>(protection.to_ulong())}; + return runCommand(request, writeStateTimeMs); +} + +error_code DS28E83_DS28E84::computeAndReadPageAuthentication( + int pageNum, KeySecret key, Page::const_span challenge, + Ecc256::Signature::span signature) { + if (pageNum < 0 || pageNum >= memoryPages || key == KeySecretS) { + return make_error_code(InvalidParameterError); + } + + const size_t requestSize = 3 + Page::size; + const size_t responseSize = 1 + 2 * Ecc256::Scalar::size; + uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)]; + buffer[0] = computeAndReadPageAuthenticationCmd; + buffer[1] = pageNum; + buffer[2] = key + 3; + copy(challenge.begin(), challenge.end(), buffer + 3); + span<uint_least8_t> response(buffer, responseSize); + const error_code result = runCommand(make_span(buffer, requestSize), + generateEcdsaSignatureTimeMs, response); + if (!result) { + span<uint_least8_t>::const_iterator begin = response.begin(); + span<uint_least8_t>::const_iterator end = begin + signature.s.size(); + copy(begin, end, signature.s.begin()); + begin = end; + end = begin + signature.r.size(); + copy(begin, end, signature.r.begin()); + } + return result; +} + +error_code +DS28E83_DS28E84::computeAndReadPageAuthentication(int pageNum, KeySecret secret, + Page::const_span challenge, + Page::span hmac) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + const size_t requestSize = 3 + Page::size; + const size_t responseSize = 1 + Page::size; + uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)]; + buffer[0] = computeAndReadPageAuthenticationCmd; + buffer[1] = pageNum; + buffer[2] = secret; + copy(challenge.begin(), challenge.end(), buffer + 3); + span<uint_least8_t> response(buffer, responseSize); + const error_code result = + runCommand(make_span(buffer, requestSize), computeTimeMs, response); + if (!result) { + copy(response.begin(), response.end(), hmac.begin()); + } + return result; +} + +error_code +DS28E83_DS28E84::computeMultiblockHash(bool firstBlock, bool lastBlock, + span<const uint_least8_t> data) { + const span<const uint_least8_t>::index_type maxDataSize = 64; + + if (data.size() < 1 || data.size() > maxDataSize) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t buffer[2 + maxDataSize]; + buffer[0] = 0x33; + buffer[1] = 0; + if (firstBlock) { + buffer[1] |= 0x40; + } + if (lastBlock) { + buffer[1] |= 0x80; + } + copy(data.begin(), data.end(), buffer + 2); + return runCommand(make_span(buffer, 2 + data.size()), computeTimeMs); +} + +error_code DS28E83_DS28E84::verifyEcdsaSignature( + KeySecret key, bool authorityKey, GpioState gpioState, + Ecc256::Signature::const_span signature, span<const uint_least8_t> data) { + return verifyEcdsaSignature(key, authorityKey, DataInput, gpioState, + signature, data); +} + +error_code DS28E83_DS28E84::verifyEcdsaSignature( + KeySecret key, bool authorityKey, GpioState gpioState, + Ecc256::Signature::const_span signature, Page::const_span hash) { + return verifyEcdsaSignature(key, authorityKey, HashInput, gpioState, + signature, hash); +} + +error_code +DS28E83_DS28E84::verifyEcdsaSignature(KeySecret key, bool authorityKey, + GpioState gpioState, + Ecc256::Signature::const_span signature) { + return verifyEcdsaSignature(key, authorityKey, THASH, gpioState, signature, + span<const uint_least8_t>()); +} + +error_code DS28E83_DS28E84::verifyEcdsaSignature( + KeySecret key, bool authorityKey, HashType hashType, GpioState gpioState, + Ecc256::Signature::const_span signature, span<const uint_least8_t> buffer) { + const span<const uint_least8_t>::index_type maxBufferSize = 61; + + if (buffer.size() > maxBufferSize) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t request[2 + 2 * Ecc256::Scalar::size + maxBufferSize]; + uint_least8_t * requestIt = request; + *requestIt++ = 0x59; + switch (key) { + case KeySecretA: + if (authorityKey) { + *requestIt = 2; + } else { + *requestIt = 0; + } + break; + case KeySecretB: + if (authorityKey) { + *requestIt = 3; + } else { + *requestIt = 1; + } + break; + case KeySecretS: + if (!authorityKey) { + *requestIt = 4; + break; + } + // else: Go to default case. + default: + return make_error_code(InvalidParameterError); + } + *requestIt |= hashType << 3; + if (gpioState != Unchanged) { + *requestIt |= 0x40; + } + if (gpioState == Conducting) { + *requestIt |= 0x20; + } + requestIt = copy(signature.r.begin(), signature.r.end(), ++requestIt); + requestIt = copy(signature.s.begin(), signature.s.end(), requestIt); + requestIt = copy(buffer.begin(), buffer.end(), requestIt); + return runCommand(make_span(request, requestIt), + verifyEcdsaTimeMs + + (hashType == DataInput ? computeTimeMs : 0)); +} + +error_code DS28E83_DS28E84::authenticateEcdsaPublicKey( + KeySecret key, Ecc256::Signature::const_span cert, + span<const uint_least8_t> certCustomization) { + return authenticateEcdsaPublicKey(key, true, cert, certCustomization, NULL); +} + +error_code DS28E83_DS28E84::authenticateEcdsaPublicKey( + KeySecret key, bool authWrites, Ecc256::Signature::const_span cert, + span<const uint_least8_t> certCustomization, + span<const uint_least8_t> ecdhCustomization) { + return authenticateEcdsaPublicKey(key, authWrites, cert, certCustomization, + &ecdhCustomization); +} + +error_code DS28E83_DS28E84::authenticateEcdsaPublicKey( + KeySecret key, bool authWrites, Ecc256::Signature::const_span cert, + span<const uint_least8_t> certCustomization, + const span<const uint_least8_t> * ecdhCustomization) { + const span<const uint_least8_t>::index_type minCustomizationSize = 1; + const span<const uint_least8_t>::index_type maxCertCustomizationSize = 32; + const span<const uint_least8_t>::index_type maxEcdhCustomizationSize = 48; + const span<const uint_least8_t>::index_type maxTotalCustomizationSize = 60; + + if (!(certCustomization.size() >= minCustomizationSize && + certCustomization.size() <= maxCertCustomizationSize && + (!ecdhCustomization || + (ecdhCustomization->size() >= minCustomizationSize && + ecdhCustomization->size() <= maxEcdhCustomizationSize && + certCustomization.size() + ecdhCustomization->size() <= + maxTotalCustomizationSize)))) { + return make_error_code(InvalidParameterError); + } + + if (key == KeySecretS) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t + request[2 + 2 * Ecc256::Scalar::size + maxTotalCustomizationSize]; + uint_least8_t * requestIt = request; + *requestIt++ = 0xA8; + *requestIt++ = static_cast<uint_least8_t>( + ((certCustomization.size() - 1) << 3) | (key << 2) | + ((ecdhCustomization != NULL) << 1) | (authWrites << 0)); + requestIt = copy(cert.r.begin(), cert.r.end(), requestIt); + requestIt = copy(cert.s.begin(), cert.s.end(), requestIt); + requestIt = + copy(certCustomization.begin(), certCustomization.end(), requestIt); + int delay = verifyEcdsaTimeMs; + if (ecdhCustomization) { + const span<const uint_least8_t>::index_type certCustomizationPaddingSize = + maxCertCustomizationSize - certCustomization.size(); + std::fill_n(requestIt, certCustomizationPaddingSize, 0); + requestIt += certCustomizationPaddingSize; + requestIt = + copy(ecdhCustomization->begin(), ecdhCustomization->end(), requestIt); + delay += verifyEcdsaTimeMs; + } + return runCommand(make_span(request, requestIt), delay); +} + +error_code DS28E83_DS28E84::authenticatedEcdsaWriteMemory( + int pageNum, bool useKeyS, Page::const_span newPageData, + Ecc256::Signature::const_span signature) { + return authenticatedEcdsaWriteMemory(pageNum, useKeyS, newPageData, signature, + NULL); +} + +error_code DS28E83_DS28E84::authenticatedEcdsaWriteMemory( + int pageNum, bool useKeyS, Page::const_span newPageData, + Ecc256::Signature::const_span signature, + EncryptionChallenge::const_span challenge) { + return authenticatedEcdsaWriteMemory(pageNum, useKeyS, newPageData, signature, + &challenge); +} + +error_code DS28E83_DS28E84::authenticatedEcdsaWriteMemory( + int pageNum, bool useKeyS, Page::const_span newPageData, + Ecc256::Signature::const_span signature, + const EncryptionChallenge::const_span * challenge) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t request[2 + Page::size + 2 * Ecc256::Scalar::size + + EncryptionChallenge::size]; + uint_least8_t * requestIt = request; + *requestIt++ = 0x89; + *requestIt = pageNum; + if (useKeyS) { + *requestIt |= 0x80; + } + requestIt = copy(newPageData.begin(), newPageData.end(), ++requestIt); + requestIt = copy(signature.r.begin(), signature.r.end(), requestIt); + requestIt = copy(signature.s.begin(), signature.s.end(), requestIt); + int delay = verifyEcdsaTimeMs + writeMemoryTimeMs; + if (challenge) { + requestIt = copy(challenge->begin(), challenge->end(), requestIt); + delay += computeTimeMs; + } + return runCommand(make_span(request, requestIt), delay); +} + +error_code +DS28E83_DS28E84::authenticatedSha256WriteMemory(int pageNum, bool useSecretS, + Page::const_span newPageData, + Page::const_span hmac) { + return authenticatedSha256WriteMemory(pageNum, useSecretS, newPageData, hmac, + NULL); +} + +error_code DS28E83_DS28E84::authenticatedSha256WriteMemory( + int pageNum, bool useSecretS, Page::const_span newPageData, + Page::const_span hmac, EncryptionChallenge::const_span challenge) { + return authenticatedSha256WriteMemory(pageNum, useSecretS, newPageData, hmac, + &challenge); +} + +error_code DS28E83_DS28E84::authenticatedSha256WriteMemory( + int pageNum, bool useSecretS, Page::const_span newPageData, + Page::const_span hmac, const EncryptionChallenge::const_span * challenge) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t request[3 + 2 * Page::size + EncryptionChallenge::size]; + uint_least8_t * requestIt = request; + *requestIt++ = 0x99; + *requestIt++ = pageNum; + *requestIt++ = useSecretS ? 2 : 0; + requestIt = copy(newPageData.begin(), newPageData.end(), requestIt); + requestIt = copy(hmac.begin(), hmac.end(), requestIt); + int delay = writeMemoryTimeMs + computeTimeMs; + if (challenge) { + requestIt = copy(challenge->begin(), challenge->end(), requestIt); + delay += computeTimeMs; + } + return runCommand(make_span(request, requestIt), delay); +} + +error_code DS28E83_DS28E84::computeAndWriteSha256Secret( + int pageNum, KeySecret masterSecret, KeySecret destinationSecret, + Page::const_span partialSecret) { + if (pageNum < 0 || pageNum >= memoryPages) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t request[3 + Page::size]; + request[0] = 0x3C; + request[1] = pageNum; + request[2] = (destinationSecret << 2) | masterSecret; + copy(partialSecret.begin(), partialSecret.end(), request + 3); + return runCommand(request, writeMemoryTimeMs + computeTimeMs); +} + +error_code DS28E83_DS28E84::generateEcc256KeyPair(KeySecret key) { + if (key == KeySecretS) { + return make_error_code(InvalidParameterError); + } + + const uint_least8_t request[] = {0xCB, key == KeySecretB}; + return runCommand(request, generateEccKeyPairTimeMs); +} + +error_code DS28E83_DS28E84::readRng(span<uint_least8_t> data) { + const span<uint_least8_t>::index_type maxDataSize = 64; + if ((data.size() < 1) || (data.size() > maxDataSize)) { + return make_error_code(InvalidParameterError); + } + + uint_least8_t buffer[1 + maxDataSize]; + buffer[0] = readRngCmd; + buffer[1] = static_cast<uint_least8_t>(data.size() - 1); + span<uint_least8_t> response(buffer, 1 + data.size()); + const error_code result = + runCommand(make_span(buffer, 2), trngGenerationTimeMs, response); + if (!result) { + copy(response.begin(), response.end(), data.begin()); + } + return result; +} + +error_code DS28E83_DS28E84::entropyHealthTest() { + const uint_least8_t request[] = {readRngCmd, 0x80}; + return runCommand(request, trngOnDemandCheckTimeMs); +} + +error_code DS28E83_DS28E84::runCommand(span<const uint_least8_t> request, + int delayTime, + span<uint_least8_t> & response) { + const span<const uint_least8_t>::index_type responseInputSize = + response.size(); + error_code result = doRunCommand(request, delayTime, response); + if (result) { + return result; + } + if (response.empty()) { + return make_error_code(InvalidResponseError); + } + // Parse command result byte. + switch (response[0]) { + case 0xAA: + // Success response. + if (response.size() != responseInputSize) { + result = make_error_code(InvalidResponseError); + } + break; + + case 0x00: + result = make_error_code(AuthenticationError); + break; + + default: + result.assign(response[0], errorCategory()); + break; + } + response = response.subspan(1); + return result; +} + +error_code DS28E83_DS28E84::runCommand(span<const uint_least8_t> request, + int delayTime) { + uint_least8_t buffer; + span<uint_least8_t> response(&buffer, 1); + return runCommand(request, delayTime, response); +} + +const error_category & DS28E83_DS28E84::errorCategory() { + static class : public error_category { + public: + virtual const char * name() const { return "DS28E83_DS28E84"; } + + virtual std::string message(int condition) const { + switch (condition) { + case InvalidOperationError: + return "Invalid Operation Error"; + + case InvalidParameterError: + return "Invalid Parameter Error"; + + case InvalidSequenceError: + return "Invalid Sequence Error"; + + case AuthenticationError: + return "Authentication Error"; + + case InternalError: + return "Internal Error"; + + case DeviceDisabledError: + return "Device Disabled Error"; + + case InvalidResponseError: + return "Invalid Response Error"; + } + return defaultErrorMessage(condition); + } + } instance; + return instance; +} + +error_code DS28E84::decrementCounter() { + const uint_least8_t request = 0xC9; + return runCommand(make_span(&request, 1), writeMemoryTimeMs); +} + +error_code DS28E84::deviceStateControl(StateOperation operation) { + const uint_least8_t request[] = {0x55, operation == Backup}; + return runCommand(request, writeMemoryTimeMs); +} + +error_code computeMultiblockHash(DS28E83_DS28E84 & device, + span<const uint_least8_t> data) { + error_code result; + span<const uint_least8_t>::index_type dataIdx = 0; + while (dataIdx < data.size() && !result) { + const span<const uint_least8_t>::index_type remainingSize = + data.size() - dataIdx; + const span<const uint_least8_t>::index_type chunkSize = + std::min<span<const uint_least8_t>::index_type>(remainingSize, 64); + result = + device.computeMultiblockHash(dataIdx == 0, remainingSize == chunkSize, + data.subspan(dataIdx, chunkSize)); + dataIdx += chunkSize; + } + return result; +} + +error_code readRomIdAndManId(DS28E83_DS28E84 & device, RomId::span romId, + ManId::span manId) { + DS28E83_DS28E84::Page::array page; + error_code result = device.readMemory(DS28E83_DS28E84::romOptionsPage, page); + if (!result) { + const DS28E83_DS28E84::RomOptions romOptions(page); + copy(romOptions.romId(), romId); + copy(romOptions.manId(), manId); + } + return result; +} + +static void setAnonymous(RomId::span romId) { + std::fill(romId.begin(), romId.end(), 0xFF); +} + +DS28E83_DS28E84::PageAuthenticationData & +DS28E83_DS28E84::PageAuthenticationData::setAnonymousRomId() { + setAnonymous(romId()); + return *this; +} + +DS28E83_DS28E84::ComputeSecretData::ComputeSecretData() : data() { + setPageNum(0); + setManId(ManId::array()); +} + +DS28E83_DS28E84::ComputeSecretData & +DS28E83_DS28E84::ComputeSecretData::setManId(ManId::const_span manId) { + ManId::array validatedManId; + copy(manId, make_span(validatedManId)); + validatedManId[1] |= 0x80; + data.setManId(validatedManId); + return *this; +} + +DS28E83_DS28E84::DecryptionHmacData & +DS28E83_DS28E84::DecryptionHmacData::setAnonymousRomId() { + setAnonymous(romId()); + return *this; +} + +} // namespace MaximInterfaceDevices
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS28E83_DS28E84.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,1022 @@ +/******************************************************************************* +* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceDevices_DS28E83_DS28E84 +#define MaximInterfaceDevices_DS28E83_DS28E84 + +#include <stdint.h> +#include <MaximInterfaceCore/Algorithm.hpp> +#include <MaximInterfaceCore/array_span.hpp> +#include <MaximInterfaceCore/Ecc256.hpp> +#include <MaximInterfaceCore/FlagSet.hpp> +#include <MaximInterfaceCore/ManId.hpp> +#include <MaximInterfaceCore/Optional.hpp> +#include <MaximInterfaceCore/RomId.hpp> +#include <MaximInterfaceCore/RunCommand.hpp> +#include <MaximInterfaceCore/system_error.hpp> +#include "Config.hpp" + +namespace MaximInterfaceDevices { + +class DS28E83_DS28E84 { +public: + /// Device command results. + enum ErrorValue { + InternalError = 0x22, + InvalidSequenceError = 0x33, + InvalidOperationError = 0x55, + InvalidParameterError = 0x77, + DeviceDisabledError = 0x88, + AuthenticationError = 0x100, + InvalidResponseError ///< Command response does not match expected format. + }; + + /// @name Device memory pages + /// @{ + + static const int publicKeyAxPage = 28; + static const int publicKeyAyPage = 29; + static const int publicKeyBxPage = 30; + static const int publicKeyByPage = 31; + static const int authorityPublicKeyAxPage = 32; + static const int authorityPublicKeyAyPage = 33; + static const int authorityPublicKeyBxPage = 34; + static const int authorityPublicKeyByPage = 35; + static const int privateKeyAPage = 36; + static const int privateKeyBPage = 37; + static const int secretAPage = 38; + static const int secretBPage = 39; + static const int romOptionsPage = 40; + static const int gpioControlPage = 41; + static const int publicKeySxPage = 42; + static const int publicKeySyPage = 43; + + /// @} + + /// Key or secret to use for operation. + enum KeySecret { KeySecretA = 0, KeySecretB = 1, KeySecretS = 2 }; + + /// Available PIO states when verifying an ECDSA signature. + enum GpioState { Unchanged, Conducting, HighImpedance }; + + /// Holds a device memory page. + typedef Core::array_span<uint_least8_t, 32> Page; + + /// Challenge for an encrypted device memory page. + typedef Core::array_span<uint_least8_t, 8> EncryptionChallenge; + + // Format page authentication input data. + class PageAuthenticationData; + + // Format authenticated write input data. + class WriteAuthenticationData; + + // Format compute secret input data. + class ComputeSecretData; + + // Format decryption HMAC input data. + class DecryptionHmacData; + + // Format encryption HMAC input data. + class EncryptionHmacData; + + // Access fields in the ROM Options page. + class RomOptions; + + // Access fields in the GPIO Control page. + class GpioControl; + + /// Page protection types. + enum BlockProtectionType { + RP = 0x01, ///< Read protection. + WP = 0x02, ///< Write protection. + EM = 0x04, ///< EPROM emulation mode. + APH = 0x08, ///< Authentication Write Protection HMAC + EPH = 0x10, ///< Encryption and Authentication Write Protection HMAC + ECH = 0x40, ///< Encryption and write using shared key from ECDH + ECW = 0x80 ///< Authentication Write Protection ECDSA + }; + typedef Core::FlagSet<BlockProtectionType, 8> BlockProtection; + +protected: + explicit DS28E83_DS28E84(const Core::RunCommand & runCommand) + : doRunCommand(runCommand) {} + + ~DS28E83_DS28E84() {} + +public: + void setRunCommand(const Core::RunCommand & runCommand) { + doRunCommand = runCommand; + } + + /// @brief Write memory with no protection. + /// @param pageNum Number of page to write. + /// @param page Data to write. + MaximInterfaceDevices_EXPORT Core::error_code + writeMemory(int pageNum, Page::const_span page); + + /// @brief Read memory with no protection. + /// @param pageNum Number of page to read. + /// @param[out] page Data that was read. + MaximInterfaceDevices_EXPORT Core::error_code readMemory(int pageNum, + Page::span page); + + /// @brief Read memory with encryption. + /// @param pageNum Number of page to read from. + /// @param secret Secret to use for encryption. + /// @param[out] challenge Encryption challenge that was read. + /// @param[out] encryptedPage Encrypted page data that was read. + MaximInterfaceDevices_EXPORT Core::error_code + encryptedReadMemory(int pageNum, KeySecret secret, + EncryptionChallenge::span challenge, + Page::span encryptedPage); + + /// @brief Read the protection settings of a block. + /// @param blockNum Number of block to read. + /// @param[out] keySecret Secret key set on the block or empty if not set. + /// @param[out] protection Protection that was read. + MaximInterfaceDevices_EXPORT Core::error_code + readBlockProtection(int blockNum, Core::Optional<KeySecret> & keySecret, + BlockProtection & protection); + + /// @brief Set the protection settings of a block. + /// @param blockNum Number of block to write. + /// @param keySecret Secret/Key A or B. + /// @param protection Protection to write. + MaximInterfaceDevices_EXPORT Core::error_code + setBlockProtection(int blockNum, KeySecret keySecret, + const BlockProtection & protection); + + /// @brief Compute and read page authentication with ECDSA. + /// @param pageNum Number of page to authenticate. + /// @param key + /// Private key to use for authentication. + /// Key S cannot be used with this command. + /// @param challenge Random challenge used to prevent replay attacks. + /// @param[out] signature Computed page signature. + MaximInterfaceDevices_EXPORT Core::error_code + computeAndReadPageAuthentication(int pageNum, KeySecret key, + Page::const_span challenge, + Core::Ecc256::Signature::span signature); + + /// @brief Compute and read page authentication with HMAC. + /// @param pageNum Number of page to authenticate. + /// @param secret + /// Secret to use for authentication. + /// Secret S cannot be used with this command. + /// @param challenge Random challenge used to prevent replay attacks. + /// @param[out] hmac Computed page HMAC. + MaximInterfaceDevices_EXPORT Core::error_code + computeAndReadPageAuthentication(int pageNum, KeySecret secret, + Page::const_span challenge, Page::span hmac); + + /// @brief Compute a hash over multiple blocks. + /// @param firstBlock True if this is the first block being hashed. + /// @param lastBlock True if this is the last block being hashed. + /// @param data + /// Data block to hash. Should be 64 bytes unless this is the last block. + MaximInterfaceDevices_EXPORT Core::error_code + computeMultiblockHash(bool firstBlock, bool lastBlock, + Core::span<const uint_least8_t> data); + + /// @brief Verify ECDSA signature with data input. + /// @param key Public key to use for verification. + /// @param authorityKey Use the authority key instead of the standard key. + /// @param gpioState New state of the GPIO pin if verification successful. + /// @param signature Signature to verify. + /// @param data Data to verify with length from 1 to 64. + MaximInterfaceDevices_EXPORT Core::error_code + verifyEcdsaSignature(KeySecret key, bool authorityKey, GpioState gpioState, + Core::Ecc256::Signature::const_span signature, + Core::span<const uint_least8_t> data); + + /// @brief Verify ECDSA signature with hash input. + /// @param key Public key to use for verification. + /// @param authorityKey Use the authority key instead of the standard key. + /// @param gpioState New state of the GPIO pin if verification successful. + /// @param signature Signature to verify. + /// @param hash Hash of data to verify. + MaximInterfaceDevices_EXPORT Core::error_code + verifyEcdsaSignature(KeySecret key, bool authorityKey, GpioState gpioState, + Core::Ecc256::Signature::const_span signature, + Page::const_span hash); + + /// @brief + /// Verify ECDSA signature with THASH input from Compute Multiblock Hash. + /// @param key Public key to use for verification. + /// @param authorityKey Use the authority key instead of the standard key. + /// @param gpioState New state of the GPIO pin if verification successful. + /// @param signature Signature to verify. + MaximInterfaceDevices_EXPORT Core::error_code + verifyEcdsaSignature(KeySecret key, bool authorityKey, GpioState gpioState, + Core::Ecc256::Signature::const_span signature); + + /// @brief Authenticate a public key for authenticated writes. + /// @param key + /// Authority key to use for authentication. Key A or B can be selected. + /// @param cert Certificate to use for authentication of Public Key S. + /// @param certCustomization + /// Certificate customization with length from 1 to 32. + MaximInterfaceDevices_EXPORT Core::error_code + authenticateEcdsaPublicKey(KeySecret key, + Core::Ecc256::Signature::const_span cert, + Core::span<const uint_least8_t> certCustomization); + + /// @brief + /// Authenticate a public key for ECDH and optionally authenticated writes. + /// @param key + /// Keys to use for authentication and ECDH key exchange. + /// Key A or B can be selected. + /// @param authWrites True to select authentication for writes. + /// @param cert Certificate to use for authentication of Public Key S. + /// @param certCustomization + /// Certificate customization with length from 1 to 32. + /// @param ecdhCustomization ECDH customization with length from 1 to 48. + /// @note The maximum total customization length is 60 bytes. + MaximInterfaceDevices_EXPORT Core::error_code + authenticateEcdsaPublicKey(KeySecret key, bool authWrites, + Core::Ecc256::Signature::const_span cert, + Core::span<const uint_least8_t> certCustomization, + Core::span<const uint_least8_t> ecdhCustomization); + + /// @brief Write with ECDSA authentication. + /// @param pageNum Number of page to write. + /// @param useKeyS + /// Use Public Key S instead of the authority key set in the block protection. + /// @param newPageData Data to write. + /// @param signature Signature to use for authentication of page data. + MaximInterfaceDevices_EXPORT Core::error_code + authenticatedEcdsaWriteMemory(int pageNum, bool useKeyS, + Page::const_span newPageData, + Core::Ecc256::Signature::const_span signature); + + /// @brief Write with ECDSA authentication and encryption. + /// @param pageNum Number of page to write. + /// @param useKeyS + /// Use Public Key S instead of the authority key set in the block protection. + /// @param newPageData Encrypted data to write. + /// @param signature Signature to use for authentication of page data. + /// @param challenge Challenge to use for decryption of page data. + MaximInterfaceDevices_EXPORT Core::error_code + authenticatedEcdsaWriteMemory(int pageNum, bool useKeyS, + Page::const_span newPageData, + Core::Ecc256::Signature::const_span signature, + EncryptionChallenge::const_span challenge); + + /// @brief Write with SHA-256 HMAC authentication. + /// @param pageNum Number of page to write. + /// @param useSecretS + /// Use Secret S instead of the secret set in the block protection. + /// @param newPageData Data to write. + /// @param hmac HMAC to use for authentication of page data. + MaximInterfaceDevices_EXPORT Core::error_code + authenticatedSha256WriteMemory(int pageNum, bool useSecretS, + Page::const_span newPageData, + Page::const_span hmac); + + /// @brief Write with SHA-256 HMAC authentication and encryption. + /// @param pageNum Number of page to write. + /// @param useSecretS + /// Use Secret S instead of the secret set in the block protection. + /// @param newPageData Data to write. + /// @param hmac HMAC to use for authentication of page data. + /// @param challenge Challenge to use for decryption of page data. + MaximInterfaceDevices_EXPORT Core::error_code authenticatedSha256WriteMemory( + int pageNum, bool useSecretS, Page::const_span newPageData, + Page::const_span hmac, EncryptionChallenge::const_span challenge); + + /// @brief Compute a derivative SHA-256 secret from an existing secret. + /// @param pageNum Number of page to use in computation. + /// @param masterSecret Master secret to use in computation. + /// @param destinationSecret + /// Destination secret to receive the computation result. + /// @param partialSecret Partial secret to use in computation. + MaximInterfaceDevices_EXPORT Core::error_code + computeAndWriteSha256Secret(int pageNum, KeySecret masterSecret, + KeySecret destinationSecret, + Page::const_span partialSecret); + + /// @brief Generate a new ECDSA key pair. + /// @param key Key to generate. Key S cannot be used with this command. + MaximInterfaceDevices_EXPORT Core::error_code + generateEcc256KeyPair(KeySecret key); + + /// @brief Read a block of random data from the RNG. + /// @param[out] data Random data from RNG with length from 1 to 64. + MaximInterfaceDevices_EXPORT Core::error_code + readRng(Core::span<uint_least8_t> data); + + /// Run entropy health test on the RNG. + MaximInterfaceDevices_EXPORT Core::error_code entropyHealthTest(); + + MaximInterfaceDevices_EXPORT static const Core::error_category & + errorCategory(); + +protected: + MaximInterfaceDevices_EXPORT Core::error_code + runCommand(Core::span<const uint_least8_t> request, int delayTime, + Core::span<uint_least8_t> & response); + + MaximInterfaceDevices_EXPORT Core::error_code + runCommand(Core::span<const uint_least8_t> request, int delayTime); + +private: + enum HashType { HashInput, DataInput, THASH }; + + Core::error_code + verifyEcdsaSignature(KeySecret key, bool authorityKey, HashType hashType, + GpioState gpioState, + Core::Ecc256::Signature::const_span signature, + Core::span<const uint_least8_t> buffer); + + Core::error_code authenticateEcdsaPublicKey( + KeySecret key, bool authWrites, Core::Ecc256::Signature::const_span cert, + Core::span<const uint_least8_t> certCustomization, + const Core::span<const uint_least8_t> * ecdhCustomization); + + Core::error_code authenticatedEcdsaWriteMemory( + int pageNum, bool useKeyS, Page::const_span newPageData, + Core::Ecc256::Signature::const_span signature, + const EncryptionChallenge::const_span * challenge); + + Core::error_code authenticatedSha256WriteMemory( + int pageNum, bool useSecretS, Page::const_span newPageData, + Page::const_span hmac, const EncryptionChallenge::const_span * challenge); + + Core::RunCommand doRunCommand; +}; + +inline Core::error_code make_error_code(DS28E83_DS28E84::ErrorValue e) { + return Core::error_code(e, DS28E83_DS28E84::errorCategory()); +} + +class DS28E83 : public DS28E83_DS28E84 { +public: + static const int memoryPages = 44; + static const int protectionBlocks = 9; + + explicit DS28E83(const Core::RunCommand & runCommand) + : DS28E83_DS28E84(runCommand) {} +}; + +class DS28E84 : public DS28E83_DS28E84 { +public: + /// @name Device memory pages + /// @{ + + static const int publicKeySxBackupPage = 104; + static const int publicKeySyBackupPage = 105; + static const int decrementCounterPage = 106; + + /// @} + + static const int memoryPages = 107; + static const int protectionBlocks = 24; + + enum StateOperation { Backup, Restore }; + + explicit DS28E84(const Core::RunCommand & runCommand) + : DS28E83_DS28E84(runCommand) {} + + /// Decrement the decrement-only counter. + MaximInterfaceDevices_EXPORT Core::error_code decrementCounter(); + + /// Back up or restore the state of the device to non-volatile memory. + MaximInterfaceDevices_EXPORT Core::error_code + deviceStateControl(StateOperation operation); +}; + +/// @brief +/// Hash arbitrary length data with successive Compute Multiblock Hash commands. +/// @param device Device for computation. +/// @param data Data to hash. +MaximInterfaceDevices_EXPORT Core::error_code +computeMultiblockHash(DS28E83_DS28E84 & device, + Core::span<const uint_least8_t> data); + +/// @brief +/// Read the device ROM ID and MAN ID using the Read Memory command on the +/// ROM Options page. +/// @param device Device to read. +/// @param[out] romId Read ROM ID valid when operation is successful. +/// @param[out] manId Read MAN ID valid when operation is successful. +MaximInterfaceDevices_EXPORT Core::error_code +readRomIdAndManId(DS28E83_DS28E84 & device, Core::RomId::span romId, + Core::ManId::span manId); + +/// Format page authentication input data. +class DS28E83_DS28E84::PageAuthenticationData { +public: + typedef Core::array_span<uint_least8_t, Core::RomId::size + 2 * Page::size + + 1 + Core::ManId::size> + Result; + + PageAuthenticationData() : result_() {} + + /// Formatted data result. + Result::const_span result() const { return result_; } + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { + return make_span(result_).subspan<romIdIdx, Core::RomId::size>(); + } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { + return const_cast<PageAuthenticationData &>(*this).romId(); + } + + /// Set ROM ID. + PageAuthenticationData & setRomId(Core::RomId::const_span romId) { + copy(romId, this->romId()); + return *this; + } + + /// Set ROM ID for use in anonymous mode. + MaximInterfaceDevices_EXPORT PageAuthenticationData & setAnonymousRomId(); + + /// @} + + /// @name Page + /// @brief Data from a device memory page. + /// @{ + + /// Get mutable page. + Page::span page() { + return make_span(result_).subspan<pageIdx, Page::size>(); + } + + /// Get immutable page. + Page::const_span page() const { + return const_cast<PageAuthenticationData &>(*this).page(); + } + + /// Set page. + PageAuthenticationData & setPage(Page::const_span page) { + copy(page, this->page()); + return *this; + } + + /// @} + + /// @name Challenge + /// @brief Random challenge used to prevent replay attacks. + /// @{ + + /// Get mutable Challenge. + Page::span challenge() { + return make_span(result_).subspan<challengeIdx, Page::size>(); + } + + /// Get immutable Challenge. + Page::const_span challenge() const { + return const_cast<PageAuthenticationData &>(*this).challenge(); + } + + /// Set Challenge. + PageAuthenticationData & setChallenge(Page::const_span challenge) { + copy(challenge, this->challenge()); + return *this; + } + + /// @} + + /// @name Page number + /// @brief Number of the page to use data from. + /// @{ + + /// Get page number. + int pageNum() const { return result_[pageNumIdx]; } + + /// Set page number. + PageAuthenticationData & setPageNum(int pageNum) { + result_[pageNumIdx] = pageNum; + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get mutable MAN ID. + Core::ManId::span manId() { + return make_span(result_).subspan<manIdIdx, Core::ManId::size>(); + } + + /// Get immutable MAN ID. + Core::ManId::const_span manId() const { + return const_cast<PageAuthenticationData &>(*this).manId(); + } + + /// Set MAN ID. + PageAuthenticationData & setManId(Core::ManId::const_span manId) { + copy(manId, this->manId()); + return *this; + } + + /// @} + +private: + typedef Result::span::index_type index; + + static const index romIdIdx = 0; + static const index pageIdx = romIdIdx + Core::RomId::size; + static const index challengeIdx = pageIdx + Page::size; + static const index pageNumIdx = challengeIdx + Page::size; + static const index manIdIdx = pageNumIdx + 1; + + Result::array result_; +}; + +/// Format authenticated write input data. +class DS28E83_DS28E84::WriteAuthenticationData { +public: + typedef PageAuthenticationData::Result Result; + + WriteAuthenticationData() : data() { setPageNum(0); } + + /// Formatted data result. + Result::const_span result() const { return data.result(); } + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { return data.romId(); } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { return data.romId(); } + + /// Set ROM ID. + WriteAuthenticationData & setRomId(Core::RomId::const_span romId) { + data.setRomId(romId); + return *this; + } + + /// Set ROM ID for use in anonymous mode. + WriteAuthenticationData & setAnonymousRomId() { + data.setAnonymousRomId(); + return *this; + } + + /// @} + + /// @name Old page + /// @brief Existing data contained in the page. + /// @{ + + /// Get mutable old page. + Page::span oldPage() { return data.page(); } + + /// Get immutable old page. + Page::const_span oldPage() const { return data.page(); } + + /// Set old page. + WriteAuthenticationData & setOldPage(Page::const_span oldPage) { + data.setPage(oldPage); + return *this; + } + + /// @} + + /// @name New page + /// @brief New data to write to the page. + /// @{ + + /// Get mutable new page. + Page::span newPage() { return data.challenge(); } + + /// Get immutable new page. + Page::const_span newPage() const { return data.challenge(); } + + /// Set new page. + WriteAuthenticationData & setNewPage(Page::const_span newPage) { + data.setChallenge(newPage); + return *this; + } + + /// @} + + /// @name Page number + /// @brief Page number for write operation. + /// @{ + + /// Get page number. + int pageNum() const { return data.pageNum() & 0x7F; } + + /// Set page number. + WriteAuthenticationData & setPageNum(int pageNum) { + data.setPageNum(pageNum | 0x80); + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get mutable MAN ID. + Core::ManId::span manId() { return data.manId(); } + + /// Get immutable MAN ID. + Core::ManId::const_span manId() const { return data.manId(); } + + /// Set MAN ID. + WriteAuthenticationData & setManId(Core::ManId::const_span manId) { + data.setManId(manId); + return *this; + } + + /// @} + +private: + PageAuthenticationData data; +}; + +/// Format compute secret input data. +class DS28E83_DS28E84::ComputeSecretData { +public: + typedef PageAuthenticationData::Result Result; + + MaximInterfaceDevices_EXPORT ComputeSecretData(); + + /// Formatted data result. + Result::const_span result() const { return data.result(); } + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { return data.romId(); } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { return data.romId(); } + + /// Set ROM ID. + ComputeSecretData & setRomId(Core::RomId::const_span romId) { + data.setRomId(romId); + return *this; + } + + /// @} + + /// @name Binding Data + /// @brief Binding Data contained in the selected page. + /// @{ + + /// Get mutable Binding Data. + Page::span bindingData() { return data.page(); } + + /// Get immutable Binding Data. + Page::const_span bindingData() const { return data.page(); } + + /// Set Binding Data. + ComputeSecretData & setBindingData(Page::const_span bindingData) { + data.setPage(bindingData); + return *this; + } + + /// @} + + /// @name Partial Secret + /// @brief Partial Secret used for customization. + /// @{ + + /// Get mutable Partial Secret. + Page::span partialSecret() { return data.challenge(); } + + /// Get immutable Partial Secret. + Page::const_span partialSecret() const { return data.challenge(); } + + /// Set Partial Secret. + ComputeSecretData & setPartialSecret(Page::const_span partialSecret) { + data.setChallenge(partialSecret); + return *this; + } + + /// @} + + /// @name Page number + /// @brief Page number for Binding Data. + /// @{ + + /// Get page number. + int pageNum() const { return data.pageNum() & 0x3F; } + + /// Set page number. + ComputeSecretData & setPageNum(int pageNum) { + data.setPageNum(pageNum | 0xC0); + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get immutable MAN ID. + Core::ManId::const_span manId() const { return data.manId(); } + + /// Set MAN ID. + MaximInterfaceDevices_EXPORT ComputeSecretData & + setManId(Core::ManId::const_span manId); + + /// @} + +private: + PageAuthenticationData data; +}; + +/// Format decryption HMAC input data. +class DS28E83_DS28E84::DecryptionHmacData { +public: + typedef Core::array_span<uint_least8_t, EncryptionChallenge::size + + Core::RomId::size + 1 + + Core::ManId::size> + Result; + + DecryptionHmacData() : result_() {} + + /// Formatted data result. + Result::const_span result() const { return result_; } + + /// @name Encryption Challenge + /// @brief Random challenge used to prevent replay attacks. + /// @{ + + /// Get mutable Encryption Challenge. + EncryptionChallenge::span encryptionChallenge() { + return make_span(result_) + .subspan<encryptionChallengeIdx, EncryptionChallenge::size>(); + } + + /// Get immutable Encryption Challenge. + EncryptionChallenge::const_span encryptionChallenge() const { + return const_cast<DecryptionHmacData &>(*this).encryptionChallenge(); + } + + /// Set Encryption Challenge. + DecryptionHmacData & + setEncryptionChallenge(EncryptionChallenge::const_span encryptionChallenge) { + copy(encryptionChallenge, this->encryptionChallenge()); + return *this; + } + + /// @} + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { + return make_span(result_).subspan<romIdIdx, Core::RomId::size>(); + } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { + return const_cast<DecryptionHmacData &>(*this).romId(); + } + + /// Set ROM ID. + DecryptionHmacData & setRomId(Core::RomId::const_span romId) { + copy(romId, this->romId()); + return *this; + } + + /// Set ROM ID for use in anonymous mode. + MaximInterfaceDevices_EXPORT DecryptionHmacData & setAnonymousRomId(); + + /// @} + + /// @name Page number + /// @brief Number of the page to use data from. + /// @{ + + /// Get page number. + int pageNum() const { return result_[pageNumIdx]; } + + /// Set page number. + DecryptionHmacData & setPageNum(int pageNum) { + result_[pageNumIdx] = pageNum; + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get mutable MAN ID. + Core::ManId::span manId() { + return make_span(result_).subspan<manIdIdx, Core::ManId::size>(); + } + + /// Get immutable MAN ID. + Core::ManId::const_span manId() const { + return const_cast<DecryptionHmacData &>(*this).manId(); + } + + /// Set MAN ID. + DecryptionHmacData & setManId(Core::ManId::const_span manId) { + copy(manId, this->manId()); + return *this; + } + + /// @} + +private: + typedef Result::span::index_type index; + + static const index encryptionChallengeIdx = 0; + static const index romIdIdx = + encryptionChallengeIdx + EncryptionChallenge::size; + static const index pageNumIdx = romIdIdx + Core::RomId::size; + static const index manIdIdx = pageNumIdx + 1; + + Result::array result_; +}; + +/// Format encryption HMAC input data. +class DS28E83_DS28E84::EncryptionHmacData { +public: + typedef DecryptionHmacData::Result Result; + + EncryptionHmacData() : data() { setPageNum(0); } + + /// Formatted data result. + Result::const_span result() const { return data.result(); } + + /// @name Encryption Challenge + /// @brief Random challenge used to prevent replay attacks. + /// @{ + + /// Get mutable Encryption Challenge. + EncryptionChallenge::span encryptionChallenge() { + return data.encryptionChallenge(); + } + + /// Get immutable Encryption Challenge. + EncryptionChallenge::const_span encryptionChallenge() const { + return data.encryptionChallenge(); + } + + /// Set Encryption Challenge. + EncryptionHmacData & + setEncryptionChallenge(EncryptionChallenge::const_span encryptionChallenge) { + data.setEncryptionChallenge(encryptionChallenge); + return *this; + } + + /// @} + + /// @name ROM ID + /// @brief 1-Wire ROM ID of the device. + /// @{ + + /// Get mutable ROM ID. + Core::RomId::span romId() { return data.romId(); } + + /// Get immutable ROM ID. + Core::RomId::const_span romId() const { return data.romId(); } + + /// Set ROM ID. + EncryptionHmacData & setRomId(Core::RomId::const_span romId) { + data.setRomId(romId); + return *this; + } + + /// Set ROM ID for use in anonymous mode. + EncryptionHmacData & setAnonymousRomId() { + data.setAnonymousRomId(); + return *this; + } + + /// @} + + /// @name Page number + /// @brief Number of the page to use data from. + /// @{ + + /// Get page number. + int pageNum() const { return data.pageNum() & 0x7F; } + + /// Set page number. + EncryptionHmacData & setPageNum(int pageNum) { + data.setPageNum(pageNum | 0x80); + return *this; + } + + /// @} + + /// @name MAN ID + /// @brief Manufacturer ID of the device. + /// @{ + + /// Get mutable MAN ID. + Core::ManId::span manId() { return data.manId(); } + + /// Get immutable MAN ID. + Core::ManId::const_span manId() const { return data.manId(); } + + /// Set MAN ID. + EncryptionHmacData & setManId(Core::ManId::const_span manId) { + data.setManId(manId); + return *this; + } + + /// @} + +private: + DecryptionHmacData data; +}; + +/// Access fields in the ROM Options page. +class DS28E83_DS28E84::RomOptions { +public: + explicit RomOptions(Page::span page) : page(page) {} + + bool anonymous() const { return page[anonymousIdx] == anonymousValue; } + + void setAnonymous(bool anonymous) { + page[anonymousIdx] = (anonymous ? anonymousValue : 0); + } + + Core::ManId::const_span manId() const { + return page.subspan<22, Core::ManId::size>(); + } + + Core::RomId::const_span romId() const { + return page.subspan<24, Core::RomId::size>(); + } + +private: + static const Page::span::index_type anonymousIdx = 1; + static const Page::span::value_type anonymousValue = 0xAA; + + Page::span page; +}; + +/// Access fields in the GPIO Control page. +class DS28E83_DS28E84::GpioControl { +public: + explicit GpioControl(Page::span page) : page(page) {} + + bool conducting() const { return page[conductingIdx] == conductingValue; } + + void setConducting(bool conducting) { + page[conductingIdx] = (conducting ? conductingValue : 0x55); + } + + bool level() const { return page[2] == 0x55; } + +private: + static const Page::span::index_type conductingIdx = 0; + static const Page::span::value_type conductingValue = 0xAA; + + Page::span page; +}; + +} // namespace MaximInterfaceDevices + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS9400.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,91 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include "DS9400.hpp" + +namespace MaximInterfaceDevices { + +using namespace Core; + +error_code DS9400::waitAwake() { + error_code result; + uint_least8_t data; + do { + result = uart->readByte(data); + } while (!result && data != 0xA5); + return result; +} + +error_code DS9400::start() { return uart->writeByte('S'); } + +error_code DS9400::start(uint_least8_t address) { + error_code result = start(); + if (!result) { + result = writeByte(address); + } + return result; +} + +error_code DS9400::stop() { return uart->writeByte('P'); } + +error_code DS9400::writeByte(uint_least8_t data) { + const uint_least8_t packet[] = {'Q', data}; + error_code result = uart->clearReadBuffer(); + if (!result) { + result = uart->writeBlock(packet); + if (!result) { + result = uart->readByte(data); + if (!result && data != 0) { + result = make_error_code(I2CMaster::NackError); + } + } + } + return result; +} + +error_code DS9400::readByte(AckStatus status, uint_least8_t & data) { + error_code result = uart->clearReadBuffer(); + if (!result) { + result = uart->writeByte(status == Ack ? 'R' : 'N'); + if (!result) { + result = uart->readByte(data); + } + } + return result; +} + +error_code DS9400::configure(uint_least8_t config) { + const uint_least8_t packet[] = {'C', config}; + return uart->writeBlock(packet); +} + +} // namespace MaximInterfaceDevices
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS9400.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,72 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceDevices_DS9400 +#define MaximInterfaceDevices_DS9400 + +#include <MaximInterfaceCore/I2CMaster.hpp> +#include <MaximInterfaceCore/Uart.hpp> +#include "Config.hpp" + +namespace MaximInterfaceDevices { + +class DS9400 : public Core::I2CMaster { +public: + explicit DS9400(Core::Uart & uart) : uart(&uart) {} + + void setUart(Core::Uart & uart) { this->uart = &uart; } + + MaximInterfaceDevices_EXPORT Core::error_code waitAwake(); + + MaximInterfaceDevices_EXPORT Core::error_code start(); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + start(uint_least8_t address); + + MaximInterfaceDevices_EXPORT virtual Core::error_code stop(); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + writeByte(uint_least8_t data); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + readByte(AckStatus status, uint_least8_t & data); + +protected: + MaximInterfaceDevices_EXPORT Core::error_code configure(uint_least8_t config); + +private: + Core::Uart * uart; +}; + +} // namespace MaximInterfaceDevices + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS9481P_300.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,249 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include <MaximInterfaceCore/Error.hpp> +#include "DS9481P_300.hpp" + +namespace MaximInterfaceDevices { + +using namespace Core; + +DS9481P_300::DS9481P_300(Sleep & sleep, SerialPort & serialPort) + : serialPort(&serialPort), currentBus(OneWire), ds2480b(sleep, serialPort), + oneWireMaster_(*this), ds9400(serialPort), i2cMaster_(*this) {} + +error_code DS9481P_300::connect(const std::string & portName) { + error_code result = serialPort->connect(portName); + if (!result) { + result = selectOneWire(); + if (result) { + serialPort->disconnect(); + } else { + currentBus = OneWire; + } + } + return result; +} + +error_code DS9481P_300::disconnect() { return serialPort->disconnect(); } + +bool DS9481P_300::connected() const { return serialPort->connected(); } + +std::string DS9481P_300::portName() const { return serialPort->portName(); } + +error_code DS9481P_300::selectOneWire() { + // Escape DS9400 mode. + error_code result = ds9400.escape(); + if (!result) { + result = ds2480b.initialize(); + } + return result; +} + +error_code DS9481P_300::selectBus(Bus newBus) { + error_code result; + if (currentBus != newBus) { + switch (currentBus) { + case OneWire: // Next bus I2C. + // Escape DS2480 Mode. + result = ds2480b.escape(); + if (!result) { + // Wait for awake notification. + result = ds9400.waitAwake(); + } + break; + + case I2C: // Next bus OneWire. + result = selectOneWire(); + break; + } + if (!result) { + currentBus = newBus; + } + } + return result; +} + +error_code DS9481P_300::OneWireMaster::reset() { + error_code result = parent->selectBus(OneWire); + if (!result) { + result = OneWireMasterDecorator::reset(); + } + return result; +} + +error_code DS9481P_300::OneWireMaster::touchBitSetLevel(bool & sendRecvBit, + Level afterLevel) { + error_code result = parent->selectBus(OneWire); + if (!result) { + result = OneWireMasterDecorator::touchBitSetLevel(sendRecvBit, afterLevel); + } + return result; +} + +error_code DS9481P_300::OneWireMaster::writeByteSetLevel(uint_least8_t sendByte, + Level afterLevel) { + error_code result = parent->selectBus(OneWire); + if (!result) { + result = OneWireMasterDecorator::writeByteSetLevel(sendByte, afterLevel); + } + return result; +} + +error_code +DS9481P_300::OneWireMaster::readByteSetLevel(uint_least8_t & recvByte, + Level afterLevel) { + error_code result = parent->selectBus(OneWire); + if (!result) { + result = OneWireMasterDecorator::readByteSetLevel(recvByte, afterLevel); + } + return result; +} + +error_code +DS9481P_300::OneWireMaster::writeBlock(span<const uint_least8_t> sendBuf) { + error_code result = parent->selectBus(OneWire); + if (!result) { + result = OneWireMasterDecorator::writeBlock(sendBuf); + } + return result; +} + +error_code DS9481P_300::OneWireMaster::readBlock(span<uint_least8_t> recvBuf) { + error_code result = parent->selectBus(OneWire); + if (!result) { + result = OneWireMasterDecorator::readBlock(recvBuf); + } + return result; +} + +error_code DS9481P_300::OneWireMaster::setSpeed(Speed newSpeed) { + error_code result = parent->selectBus(OneWire); + if (!result) { + result = OneWireMasterDecorator::setSpeed(newSpeed); + } + return result; +} + +error_code DS9481P_300::OneWireMaster::setLevel(Level newLevel) { + error_code result = parent->selectBus(OneWire); + if (!result) { + result = OneWireMasterDecorator::setLevel(newLevel); + } + return result; +} + +error_code DS9481P_300::OneWireMaster::triplet(TripletData & data) { + error_code result = parent->selectBus(OneWire); + if (!result) { + result = OneWireMasterDecorator::triplet(data); + } + return result; +} + +error_code DS9481P_300::I2CMaster::start(uint_least8_t address) { + error_code result = parent->selectBus(I2C); + if (!result) { + result = I2CMasterDecorator::start(address); + } + return result; +} + +error_code DS9481P_300::I2CMaster::stop() { + error_code result = parent->selectBus(I2C); + if (!result) { + result = I2CMasterDecorator::stop(); + } + return result; +} + +error_code DS9481P_300::I2CMaster::writeByte(uint_least8_t data) { + error_code result = parent->selectBus(I2C); + if (!result) { + result = I2CMasterDecorator::writeByte(data); + } + return result; +} + +error_code DS9481P_300::I2CMaster::writeBlock(span<const uint_least8_t> data) { + error_code result = parent->selectBus(I2C); + if (!result) { + result = I2CMasterDecorator::writeBlock(data); + } + return result; +} + +error_code DS9481P_300::I2CMaster::doWritePacket(uint_least8_t address, + span<const uint_least8_t> data, + bool sendStop) { + error_code result = parent->selectBus(I2C); + if (!result) { + result = I2CMasterDecorator::doWritePacket(address, data, sendStop); + } + return result; +} + +error_code DS9481P_300::I2CMaster::readByte(AckStatus status, + uint_least8_t & data) { + error_code result = parent->selectBus(I2C); + if (!result) { + result = I2CMasterDecorator::readByte(status, data); + } + return result; +} + +error_code DS9481P_300::I2CMaster::readBlock(AckStatus status, + span<uint_least8_t> data) { + error_code result = parent->selectBus(I2C); + if (!result) { + result = I2CMasterDecorator::readBlock(status, data); + } + return result; +} + +error_code DS9481P_300::I2CMaster::doReadPacket(uint_least8_t address, + span<uint_least8_t> data, + bool sendStop) { + error_code result = parent->selectBus(I2C); + if (!result) { + result = I2CMasterDecorator::doReadPacket(address, data, sendStop); + } + return result; +} + +error_code DS9481P_300::DS2480BWithEscape::escape() { + return sendCommand(0xE5); +} + +error_code DS9481P_300::DS9400WithEscape::escape() { return configure('O'); } + +} // namespace MaximInterfaceDevices
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceDevices/DS9481P_300.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,179 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceDevices_DS9481P_300 +#define MaximInterfaceDevices_DS9481P_300 + +#include <MaximInterfaceCore/I2CMasterDecorator.hpp> +#include <MaximInterfaceCore/OneWireMasterDecorator.hpp> +#include <MaximInterfaceCore/SerialPort.hpp> +#include <MaximInterfaceCore/Sleep.hpp> +#include "DS2480B.hpp" +#include "DS9400.hpp" +#include "Config.hpp" + +namespace MaximInterfaceDevices { + +/// DS9481P-300 USB to 1-Wire and I2C adapter. +class DS9481P_300 { +public: + MaximInterfaceDevices_EXPORT DS9481P_300(Core::Sleep & sleep, + Core::SerialPort & serialPort); + + void setSleep(Core::Sleep & sleep) { ds2480b.setSleep(sleep); } + + void setSerialPort(Core::SerialPort & serialPort) { + this->serialPort = &serialPort; + ds2480b.setUart(serialPort); + ds9400.setUart(serialPort); + } + + MaximInterfaceDevices_EXPORT Core::error_code + connect(const std::string & portName); + + MaximInterfaceDevices_EXPORT Core::error_code disconnect(); + + MaximInterfaceDevices_EXPORT bool connected() const; + + MaximInterfaceDevices_EXPORT std::string portName() const; + + /// Access the 1-Wire master when connected to an adapter. + Core::OneWireMaster & oneWireMaster() { return oneWireMaster_; } + + /// Access the I2C master when connected to an adapter. + Core::I2CMaster & i2cMaster() { return i2cMaster_; } + +private: + class OneWireMaster : public Core::OneWireMasterDecorator { + public: + explicit OneWireMaster(DS9481P_300 & parent) + : OneWireMasterDecorator(parent.ds2480b), parent(&parent) {} + + MaximInterfaceDevices_EXPORT virtual Core::error_code reset(); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + touchBitSetLevel(bool & sendRecvBit, Level afterLevel); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + writeByteSetLevel(uint_least8_t sendByte, Level afterLevel); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + readByteSetLevel(uint_least8_t & recvByte, Level afterLevel); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + writeBlock(Core::span<const uint_least8_t> sendBuf); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + readBlock(Core::span<uint_least8_t> recvBuf); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + setSpeed(Speed newSpeed); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + setLevel(Level newLevel); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + triplet(TripletData & data); + + private: + DS9481P_300 * parent; + }; + + class I2CMaster : public Core::I2CMasterDecorator { + public: + explicit I2CMaster(DS9481P_300 & parent) + : I2CMasterDecorator(parent.ds9400), parent(&parent) {} + + MaximInterfaceDevices_EXPORT virtual Core::error_code + start(uint_least8_t address); + + MaximInterfaceDevices_EXPORT virtual Core::error_code stop(); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + writeByte(uint_least8_t data); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + writeBlock(Core::span<const uint_least8_t> data); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + readByte(AckStatus status, uint_least8_t & data); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + readBlock(AckStatus status, Core::span<uint_least8_t> data); + + protected: + MaximInterfaceDevices_EXPORT virtual Core::error_code + doWritePacket(uint_least8_t address, Core::span<const uint_least8_t> data, + bool sendStop); + + MaximInterfaceDevices_EXPORT virtual Core::error_code + doReadPacket(uint_least8_t address, Core::span<uint_least8_t> data, + bool sendStop); + + private: + DS9481P_300 * parent; + }; + + class DS2480BWithEscape : public DS2480B { + public: + DS2480BWithEscape(Core::Sleep & sleep, Core::Uart & uart) + : DS2480B(sleep, uart) {} + + Core::error_code escape(); + }; + + class DS9400WithEscape : public DS9400 { + public: + explicit DS9400WithEscape(Core::Uart & uart) : DS9400(uart) {} + + Core::error_code escape(); + }; + + enum Bus { OneWire, I2C }; + + Core::SerialPort * serialPort; + Bus currentBus; + DS2480BWithEscape ds2480b; + OneWireMaster oneWireMaster_; + DS9400WithEscape ds9400; + I2CMaster i2cMaster_; + + Core::error_code selectOneWire(); + Core::error_code selectBus(Bus newBus); + + friend class OneWireMaster; + friend class I2CMaster; +}; + +} // namespace MaximInterfaceDevices + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceMbed/I2CMaster.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,75 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include "I2CMaster.hpp" + +namespace MaximInterfaceMbed { + +using namespace MaximInterfaceCore; + +error_code I2CMaster::start(uint_least8_t address) { + i2c->start(); + return writeByte(address); +} + +error_code I2CMaster::stop() { + i2c->stop(); + return error_code(); +} + +error_code I2CMaster::writeByte(uint_least8_t data) { + return (i2c->write(data) == 1) ? error_code() : make_error_code(NackError); +} + +error_code I2CMaster::doWritePacket(uint_least8_t address, + span<const uint_least8_t> data, + bool sendStop) { + return (i2c->write(address, reinterpret_cast<const char *>(data.data()), + data.size(), !sendStop) == 0) + ? error_code() + : make_error_code(NackError); +} + +error_code I2CMaster::readByte(AckStatus status, uint_least8_t & data) { + data = i2c->read(status == Ack); + return error_code(); +} + +error_code I2CMaster::doReadPacket(uint_least8_t address, + span<uint_least8_t> data, bool sendStop) { + return (i2c->read(address, reinterpret_cast<char *>(data.data()), data.size(), + !sendStop) == 0) + ? error_code() + : make_error_code(NackError); +} + +} // namespace MaximInterfaceMbed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceMbed/I2CMaster.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,73 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceMbed_I2CMaster +#define MaximInterfaceMbed_I2CMaster + +#include <MaximInterfaceCore/I2CMaster.hpp> +#include <mbed-os/drivers/I2C.h> + +namespace MaximInterfaceMbed { + +/// Wrapper for mbed::I2C. +class I2CMaster : public MaximInterfaceCore::I2CMaster { +public: + explicit I2CMaster(mbed::I2C & i2c) : i2c(&i2c) {} + + void setI2C(mbed::I2C & i2c) { this->i2c = &i2c; } + + virtual MaximInterfaceCore::error_code start(uint_least8_t address); + + virtual MaximInterfaceCore::error_code stop(); + + virtual MaximInterfaceCore::error_code writeByte(uint_least8_t data); + + virtual MaximInterfaceCore::error_code readByte(AckStatus status, + uint_least8_t & data); + +protected: + virtual MaximInterfaceCore::error_code + doReadPacket(uint_least8_t address, + MaximInterfaceCore::span<uint_least8_t> data, bool sendStop); + + virtual MaximInterfaceCore::error_code + doWritePacket(uint_least8_t address, + MaximInterfaceCore::span<const uint_least8_t> data, + bool sendStop); + +private: + mbed::I2C * i2c; +}; + +} // namespace MaximInterfaceMbed + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceMbed/Sleep.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,47 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include <mbed-os/platform/mbed_wait_api.h> +#include "Sleep.hpp" + +namespace MaximInterfaceMbed { + +void sleep(int ms) { wait_ms(ms); } + +Sleep & Sleep::instance() { + static Sleep instance; + return instance; +} + +void Sleep::invoke(int ms) const { sleep(ms); } + +} // namespace MaximInterfaceMbed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceMbed/Sleep.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,55 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceMbed_Sleep +#define MaximInterfaceMbed_Sleep + +#include <MaximInterfaceCore/Sleep.hpp> +#include <MaximInterfaceCore/Uncopyable.hpp> + +namespace MaximInterfaceMbed { + +void sleep(int ms); + +class Sleep : public MaximInterfaceCore::Sleep, + private MaximInterfaceCore::Uncopyable { +public: + static Sleep & instance(); + virtual void invoke(int ms) const; + +private: + Sleep() {} +}; + +} // namespace MaximInterfaceMbed + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceMbed/Uart.cpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,106 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#include <MaximInterfaceCore/Error.hpp> +#include <mbed-os/drivers/Timer.h> +#include "Uart.hpp" + +namespace MaximInterfaceMbed { + +using namespace MaximInterfaceCore; + +static const int timeout_ms = 10000; + +error_code Uart::setBaudRate(int_least32_t baudRate) { + serial->baud(baudRate); + return error_code(); +} + +error_code Uart::sendBreak() { + serial->send_break(); + return error_code(); +} + +error_code Uart::clearReadBuffer() { + while (serial->readable()) { + serial->getc(); + } + return error_code(); +} + +error_code Uart::writeByte(uint_least8_t data) { + if (!serial->writeable()) { + mbed::Timer timer; + timer.start(); + while (!serial->writeable()) { + if (timer.read_ms() >= timeout_ms) { + return make_error_code(HardwareError); + } + } + } + serial->putc(data); + return error_code(); +} + +error_code Uart::readByte(uint_least8_t & data) { + if (!serial->readable()) { + mbed::Timer timer; + timer.start(); + while (!serial->readable()) { + if (timer.read_ms() >= timeout_ms) { + return make_error_code(TimeoutError); + } + } + } + data = serial->getc(); + return error_code(); +} + +const error_category & Uart::errorCategory() { + static class : public error_category { + public: + virtual const char * name() const { return "mbed UART"; } + + virtual std::string message(int condition) const { + switch (condition) { + case HardwareError: + return "Hardware Error"; + + default: + return defaultErrorMessage(condition); + } + } + } instance; + return instance; +} + +} // namespace MaximInterfaceMbed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MaximInterfaceMbed/Uart.hpp Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,74 @@ +/******************************************************************************* +* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +*******************************************************************************/ + +#ifndef MaximInterfaceMbed_Uart +#define MaximInterfaceMbed_Uart + +#include <MaximInterfaceCore/Uart.hpp> +#include <mbed-os/drivers/Serial.h> + +namespace MaximInterfaceMbed { + +/// Wrapper for mbed::Serial. +class Uart : public MaximInterfaceCore::Uart { +public: + enum ErrorValue { + HardwareError = 1 ///< Write operation aborted due to timeout. + }; + + explicit Uart(mbed::Serial & serial) : serial(&serial) {} + + void setSerial(mbed::Serial & serial) { this->serial = &serial; } + + virtual MaximInterfaceCore::error_code setBaudRate(int_least32_t baudRate); + + virtual MaximInterfaceCore::error_code sendBreak(); + + virtual MaximInterfaceCore::error_code clearReadBuffer(); + + virtual MaximInterfaceCore::error_code writeByte(uint_least8_t data); + + virtual MaximInterfaceCore::error_code readByte(uint_least8_t & data); + + static const MaximInterfaceCore::error_category & errorCategory(); + +private: + mbed::Serial * serial; +}; + +inline MaximInterfaceCore::error_code make_error_code(Uart::ErrorValue e) { + return MaximInterfaceCore::error_code(e, Uart::errorCategory()); +} + +} // namespace MaximInterfaceMbed + +#endif
--- a/Platforms/mbed/I2CMaster.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include "I2CMaster.hpp" - -namespace MaximInterface { -namespace mbed { - -error_code I2CMaster::start(uint_least8_t address) { - i2c->start(); - return writeByte(address); -} - -error_code I2CMaster::stop() { - i2c->stop(); - return error_code(); -} - -error_code I2CMaster::writeByte(uint_least8_t data) { - return (i2c->write(data) == 1) ? error_code() : make_error_code(NackError); -} - -error_code I2CMaster::writePacketImpl(uint_least8_t address, - span<const uint_least8_t> data, - bool sendStop) { - return (i2c->write(address, reinterpret_cast<const char *>(data.data()), - data.size(), !sendStop) == 0) - ? error_code() - : make_error_code(NackError); -} - -error_code I2CMaster::readByte(AckStatus status, uint_least8_t & data) { - data = i2c->read(status == Ack); - return error_code(); -} - -error_code I2CMaster::readPacketImpl(uint_least8_t address, - span<uint_least8_t> data, bool sendStop) { - return (i2c->read(address, reinterpret_cast<char *>(data.data()), data.size(), - !sendStop) == 0) - ? error_code() - : make_error_code(NackError); -} - -} // namespace mbed -} // namespace MaximInterface
--- a/Platforms/mbed/I2CMaster.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_mbed_I2CMaster -#define MaximInterface_mbed_I2CMaster - -#include <I2C.h> -#include <MaximInterface/Links/I2CMaster.hpp> - -namespace MaximInterface { -namespace mbed { - -/// Wrapper for mbed::I2C. -class I2CMaster : public MaximInterface::I2CMaster { -public: - explicit I2CMaster(::mbed::I2C & i2c) : i2c(&i2c) {} - - void setI2C(::mbed::I2C & i2c) { this->i2c = &i2c; } - - virtual error_code start(uint_least8_t address); - virtual error_code stop(); - virtual error_code writeByte(uint_least8_t data); - virtual error_code readByte(AckStatus status, uint_least8_t & data); - -protected: - virtual error_code readPacketImpl(uint_least8_t address, - span<uint_least8_t> data, bool sendStop); - - virtual error_code writePacketImpl(uint_least8_t address, - span<const uint_least8_t> data, - bool sendStop); - -private: - ::mbed::I2C * i2c; -}; - -} // namespace mbed -} // namespace MaximInterface - -#endif
--- a/Platforms/mbed/Sleep.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include <wait_api.h> -#include "Sleep.hpp" - -namespace MaximInterface { -namespace mbed { - -void sleep(int ms) { wait_ms(ms); } - -Sleep & Sleep::instance() { - static Sleep instance; - return instance; -} - -void Sleep::invoke(int ms) const { sleep(ms); } - -} // namespace mbed -} // namespace MaximInterface
--- a/Platforms/mbed/Sleep.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_mbed_Sleep -#define MaximInterface_mbed_Sleep - -#include <MaximInterface/Links/Sleep.hpp> -#include <MaximInterface/Utilities/Uncopyable.hpp> - -namespace MaximInterface { -namespace mbed { - -void sleep(int ms); - -class Sleep : public MaximInterface::Sleep, private Uncopyable { -public: - static Sleep & instance(); - virtual void invoke(int ms) const; - -private: - Sleep() {} -}; - -} // namespace mbed -} // namespace MaximInterface - -#endif
--- a/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/GpioOneWireMaster.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,173 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifdef TARGET_MAX32600 - -#include "GpioOneWireMaster.hpp" -#include "owlink.h" -#include <gpio_regs.h> -#include <clkman_regs.h> - -namespace MaximInterface { - -static const OneWireTiming stdTiming = { - 560, // tRSTL - 68, // tMSP - 64, // tW0L - 8, // tW1L - 12, // tMSR - 70, // tSLOT -}; - -static const OneWireTiming odTiming = { - 56, // tRSTL - 8, // tMSP - 8, // tW0L - 1, // tW1L - 1, // tMSR - 10, // tSLOT -}; - -GpioOneWireMaster::GpioOneWireMaster(PinName owGpio, PinName extSpu, - bool extSpuActiveHigh) - : port(PINNAME_TO_PORT(owGpio)), pin(PINNAME_TO_PIN(owGpio)), - speed(StandardSpeed), extSpu(extSpu), extSpuActiveHigh(extSpuActiveHigh) { -} - -error_code GpioOneWireMaster::initialize() { - if (MXC_CLKMAN->clk_ctrl_1_gpio == MXC_E_CLKMAN_CLK_SCALE_DISABLED) { - MXC_CLKMAN->clk_ctrl_1_gpio = MXC_E_CLKMAN_CLK_SCALE_ENABLED; - } - - /* Set function */ - MXC_GPIO->func_sel[port] &= ~(0xF << (4 * pin)); - - /* Normal input is always enabled */ - MXC_GPIO->in_mode[port] &= ~(0xF << (4 * pin)); - - writeGpioHigh(); - setLevel(NormalLevel); - - return error_code(); -} - -error_code GpioOneWireMaster::reset() { - const OneWireTiming & curTiming(speed == OverdriveSpeed ? odTiming - : stdTiming); - const uint16_t tREC = curTiming.tRSTL - curTiming.tMSP; // tSLOT = 2 *tRSTL - - __disable_irq(); // Enter critical section - - writeGpioLow(); // Pull low - ow_usdelay(curTiming.tRSTL); // Wait specified time for reset pulse - writeGpioHigh(); // Let go of pin - ow_usdelay(curTiming.tMSP); // Wait specified time for master sample - const bool pd_pulse = readGpio(); // Get sample - ow_usdelay(tREC); // Wait for slot time to finish including recovery - - __enable_irq(); // Exit critical section - - return pd_pulse ? make_error_code(NoSlaveError) : error_code(); -} - -error_code GpioOneWireMaster::touchBitSetLevel(bool & sendRecvBit, - Level afterLevel) { - __disable_irq(); // Enter critical section - - uint8_t sendRecvUint = sendRecvBit; - ow_bit(&sendRecvUint, &MXC_GPIO->in_val[port], &MXC_GPIO->out_val[port], - (1 << pin), ((speed == OverdriveSpeed) ? &odTiming : &stdTiming)); - setLevel(afterLevel); - sendRecvBit = sendRecvUint; - - __enable_irq(); // Exit critical section - - return error_code(); -} - -error_code GpioOneWireMaster::setSpeed(Speed newSpeed) { - if (!((newSpeed == StandardSpeed) || (newSpeed == OverdriveSpeed))) { - return make_error_code(InvalidSpeedError); - } - speed = newSpeed; - return error_code(); -} - -error_code GpioOneWireMaster::setLevel(Level newLevel) { - error_code result; - switch (newLevel) { - case NormalLevel: - setGpioMode(MXC_V_GPIO_OUT_MODE_OPEN_DRAIN); - if (extSpu.is_connected()) { - extSpu = !extSpuActiveHigh; - } - break; - - case StrongLevel: - if (extSpu.is_connected()) { - extSpu = extSpuActiveHigh; - } else { - setGpioMode(MXC_V_GPIO_OUT_MODE_NORMAL_DRIVE); - } - break; - - default: - result = make_error_code(InvalidLevelError); - break; - } - return result; -} - -inline void GpioOneWireMaster::writeGpioLow() { - MXC_GPIO->out_val[port] &= ~(1 << pin); -} - -inline void GpioOneWireMaster::writeGpioHigh() { - MXC_GPIO->out_val[port] |= (1 << pin); -} - -inline bool GpioOneWireMaster::readGpio() { - return ((MXC_GPIO->in_val[port] & (1 << pin)) >> pin); -} - -inline void GpioOneWireMaster::setGpioMode(unsigned int mode) { - //read port out_mode - uint32_t ow_out_mode = MXC_GPIO->out_mode[port]; - //clear the mode for ow_pin - ow_out_mode &= ~(0xF << (pin * 4)); - //write ow_pin mode and original data back - MXC_GPIO->out_mode[port] = (ow_out_mode | (mode << (pin * 4))); -} - -} // namespace MaximInterface - -#endif /* TARGET_MAX32600 */
--- a/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/GpioOneWireMaster.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_GpioOneWireMaster -#define MaximInterface_GpioOneWireMaster - -#include <MaximInterface/Links/OneWireMaster.hpp> -#include <DigitalOut.h> - -namespace MaximInterface { - -class GpioOneWireMaster : public OneWireMaster { -public: - /// @param owGpio Pin to use for 1-Wire bus - /// @param extSpu Pin to use for external Strong Pullup - explicit GpioOneWireMaster(PinName owGpio, PinName extSpu = NC, - bool extSpuActiveHigh = false); - - error_code initialize(); - - virtual error_code reset(); - virtual error_code touchBitSetLevel(bool & sendRecvBit, Level afterLevel); - virtual error_code setSpeed(Speed newSpeed); - virtual error_code setLevel(Level newLevel); - -private: - unsigned int port; - unsigned int pin; - Speed speed; - mbed::DigitalOut extSpu; - bool extSpuActiveHigh; - - inline void writeGpioLow(); - inline void writeGpioHigh(); - inline bool readGpio(); - inline void setGpioMode(unsigned int mode); -}; - -} // namespace MaximInterface - -#endif
--- a/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_ARM_STD/owlink.s Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,209 +0,0 @@ -/******************************************************************//** -* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -**********************************************************************/ - -// ow_usdelay configuration -// -// Make PROC_CLOCK_MHZ and OVERHEAD_TUNING divisible by PROC_CYCLES_PER_LOOP -// for best results -// -// Processor clock in MHz -#define PROC_CLOCK_MHZ (__SYSTEM_HFX / 1000000) -// -// Fraction where OverheadTime(us) = OVERHEAD_TUNING / PROC_CLOCK_MHZ -#define OVERHEAD_TUNING 18 -// -// ARM specifies 1-3 cycles for pipeline refill following a branch -#define PIPELINE_REFILL_PROC_CYCLES 1 - -// ow_usdelay constants -#define PROC_CYCLES_PER_LOOP (2 + PIPELINE_REFILL_PROC_CYCLES) -#define LOOPS_PER_US (PROC_CLOCK_MHZ / PROC_CYCLES_PER_LOOP) -#define LOOPS_REMOVED_TUNING (OVERHEAD_TUNING / PROC_CYCLES_PER_LOOP) - -// OneWireTiming offsets -#define tRSTL_OFFSET 0 -#define tMSP_OFFSET 2 -#define tW0L_OFFSET 4 -#define tW1L_OFFSET 6 -#define tMSR_OFFSET 8 -#define tSLOT_OFFSET 10 - -// Define a code section - AREA owlink, CODE -// void ow_usdelay(unsigned int time_us) - EXPORT ow_usdelay -ow_usdelay - cmp R0, #0 // Return if time_us equals zero - beq ow_usdelay_return - mov R2, #LOOPS_PER_US - mul R0, R0, R2 - sub R0, R0, #LOOPS_REMOVED_TUNING -loop - subs R0, R0, #1 - bne loop -ow_usdelay_return - bx R14 - -// void write_ow_gpio_low(volatile uint32_t * portReg, unsigned int pinMask) - MACRO -$label write_ow_gpio_low - ldr R2, [R0] - bic R2, R2, R1 - str R2, [R0] - MEND - -// void write_ow_gpio_high(volatile uint32_t * portReg, unsigned int pinMask) - MACRO -$label write_ow_gpio_high - ldr R2, [R0] - orr R2, R2, R1 - str R2, [R0] - MEND - -// void ow_bit(uint8_t * sendRecvBit, const volatile uint32_t * inReg, -// volatile uint32_t * outReg, unsigned int pinMask, -// const OneWireTiming * timing) - EXPORT ow_bit -ow_bit - push {R4-R8, R14} - // Retrive extra parameters from stack - add R6, SP, #24 // Find beginning of stack: 6 scratch registers * 4 bytes each - ldr R6, [R6] // Load timing struct - ldrh R4, [R6, #tSLOT_OFFSET] - ldrh R5, [R6, #tMSR_OFFSET] - // R0: sendRecvBit - // R1: inReg - // R2: outReg - // R3: pinMask - // R4: tSLOT - // R5: tMSR - // R6: timing - // R7: Scratch - // R8: Scratch - // R14: Scratch - - // Reorganize registers for upcoming function calls - mov R8, R1 // inReg to R8 - mov R7, R2 // outReg to R7 - mov R1, R3 // pinMask to R1 - mov R3, R0 // sendRecvBit to R3 - // R0: Scratch - // R1: pinMask - // R2: Scratch - // R3: sendRecvBit - // R4: tSLOT - // R5: tMSR - // R6: timing - // R7: outReg - // R8: inReg - // R14: Scratch - - // if (*sendRecvBit & 1) - ldrb R14, [R3] - tst R14, #1 - beq write_zero - ldrh R6, [R6, #tW1L_OFFSET] // tW1L - sub R4, R4, R5 // tREC = tSLOT - tMSR - sub R5, R5, R6 // delay2 = tMSR - tLW1L - // R0: Scratch - // R1: pinMask - // R2: Scratch - // R3: sendRecvBit - // R4: tREC - // R5: delay2 - // R6: tW1L - // R7: outReg - // R8: inReg - // R14: Scratch - mov R0, R7 // outReg - write_ow_gpio_low // Pull low - mov R0, R6 // tLOW - bl ow_usdelay // Delay for tLOW - mov R0, R7 // outReg - write_ow_gpio_high // Release pin - mov R0, R5 // delay2 - bl ow_usdelay // Delay for sample time - ldr R5, [R8] // Read *inReg - b recovery_delay - // else -write_zero - ldrh R6, [R6, #tW0L_OFFSET] // tW0L - sub R4, R4, R6 // tREC = tSLOT - tLW0L - sub R6, R6, R5 // delay2 = tW0L - tMSR - // R0: Scratch - // R1: pinMask - // R2: Scratch - // R3: sendRecvBit - // R4: tREC - // R5: tMSR - // R6: delay2 - // R7: outReg - // R8: inReg - // R14: Scratch - mov R0, R7 // outReg - write_ow_gpio_low // Pull low - mov R0, R5 // tMSR - bl ow_usdelay // Delay for tMSR - ldr R5, [R8] // Read *inReg - mov R0, R6 // delay2 - bl ow_usdelay // Delay for release - mov R0, R7 // outReg - write_ow_gpio_high // Release pin - // endif (*sendRecvBit & 1) - // R0: Scratch - // R1: pinMask - // R2: Scratch - // R3: sendRecvBit - // R4: tREC - // R5: *inReg - // R6: Scratch - // R7: outReg - // R8: inReg - // R14: Scratch - -recovery_delay - mov R0, R4 - bl ow_usdelay // Delay for tREC - - // Parse received bit - // *sendRecvBit = ((*inReg & pinMask) == pinMask) - and R5, R5, R1 - cmp R5, R1 - ite eq - moveq R5, #1 - movne R5, #0 - strb R5, [R3] - - pop {R4-R8, R14} - bx R14 - - END
--- a/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_GCC_ARM/owlink.S Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,210 +0,0 @@ -/******************************************************************//** -* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -**********************************************************************/ - -// ow_usdelay configuration -// -// Make PROC_CLOCK_MHZ and OVERHEAD_TUNING divisible by PROC_CYCLES_PER_LOOP -// for best results -// -// Processor clock in MHz -#define PROC_CLOCK_MHZ (__SYSTEM_HFX / 1000000) -// -// Fraction where OverheadTime(us) = OVERHEAD_TUNING / PROC_CLOCK_MHZ -#define OVERHEAD_TUNING 18 -// -// ARM specifies 1-3 cycles for pipeline refill following a branch -#define PIPELINE_REFILL_PROC_CYCLES 1 - -// ow_usdelay constants -#define PROC_CYCLES_PER_LOOP (2 + PIPELINE_REFILL_PROC_CYCLES) -#define LOOPS_PER_US (PROC_CLOCK_MHZ / PROC_CYCLES_PER_LOOP) -#define LOOPS_REMOVED_TUNING (OVERHEAD_TUNING / PROC_CYCLES_PER_LOOP) - -// OneWireTiming offsets -#define tRSTL_OFFSET 0 -#define tMSP_OFFSET 2 -#define tW0L_OFFSET 4 -#define tW1L_OFFSET 6 -#define tMSR_OFFSET 8 -#define tSLOT_OFFSET 10 - -// Define a code section - .syntax unified - .section .text -// void ow_usdelay(unsigned int time_us) - .thumb_func - .global ow_usdelay -ow_usdelay: - cmp R0, #0 // Return if time_us equals zero - beq ow_usdelay_return - mov R2, #LOOPS_PER_US - mul R0, R0, R2 - sub R0, R0, #LOOPS_REMOVED_TUNING -loop: - subs R0, R0, #1 - bne loop -ow_usdelay_return: - bx R14 - -// void write_ow_gpio_low(volatile uint32_t * portReg, unsigned int pinMask) -.macro write_ow_gpio_low - ldr R2, [R0] - bic R2, R2, R1 - str R2, [R0] - .endm - -// void write_ow_gpio_high(volatile uint32_t * portReg, unsigned int pinMask) -.macro write_ow_gpio_high - ldr R2, [R0] - orr R2, R2, R1 - str R2, [R0] - .endm - -// void ow_bit(uint8_t * sendRecvBit, const volatile uint32_t * inReg, -// volatile uint32_t * outReg, unsigned int pinMask, -// const OneWireTiming * timing) - .thumb_func - .global ow_bit -ow_bit: - push {R4-R8, R14} - // Retrive extra parameters from stack - add R6, SP, #24 // Find beginning of stack: 6 scratch registers * 4 bytes each - ldr R6, [R6] // Load timing struct - ldrh R4, [R6, #tSLOT_OFFSET] - ldrh R5, [R6, #tMSR_OFFSET] - // R0: sendRecvBit - // R1: inReg - // R2: outReg - // R3: pinMask - // R4: tSLOT - // R5: tMSR - // R6: timing - // R7: Scratch - // R8: Scratch - // R14: Scratch - - // Reorganize registers for upcoming function calls - mov R8, R1 // inReg to R8 - mov R7, R2 // outReg to R7 - mov R1, R3 // pinMask to R1 - mov R3, R0 // sendRecvBit to R3 - // R0: Scratch - // R1: pinMask - // R2: Scratch - // R3: sendRecvBit - // R4: tSLOT - // R5: tMSR - // R6: timing - // R7: outReg - // R8: inReg - // R14: Scratch - - // if (*sendRecvBit & 1) - ldrb R14, [R3] - tst R14, #1 - beq write_zero - ldrh R6, [R6, #tW1L_OFFSET] // tW1L - sub R4, R4, R5 // tREC = tSLOT - tMSR - sub R5, R5, R6 // delay2 = tMSR - tLW1L - // R0: Scratch - // R1: pinMask - // R2: Scratch - // R3: sendRecvBit - // R4: tREC - // R5: delay2 - // R6: tW1L - // R7: outReg - // R8: inReg - // R14: Scratch - mov R0, R7 // outReg - write_ow_gpio_low // Pull low - mov R0, R6 // tLOW - bl ow_usdelay // Delay for tLOW - mov R0, R7 // outReg - write_ow_gpio_high // Release pin - mov R0, R5 // delay2 - bl ow_usdelay // Delay for sample time - ldr R5, [R8] // Read *inReg - b recovery_delay - // else -write_zero: - ldrh R6, [R6, #tW0L_OFFSET] // tW0L - sub R4, R4, R6 // tREC = tSLOT - tLW0L - sub R6, R6, R5 // delay2 = tW0L - tMSR - // R0: Scratch - // R1: pinMask - // R2: Scratch - // R3: sendRecvBit - // R4: tREC - // R5: tMSR - // R6: delay2 - // R7: outReg - // R8: inReg - // R14: Scratch - mov R0, R7 // outReg - write_ow_gpio_low // Pull low - mov R0, R5 // tMSR - bl ow_usdelay // Delay for tMSR - ldr R5, [R8] // Read *inReg - mov R0, R6 // delay2 - bl ow_usdelay // Delay for release - mov R0, R7 // outReg - write_ow_gpio_high // Release pin - // endif (*sendRecvBit & 1) - // R0: Scratch - // R1: pinMask - // R2: Scratch - // R3: sendRecvBit - // R4: tREC - // R5: *inReg - // R6: Scratch - // R7: outReg - // R8: inReg - // R14: Scratch - -recovery_delay: - mov R0, R4 - bl ow_usdelay // Delay for tREC - - // Parse received bit - // *sendRecvBit = ((*inReg & pinMask) == pinMask) - and R5, R5, R1 - cmp R5, R1 - ite eq - moveq R5, #1 - movne R5, #0 - strb R5, [R3] - - pop {R4-R8, R14} - bx R14 - .end - \ No newline at end of file
--- a/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_IAR/owlink.s Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,207 +0,0 @@ -/******************************************************************//** -* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -**********************************************************************/ - -// ow_usdelay configuration -// -// Make PROC_CLOCK_MHZ and OVERHEAD_TUNING divisible by PROC_CYCLES_PER_LOOP -// for best results -// -// Processor clock in MHz -#define PROC_CLOCK_MHZ (__SYSTEM_HFX / 1000000) -// -// Fraction where OverheadTime(us) = OVERHEAD_TUNING / PROC_CLOCK_MHZ -#define OVERHEAD_TUNING 18 -// -// ARM specifies 1-3 cycles for pipeline refill following a branch -#define PIPELINE_REFILL_PROC_CYCLES 1 - -// ow_usdelay constants -#define PROC_CYCLES_PER_LOOP (2 + PIPELINE_REFILL_PROC_CYCLES) -#define LOOPS_PER_US (PROC_CLOCK_MHZ / PROC_CYCLES_PER_LOOP) -#define LOOPS_REMOVED_TUNING (OVERHEAD_TUNING / PROC_CYCLES_PER_LOOP) - -// OneWireTiming offsets -#define tRSTL_OFFSET 0 -#define tMSP_OFFSET 2 -#define tW0L_OFFSET 4 -#define tW1L_OFFSET 6 -#define tMSR_OFFSET 8 -#define tSLOT_OFFSET 10 - -// Define a code section - SECTION owlink : CODE - -// void ow_usdelay(unsigned int time_us) - EXPORT ow_usdelay -ow_usdelay - cmp R0, #0 // Return if time_us equals zero - beq ow_usdelay_return - mov R2, #LOOPS_PER_US - mul R0, R0, R2 - sub R0, R0, #LOOPS_REMOVED_TUNING -loop - subs R0, R0, #1 - bne loop -ow_usdelay_return - bx R14 - -// void write_ow_gpio_low(volatile uint32_t * portReg, unsigned int pinMask) -write_ow_gpio_low MACRO - ldr R2, [R0] - bic R2, R2, R1 - str R2, [R0] - ENDM - -// void write_ow_gpio_high(volatile uint32_t * portReg, unsigned int pinMask) -write_ow_gpio_high MACRO - ldr R2, [R0] - orr R2, R2, R1 - str R2, [R0] - ENDM - -// void ow_bit(uint8_t * sendRecvBit, const volatile uint32_t * inReg, -// volatile uint32_t * outReg, unsigned int pinMask, -// const OneWireTiming * timing) - EXPORT ow_bit -ow_bit - push {R4-R8, R14} - // Retrive extra parameters from stack - add R6, SP, #24 // Find beginning of stack: 6 scratch registers * 4 bytes each - ldr R6, [R6] // Load timing struct - ldrh R4, [R6, #tSLOT_OFFSET] - ldrh R5, [R6, #tMSR_OFFSET] - // R0: sendRecvBit - // R1: inReg - // R2: outReg - // R3: pinMask - // R4: tSLOT - // R5: tMSR - // R6: timing - // R7: Scratch - // R8: Scratch - // R14: Scratch - - // Reorganize registers for upcoming function calls - mov R8, R1 // inReg to R8 - mov R7, R2 // outReg to R7 - mov R1, R3 // pinMask to R1 - mov R3, R0 // sendRecvBit to R3 - // R0: Scratch - // R1: pinMask - // R2: Scratch - // R3: sendRecvBit - // R4: tSLOT - // R5: tMSR - // R6: timing - // R7: outReg - // R8: inReg - // R14: Scratch - - // if (*sendRecvBit & 1) - ldrb R14, [R3] - tst R14, #1 - beq write_zero - ldrh R6, [R6, #tW1L_OFFSET] // tW1L - sub R4, R4, R5 // tREC = tSLOT - tMSR - sub R5, R5, R6 // delay2 = tMSR - tLW1L - // R0: Scratch - // R1: pinMask - // R2: Scratch - // R3: sendRecvBit - // R4: tREC - // R5: delay2 - // R6: tW1L - // R7: outReg - // R8: inReg - // R14: Scratch - mov R0, R7 // outReg - write_ow_gpio_low // Pull low - mov R0, R6 // tLOW - bl ow_usdelay // Delay for tLOW - mov R0, R7 // outReg - write_ow_gpio_high // Release pin - mov R0, R5 // delay2 - bl ow_usdelay // Delay for sample time - ldr R5, [R8] // Read *inReg - b recovery_delay - // else -write_zero - ldrh R6, [R6, #tW0L_OFFSET] // tW0L - sub R4, R4, R6 // tREC = tSLOT - tLW0L - sub R6, R6, R5 // delay2 = tW0L - tMSR - // R0: Scratch - // R1: pinMask - // R2: Scratch - // R3: sendRecvBit - // R4: tREC - // R5: tMSR - // R6: delay2 - // R7: outReg - // R8: inReg - // R14: Scratch - mov R0, R7 // outReg - write_ow_gpio_low // Pull low - mov R0, R5 // tMSR - bl ow_usdelay // Delay for tMSR - ldr R5, [R8] // Read *inReg - mov R0, R6 // delay2 - bl ow_usdelay // Delay for release - mov R0, R7 // outReg - write_ow_gpio_high // Release pin - // endif (*sendRecvBit & 1) - // R0: Scratch - // R1: pinMask - // R2: Scratch - // R3: sendRecvBit - // R4: tREC - // R5: *inReg - // R6: Scratch - // R7: outReg - // R8: inReg - // R14: Scratch - -recovery_delay - mov R0, R4 - bl ow_usdelay // Delay for tREC - - // Parse received bit - // *sendRecvBit = ((*inReg & pinMask) == pinMask) - and R5, R5, R1 - cmp R5, R1 - ite eq - moveq R5, #1 - movne R5, #0 - strb R5, [R3] - - pop {R4-R8, R14} - bx R14 - END
--- a/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/owlink.h Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_owlink -#define MaximInterface_owlink - -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/// Timing parameters for the 1-Wire bus in microseconds. -struct OneWireTiming { - uint16_t tRSTL; ///< Reset Low Time - uint16_t tMSP; ///< Presence-Detect Sample Time - uint16_t tW0L; ///< Write-Zero Low Time - uint16_t tW1L; ///< Write-One Low Time - uint16_t tMSR; ///< Read Sample Time - uint16_t tSLOT; ///< Time Slot Duration -}; - -/// Delay for the specified number of microseconds. -void ow_usdelay(unsigned int time_us); - -/// @brief Send and receive one bit, and set a new level on the 1-Wire bus. -/// @note GPIO pin must be configured for open drain operation. -/// @param[in,out] sendRecvBit -/// Buffer containing the bit to send on 1-Wire bus in lsb. -/// Read data from 1-Wire bus will be returned in lsb. -/// @param[in] inReg Input register for GPIO pin. -/// @param[in,out] outReg Output register for GPIO pin. -/// @param pinMask Pin mask for input and output registers. -/// @param[in] timing 1-Wire timing parameters to use. -void ow_bit(uint8_t * sendRecvBit, const volatile uint32_t * inReg, - volatile uint32_t * outReg, unsigned int pinMask, - const OneWireTiming * timing); - -#ifdef __cplusplus -} -#endif - -#endif /* MaximInterface_owlink */
--- a/Platforms/mbed/Uart.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include <MaximInterface/Utilities/Error.hpp> -#include <Timer.h> -#include "Uart.hpp" - -static const int timeout_ms = 10000; - -namespace MaximInterface { -namespace mbed { - -error_code Uart::setBaudRate(int_least32_t baudRate) { - serial->baud(baudRate); - return error_code(); -} - -error_code Uart::sendBreak() { - serial->send_break(); - return error_code(); -} - -error_code Uart::clearReadBuffer() { - while (serial->readable()) { - serial->getc(); - } - return error_code(); -} - -error_code Uart::writeByte(uint_least8_t data) { - if (!serial->writeable()) { - ::mbed::Timer timer; - timer.start(); - while (!serial->writeable()) { - if (timer.read_ms() >= timeout_ms) { - return make_error_code(HardwareError); - } - } - } - serial->putc(data); - return error_code(); -} - -error_code Uart::readByte(uint_least8_t & data) { - if (!serial->readable()) { - ::mbed::Timer timer; - timer.start(); - while (!serial->readable()) { - if (timer.read_ms() >= timeout_ms) { - return make_error_code(TimeoutError); - } - } - } - data = serial->getc(); - return error_code(); -} - -const error_category & Uart::errorCategory() { - static class : public error_category { - public: - virtual const char * name() const { return "mbed UART"; } - - virtual std::string message(int condition) const { - switch (condition) { - case HardwareError: - return "Hardware Error"; - - default: - return defaultErrorMessage(condition); - } - } - } instance; - return instance; -} - -} // namespace mbed -} // namespace MaximInterface
--- a/Platforms/mbed/Uart.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_mbed_Uart -#define MaximInterface_mbed_Uart - -#include <Serial.h> -#include <MaximInterface/Links/Uart.hpp> - -namespace MaximInterface { -namespace mbed { - -/// Wrapper for mbed::Serial. -class Uart : public MaximInterface::Uart { -public: - enum ErrorValue { - HardwareError = 1 ///< Write operation aborted due to timeout. - }; - - explicit Uart(::mbed::Serial & serial) : serial(&serial) {} - - void setSerial(::mbed::Serial & serial) { this->serial = &serial; } - - virtual error_code setBaudRate(int_least32_t baudRate); - virtual error_code sendBreak(); - virtual error_code clearReadBuffer(); - virtual error_code writeByte(uint_least8_t data); - virtual error_code readByte(uint_least8_t & data); - - static const error_category & errorCategory(); - -private: - ::mbed::Serial * serial; -}; - -inline error_code make_error_code(Uart::ErrorValue e) { - return error_code(e, Uart::errorCategory()); -} - -} // namespace mbed -} // namespace MaximInterface - -#endif
--- a/Utilities/Algorithm.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_Algorithm -#define MaximInterface_Algorithm - -/// Alternative to std::max when a constant expression is required. -#define MaximInterface_MAX(a, b) ((a) < (b) ? (b) : (a)) - -/// Alternative to std::min when a constant expression is required. -#define MaximInterface_MIN(a, b) ((b) < (a) ? (b) : (a)) - -#endif
--- a/Utilities/ChangeSizeType.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_ChangeSizeType -#define MaximInterface_ChangeSizeType - -#include <stdint.h> -#include <algorithm> -#include <limits> -#include "span.hpp" -#include "system_error.hpp" - -namespace MaximInterface { - -/// @brief -/// Adapts functions taking an array pointer and size where the size type is -/// nonstandard. -/// @tparam NewSize Nonstandard size type. -/// @tparam Func Must be callable as func(Data *, NewSize). -/// @tparam Data Array element type. -/// @param func Callback for processing chunks of data. -/// @param data Data to process with callback. -template <typename NewSize, typename Func, typename Data> -error_code changeSizeType(Func func, span<Data> data) { - using namespace std; - typedef typename span<Data>::index_type DataSize; - - error_code result; - // Check if NewSize can represent the maximum value of DataSize. - if (static_cast<uintmax_t>(numeric_limits<DataSize>::max()) > - static_cast<uintmax_t>(numeric_limits<NewSize>::max())) { - DataSize dataIdx = 0; - do { - const span<Data> chunk = - data.subspan(dataIdx, min<DataSize>(data.size() - dataIdx, - numeric_limits<NewSize>::max())); - result = func(chunk.data(), static_cast<NewSize>(chunk.size())); - dataIdx += chunk.size(); - } while (dataIdx < data.size() && !result); - } else { - result = func(data.data(), static_cast<NewSize>(data.size())); - } - return result; -} - -} // namespace MaximInterface - -#endif \ No newline at end of file
--- a/Utilities/Ecc256.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include "Ecc256.hpp" - -namespace MaximInterface { -namespace Ecc256 { - -void copy(Point::const_span src, Point::span dst) { - copy(src.x, dst.x); - copy(src.y, dst.y); -} - -void copy(KeyPair::const_span src, KeyPair::span dst) { - copy(src.privateKey, dst.privateKey); - copy(src.publicKey, dst.publicKey); -} - -void copy(Signature::const_span src, Signature::span dst) { - copy(src.r, dst.r); - copy(src.s, dst.s); -} - -PublicKey::span CertificateData::publicKey() { - const PublicKey::span span = { - make_span(result_).subspan<publicKeyIdx, Scalar::size>(), - make_span(result_) - .subspan<publicKeyIdx + Scalar::size, Scalar::size>()}; - return span; -} - -} // namespace Ecc256 -} // namespace MaximInterface
--- a/Utilities/Ecc256.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,249 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_Ecc256 -#define MaximInterface_Ecc256 - -#include <stdint.h> -#include "array_span.hpp" -#include "Export.h" -#include "ManId.hpp" -#include "RomId.hpp" - -namespace MaximInterface { -namespace Ecc256 { - -typedef array_span<uint_least8_t, 32> Scalar; - -struct Point { - struct const_span { - Scalar::const_span x; - Scalar::const_span y; - }; - - struct span { - Scalar::span x; - Scalar::span y; - - operator const_span() const { - const const_span sp = {x, y}; - return sp; - } - }; - - struct array { - Scalar::array x; - Scalar::array y; - - operator span() { - const span sp = {x, y}; - return sp; - } - - operator const_span() const { - const const_span sp = {x, y}; - return sp; - } - }; - -private: - Point(); // deleted -}; - -MaximInterface_EXPORT void copy(Point::const_span src, Point::span dst); - -typedef Scalar PrivateKey; -typedef Point PublicKey; - -struct KeyPair { - struct const_span { - PrivateKey::const_span privateKey; - PublicKey::const_span publicKey; - }; - - struct span { - PrivateKey::span privateKey; - PublicKey::span publicKey; - - operator const_span() const { - const const_span sp = {privateKey, publicKey}; - return sp; - } - }; - - struct array { - PrivateKey::array privateKey; - PublicKey::array publicKey; - - operator span() { - const span sp = {privateKey, publicKey}; - return sp; - } - - operator const_span() const { - const const_span sp = {privateKey, publicKey}; - return sp; - } - }; - -private: - KeyPair(); // deleted -}; - -MaximInterface_EXPORT void copy(KeyPair::const_span src, KeyPair::span dst); - -struct Signature { - struct const_span { - Scalar::const_span r; - Scalar::const_span s; - }; - - struct span { - Scalar::span r; - Scalar::span s; - - operator const_span() const { - const const_span sp = {r, s}; - return sp; - } - }; - - struct array { - Scalar::array r; - Scalar::array s; - - operator span() { - const span sp = {r, s}; - return sp; - } - - operator const_span() const { - const const_span sp = {r, s}; - return sp; - } - }; - -private: - Signature(); // deleted -}; - -MaximInterface_EXPORT void copy(Signature::const_span src, Signature::span dst); - -/// Data used to create a device key certificate for ECC-256 authenticators. -class CertificateData { -public: - typedef array_span<uint_least8_t, 2 * Scalar::size + RomId::size + ManId::size> - Result; - - CertificateData() : result_() {} - - /// Formatted data result. - Result::const_span result() const { return result_; } - - /// @name Public Key - /// @brief Public key of the device. - /// @{ - - /// Get mutable Public Key. - MaximInterface_EXPORT PublicKey::span publicKey(); - - /// Get immutable Public Key. - PublicKey::const_span publicKey() const { - return const_cast<CertificateData &>(*this).publicKey(); - } - - /// Set Public Key. - CertificateData & setPublicKey(PublicKey::const_span publicKey) { - copy(publicKey, this->publicKey()); - return *this; - } - - /// @} - - /// @name ROM ID - /// @brief 1-Wire ROM ID of the device. - /// @{ - - /// Get mutable ROM ID. - RomId::span romId() { - return make_span(result_).subspan<romIdIdx, RomId::size>(); - } - - /// Get immutable ROM ID. - RomId::const_span romId() const { - return const_cast<CertificateData &>(*this).romId(); - } - - /// Set ROM ID. - CertificateData & setRomId(RomId::const_span romId) { - copy(romId, this->romId()); - return *this; - } - - /// @} - - /// @name MAN ID - /// @brief Manufacturer ID of the device. - /// @{ - - /// Get mutable MAN ID. - ManId::span manId() { - return make_span(result_).subspan<manIdIdx, ManId::size>(); - } - - /// Get immutable MAN ID. - ManId::const_span manId() const { - return const_cast<CertificateData &>(*this).manId(); - } - - /// Set MAN ID. - CertificateData & setManId(ManId::const_span manId) { - copy(manId, this->manId()); - return *this; - } - - /// @} - -private: - typedef Result::span::index_type index; - - static const index publicKeyIdx = 0; - static const index romIdIdx = publicKeyIdx + 2 * Scalar::size; - static const index manIdIdx = romIdIdx + RomId::size; - - Result::array result_; -}; - -} // namespace Ecc256 -} // namespace MaximInterface - -#endif
--- a/Utilities/Error.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include "Error.hpp" - -namespace MaximInterface { - -const char * defaultErrorMessage(int condition) { - return (condition == 0) ? "Success" : "Unknown Error"; -} - -} // namespace MaximInterface
--- a/Utilities/Error.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_Error -#define MaximInterface_Error - -#include "Export.h" - -namespace MaximInterface { - -/// @brief Get the default error message associated with a condition. -/// @details Typically used by an error_category when the condition is unknown. -MaximInterface_EXPORT const char * defaultErrorMessage(int condition); - -} - -#endif
--- a/Utilities/Export.h Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_EXPORT - #if defined(_MSC_VER) && defined(MaximInterface_EXPORTING) - #define MaximInterface_EXPORT __declspec(dllexport) - #else - #define MaximInterface_EXPORT - #endif -#endif
--- a/Utilities/FlagSet.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,226 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_FlagSet -#define MaximInterface_FlagSet - -#include <stddef.h> -#include <bitset> - -namespace MaximInterface { - -/// @brief -/// Provides functionality similar to std::bitset except using a bit flag, -/// typically of an enum type, as the indexer. -template <typename Flag, size_t flagBits> class FlagSet { -public: - class reference { - public: - reference(FlagSet & flagSet, Flag flag) : flagSet(&flagSet), flag(flag) {} - - reference & operator=(bool x) { - flagSet->set(flag, x); - return *this; - } - - reference & operator=(const reference & x) { - return operator=(static_cast<bool>(x)); - } - - operator bool() const { return flagSet->test(flag); } - - bool operator~() const { return reference(*this).flip(); } - - reference & flip() { - *this = !*this; - return *this; - } - - private: - FlagSet * flagSet; - Flag flag; - }; - - FlagSet() : bits() {} - - FlagSet(unsigned long val) : bits(val) {} - - template <typename CharT, typename Traits, typename Alloc> - explicit FlagSet( - const std::basic_string<CharT, Traits, Alloc> & str, - typename std::basic_string<CharT, Traits, Alloc>::size_type pos = 0, - typename std::basic_string<CharT, Traits, Alloc>::size_type n = - std::basic_string<CharT, Traits, Alloc>::npos) - : bits(str, pos, n) {} - - bool operator==(const FlagSet & rhs) const { return bits == rhs.bits; } - - bool operator!=(const FlagSet & rhs) const { return !operator==(rhs); } - - /// @name Element access - /// @{ - - bool operator[](Flag flag) const { return test(flag); } - - reference operator[](Flag flag) { return reference(*this, flag); } - - bool test(Flag flag) const { return (bits.to_ulong() & flag) == flag; } - - bool any() const { return bits.any(); } - - bool none() const { return bits.none(); } - - size_t count() const { return bits.count(); } - - /// @} - - /// @name Capacity - /// @{ - - size_t size() const { return bits.size(); } - - /// @} - - /// @name Modifiers - /// @{ - - FlagSet & operator&=(const FlagSet & other) { - bits &= other.bits; - return *this; - } - - FlagSet & operator|=(const FlagSet & other) { - bits |= other.bits; - return *this; - } - - FlagSet & operator^=(const FlagSet & other) { - bits ^= other.bits; - return *this; - } - - FlagSet operator~() const { return ~bits; } - - FlagSet & set() { - bits.set(); - return *this; - } - - FlagSet & set(Flag flag, bool value = true) { - if (value) { - bits |= flag; - } else { - bits &= ~std::bitset<flagBits>(flag); - } - return *this; - } - - FlagSet & reset() { - bits.reset(); - return *this; - } - - FlagSet & reset(Flag flag) { return set(flag, false); } - - FlagSet & flip() { - bits.flip(); - return *this; - } - - FlagSet & flip(Flag flag) { - bits ^= flag; - return *this; - } - - /// @} - - /// @name Conversions - /// @{ - - template <typename CharT, typename Traits, typename Allocator> - std::basic_string<CharT, Traits, Allocator> to_string() const { - return bits.template to_string<CharT, Traits, Allocator>(); - } - - unsigned long to_ulong() const { return bits.to_ulong(); } - - /// @} - -private: - std::bitset<flagBits> bits; - - template <typename CharT, typename Traits> - friend std::basic_ostream<CharT, Traits> & - operator<<(std::basic_ostream<CharT, Traits> & os, const FlagSet & x); - - template <typename CharT, class Traits> - friend std::basic_istream<CharT, Traits> & - operator>>(std::basic_istream<CharT, Traits> & is, FlagSet & x); -}; - -template <typename Flag, size_t flagBits> -FlagSet<Flag, flagBits> operator&(const FlagSet<Flag, flagBits> & lhs, - const FlagSet<Flag, flagBits> & rhs) { - return FlagSet<Flag, flagBits>(lhs) &= rhs; -} - -template <typename Flag, size_t flagBits> -FlagSet<Flag, flagBits> operator|(const FlagSet<Flag, flagBits> & lhs, - const FlagSet<Flag, flagBits> & rhs) { - return FlagSet<Flag, flagBits>(lhs) |= rhs; -} - -template <typename Flag, size_t flagBits> -FlagSet<Flag, flagBits> operator^(const FlagSet<Flag, flagBits> & lhs, - const FlagSet<Flag, flagBits> & rhs) { - return FlagSet<Flag, flagBits>(lhs) ^= rhs; -} - -template <typename CharT, typename Traits, typename Flag, size_t flagBits> -std::basic_ostream<CharT, Traits> & -operator<<(std::basic_ostream<CharT, Traits> & os, - const FlagSet<Flag, flagBits> & x) { - os << x.bits; - return os; -} - -template <typename CharT, class Traits, typename Flag, size_t flagBits> -std::basic_istream<CharT, Traits> & -operator>>(std::basic_istream<CharT, Traits> & is, - FlagSet<Flag, flagBits> & x) { - is >> x.bits; - return is; -} - -} // namespace MaximInterface - -#endif
--- a/Utilities/Function.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,565 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_Function -#define MaximInterface_Function - -#include <stddef.h> -#include "SafeBool.hpp" -#include "type_traits.hpp" - -// Include for std::swap. -#include <algorithm> -#include <utility> - -namespace MaximInterface { -namespace detail { - -// Provides char buffer storage for a given type. -// Suitability of alignment for type should be verified with alignment_of. -template <typename Type, size_t TypeSize> union TypeStorage { -public: - operator const Type *() const { return reinterpret_cast<const Type *>(data); } - - operator Type *() { - return const_cast<Type *>( - static_cast<const Type *>(static_cast<const TypeStorage &>(*this))); - } - - const Type & operator*() const { return **this; } - - Type & operator*() { - return const_cast<Type &>( - static_cast<const TypeStorage &>(*this).operator*()); - } - - const Type * operator->() const { return *this; } - - Type * operator->() { - return const_cast<Type *>( - static_cast<const TypeStorage &>(*this).operator->()); - } - -private: - char data[TypeSize]; - long double aligner1; - long int aligner2; - void * aligner3; -}; - -// Computes the internal target size for TypeStorage based on a desired total -// size. No internal storage will be allocated if the requested size is smaller -// than the required data elements of TypeWrapper or if the requested size is -// smaller than minimum size of TypeStorage. -template <typename Target, size_t totalSize> class TypeWrapperTotalSize { -private: - typedef TypeStorage<Target, 1> MinSizeStorage; - - static const size_t otherDataSize = sizeof(Target *); - - // Round down to be a multiple of alignment_of<MinSizeTargetStorage>::value. - static const size_t internalTargetRawSize = - (totalSize - otherDataSize) / alignment_of<MinSizeStorage>::value * - alignment_of<MinSizeStorage>::value; - -public: - // Use internal storage if internalTargetRawSize is valid and at least as - // large as the minimum size of TypeStorage. - static const size_t internalTargetSize = - ((totalSize > otherDataSize) && - (internalTargetRawSize >= sizeof(MinSizeStorage))) - ? internalTargetRawSize - : 0; -}; - -// Basic type erasure implementation with small object optimization. -template <typename Target, template <typename> class TargetAdapter, - size_t internalTargetSize = - TypeWrapperTotalSize<Target, 32>::internalTargetSize> -class TypeWrapper { -private: - typedef TypeStorage<Target, internalTargetSize> TargetStorage; - -public: - TypeWrapper() : currentTarget(NULL) {} - - TypeWrapper(const TypeWrapper & other) { - if (other.currentTarget == other.internalTarget) { - other.currentTarget->clone(internalTarget); - currentTarget = internalTarget; - } else if (other.currentTarget) { - currentTarget = other.currentTarget->clone(); - } else { - currentTarget = NULL; - } - } - - template <typename Source> TypeWrapper(Source source) { - if (sizeof(TargetAdapter<Source>) <= internalTargetSize && - alignment_of<TargetAdapter<Source> >::value <= - alignment_of<TargetStorage>::value) { - new (internalTarget) TargetAdapter<Source>(source); - currentTarget = internalTarget; - } else { - currentTarget = new TargetAdapter<Source>(source); - } - } - - ~TypeWrapper() { - if (currentTarget == internalTarget) { - currentTarget->~Target(); - } else { - delete currentTarget; - } - } - - const TypeWrapper & operator=(const TypeWrapper & rhs) { - TypeWrapper(rhs).swap(*this); - return *this; - } - - template <typename Source> const TypeWrapper & operator=(Source source) { - TypeWrapper(source).swap(*this); - return *this; - } - - void clear() { TypeWrapper().swap(*this); } - - void swap(TypeWrapper & other) { - if (this == &other) { - return; - } - - if (currentTarget == internalTarget && - other.currentTarget == other.internalTarget) { - TargetStorage temp; - currentTarget->clone(temp); - currentTarget->~Target(); - currentTarget = NULL; - other.currentTarget->clone(internalTarget); - other.currentTarget->~Target(); - other.currentTarget = NULL; - currentTarget = internalTarget; - temp->clone(other.internalTarget); - temp->~Target(); - other.currentTarget = other.internalTarget; - } else if (currentTarget == internalTarget) { - currentTarget->clone(other.internalTarget); - currentTarget->~Target(); - currentTarget = other.currentTarget; - other.currentTarget = other.internalTarget; - } else if (other.currentTarget == other.internalTarget) { - other.currentTarget->clone(internalTarget); - other.currentTarget->~Target(); - other.currentTarget = currentTarget; - currentTarget = internalTarget; - } else { - using std::swap; - swap(currentTarget, other.currentTarget); - } - } - - const Target * target() const { return currentTarget; } - -private: - TargetStorage internalTarget; - Target * currentTarget; -}; - -// TypeWrapper specialization with no internal storage space. -template <typename Target, template <typename> class TargetAdapter> -class TypeWrapper<Target, TargetAdapter, 0> { -public: - TypeWrapper() : currentTarget(NULL) {} - - TypeWrapper(const TypeWrapper & other) { - if (other.currentTarget) { - currentTarget = other.currentTarget->clone(); - } else { - currentTarget = NULL; - } - } - - template <typename Source> - TypeWrapper(Source source) - : currentTarget(new TargetAdapter<Source>(source)) {} - - ~TypeWrapper() { delete currentTarget; } - - const TypeWrapper & operator=(const TypeWrapper & rhs) { - TypeWrapper(rhs).swap(*this); - return *this; - } - - template <typename Source> const TypeWrapper & operator=(Source source) { - TypeWrapper(source).swap(*this); - return *this; - } - - void clear() { TypeWrapper().swap(*this); } - - void swap(TypeWrapper & other) { - using std::swap; - swap(currentTarget, other.currentTarget); - } - - const Target * target() const { return currentTarget; } - -private: - Target * currentTarget; -}; - -} // namespace detail - -// Function wrapper similar to std::function for 0-3 argument functions. -template <typename> class Function; - -// Function implementation for zero argument functions. -template <typename ResultType> class Function<ResultType()> { -public: - typedef ResultType result_type; - - Function(ResultType (*func)() = NULL) : callableWrapper() { - if (func) { - callableWrapper = func; - } - } - - template <typename F> Function(F func) : callableWrapper(func) {} - - const Function & operator=(ResultType (*func)()) { - if (func) { - callableWrapper = func; - } else { - callableWrapper.clear(); - } - return *this; - } - - template <typename F> const Function & operator=(F func) { - callableWrapper = func; - return *this; - } - - void swap(Function & other) { callableWrapper.swap(other.callableWrapper); } - - operator SafeBool() const { - return makeSafeBool(callableWrapper.target() != NULL); - } - - ResultType operator()() const { - return callableWrapper.target() ? callableWrapper.target()->invoke() - : ResultType(); - } - -private: - class Callable { - public: - virtual ~Callable() {} - virtual ResultType invoke() const = 0; - virtual Callable * clone() const = 0; - virtual void clone(void * buffer) const = 0; - }; - - template <typename F> class CallableAdapter : public Callable { - public: - CallableAdapter(F func) : func(func) {} - - virtual ResultType invoke() const { return func(); } - - virtual Callable * clone() const { return new CallableAdapter(*this); } - - virtual void clone(void * buffer) const { - new (buffer) CallableAdapter(*this); - } - - private: - F func; - }; - - detail::TypeWrapper<Callable, CallableAdapter> callableWrapper; -}; - -template <typename ResultType> -inline void swap(Function<ResultType()> & lhs, Function<ResultType()> & rhs) { - lhs.swap(rhs); -} - -// Function implementation for one argument functions. -template <typename ArgumentType, typename ResultType> -class Function<ResultType(ArgumentType)> { -public: - typedef ArgumentType argument_type; - typedef ResultType result_type; - - Function(ResultType (*func)(ArgumentType) = NULL) : callableWrapper() { - if (func) { - callableWrapper = func; - } - } - - template <typename F> Function(F func) : callableWrapper(func) {} - - const Function & operator=(ResultType (*func)(ArgumentType)) { - if (func) { - callableWrapper = func; - } else { - callableWrapper.clear(); - } - return *this; - } - - template <typename F> const Function & operator=(F func) { - callableWrapper = func; - return *this; - } - - void swap(Function & other) { callableWrapper.swap(other.callableWrapper); } - - operator SafeBool() const { - return makeSafeBool(callableWrapper.target() != NULL); - } - - ResultType operator()(ArgumentType arg) const { - return callableWrapper.target() ? callableWrapper.target()->invoke(arg) - : ResultType(); - } - -private: - class Callable { - public: - virtual ~Callable() {} - virtual ResultType invoke(ArgumentType) const = 0; - virtual Callable * clone() const = 0; - virtual void clone(void * buffer) const = 0; - }; - - template <typename F> class CallableAdapter : public Callable { - public: - CallableAdapter(F func) : func(func) {} - - virtual ResultType invoke(ArgumentType arg) const { return func(arg); } - - virtual Callable * clone() const { return new CallableAdapter(*this); } - - virtual void clone(void * buffer) const { - new (buffer) CallableAdapter(*this); - } - - private: - F func; - }; - - detail::TypeWrapper<Callable, CallableAdapter> callableWrapper; -}; - -template <typename ArgumentType, typename ResultType> -inline void swap(Function<ResultType(ArgumentType)> & lhs, - Function<ResultType(ArgumentType)> & rhs) { - lhs.swap(rhs); -} - -// Function implementation for two argument functions. -template <typename FirstArgumentType, typename SecondArgumentType, - typename ResultType> -class Function<ResultType(FirstArgumentType, SecondArgumentType)> { -public: - typedef FirstArgumentType first_argument_type; - typedef SecondArgumentType second_argument_type; - typedef ResultType result_type; - - Function(ResultType (*func)(FirstArgumentType, SecondArgumentType) = NULL) - : callableWrapper() { - if (func) { - callableWrapper = func; - } - } - - template <typename F> Function(F func) : callableWrapper(func) {} - - const Function & operator=(ResultType (*func)(FirstArgumentType, - SecondArgumentType)) { - if (func) { - callableWrapper = func; - } else { - callableWrapper.clear(); - } - return *this; - } - - template <typename F> const Function & operator=(F func) { - callableWrapper = func; - return *this; - } - - void swap(Function & other) { callableWrapper.swap(other.callableWrapper); } - - operator SafeBool() const { - return makeSafeBool(callableWrapper.target() != NULL); - } - - ResultType operator()(FirstArgumentType arg1, SecondArgumentType arg2) const { - return callableWrapper.target() - ? callableWrapper.target()->invoke(arg1, arg2) - : ResultType(); - } - -private: - class Callable { - public: - virtual ~Callable() {} - virtual ResultType invoke(FirstArgumentType, SecondArgumentType) const = 0; - virtual Callable * clone() const = 0; - virtual void clone(void * buffer) const = 0; - }; - - template <typename F> class CallableAdapter : public Callable { - public: - CallableAdapter(F func) : func(func) {} - - virtual ResultType invoke(FirstArgumentType arg1, - SecondArgumentType arg2) const { - return func(arg1, arg2); - } - - virtual Callable * clone() const { return new CallableAdapter(*this); } - - virtual void clone(void * buffer) const { - new (buffer) CallableAdapter(*this); - } - - private: - F func; - }; - - detail::TypeWrapper<Callable, CallableAdapter> callableWrapper; -}; - -template <typename FirstArgumentType, typename SecondArgumentType, - typename ResultType> -inline void -swap(Function<ResultType(FirstArgumentType, SecondArgumentType)> & lhs, - Function<ResultType(FirstArgumentType, SecondArgumentType)> & rhs) { - lhs.swap(rhs); -} - -// Function implementation for three argument functions. -template <typename FirstArgumentType, typename SecondArgumentType, - typename ThirdArgumentType, typename ResultType> -class Function<ResultType(FirstArgumentType, SecondArgumentType, - ThirdArgumentType)> { -public: - typedef ResultType result_type; - - Function(ResultType (*func)(FirstArgumentType, SecondArgumentType, - ThirdArgumentType) = NULL) - : callableWrapper() { - if (func) { - callableWrapper = func; - } - } - - template <typename F> Function(F func) : callableWrapper(func) {} - - const Function & operator=(ResultType (*func)(FirstArgumentType, - SecondArgumentType, - ThirdArgumentType)) { - if (func) { - callableWrapper = func; - } else { - callableWrapper.clear(); - } - return *this; - } - - template <typename F> const Function & operator=(F func) { - callableWrapper = func; - return *this; - } - - void swap(Function & other) { callableWrapper.swap(other.callableWrapper); } - - operator SafeBool() const { - return makeSafeBool(callableWrapper.target() != NULL); - } - - ResultType operator()(FirstArgumentType arg1, SecondArgumentType arg2, - ThirdArgumentType arg3) const { - return callableWrapper.target() - ? callableWrapper.target()->invoke(arg1, arg2, arg3) - : ResultType(); - } - -private: - class Callable { - public: - virtual ~Callable() {} - virtual ResultType invoke(FirstArgumentType, SecondArgumentType, - ThirdArgumentType) const = 0; - virtual Callable * clone() const = 0; - virtual void clone(void * buffer) const = 0; - }; - - template <typename F> class CallableAdapter : public Callable { - public: - CallableAdapter(F func) : func(func) {} - - virtual ResultType invoke(FirstArgumentType arg1, SecondArgumentType arg2, - ThirdArgumentType arg3) const { - return func(arg1, arg2, arg3); - } - - virtual Callable * clone() const { return new CallableAdapter(*this); } - - virtual void clone(void * buffer) const { - new (buffer) CallableAdapter(*this); - } - - private: - F func; - }; - - detail::TypeWrapper<Callable, CallableAdapter> callableWrapper; -}; - -template <typename FirstArgumentType, typename SecondArgumentType, - typename ThirdArgumentType, typename ResultType> -inline void swap(Function<ResultType(FirstArgumentType, SecondArgumentType, - ThirdArgumentType)> & lhs, - Function<ResultType(FirstArgumentType, SecondArgumentType, - ThirdArgumentType)> & rhs) { - lhs.swap(rhs); -} - -} // namespace MaximInterface - -#endif
--- a/Utilities/HexConversions.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include <cctype> -#include <cstdio> -#include <cstdlib> -#include "HexConversions.hpp" - -using std::string; -using std::vector; - -namespace MaximInterface { - -static const int charsPerByte = 2; - -string byteArrayToHexString(span<const uint_least8_t> byteArray) { - string hexString; - hexString.reserve(byteArray.size() * charsPerByte); - for (span<const uint_least8_t>::index_type i = 0; i < byteArray.size(); ++i) { - char hexBuf[charsPerByte + 1]; - std::sprintf(hexBuf, "%2.2X", byteArray[i] & 0xFF); - hexString.append(hexBuf, charsPerByte); - } - return hexString; -} - -optional<vector<uint_least8_t> > -hexStringToByteArray(const string & hexString) { - optional<vector<uint_least8_t> > byteArray = vector<uint_least8_t>(); - byteArray->reserve(hexString.size() / charsPerByte); - char hexBuf[charsPerByte + 1]; - char * const hexBufEnd = hexBuf + charsPerByte; - *hexBufEnd = '\0'; - char * hexBufIt = hexBuf; - for (string::const_iterator hexStringIt = hexString.begin(), - hexStringEnd = hexString.end(); - hexStringIt != hexStringEnd; ++hexStringIt) { - if (!std::isspace(*hexStringIt)) { - *hexBufIt = *hexStringIt; - if (++hexBufIt == hexBufEnd) { - char * hexBufParseEnd; - byteArray->push_back(static_cast<uint_least8_t>( - std::strtoul(hexBuf, &hexBufParseEnd, 16))); - if (hexBufParseEnd != hexBufEnd) { - break; - } - hexBufIt = hexBuf; - } - } - } - if (hexBufIt != hexBuf) { - byteArray.reset(); - } - return byteArray; -} - -} // namespace MaximInterface
--- a/Utilities/HexConversions.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_HexConversions -#define MaximInterface_HexConversions - -#include <stddef.h> -#include <stdint.h> -#include <string> -#include <vector> -#include "Export.h" -#include "optional.hpp" -#include "span.hpp" - -namespace MaximInterface { - -/// Convert a byte array to a hex string. -MaximInterface_EXPORT std::string -byteArrayToHexString(span<const uint_least8_t> byteArray); - -/// Convert a hex string to a byte array. -MaximInterface_EXPORT optional<std::vector<uint_least8_t> > -hexStringToByteArray(const std::string & hexString); - -} // namespace MaximInterface - -#endif
--- a/Utilities/ManId.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_ManId -#define MaximInterface_ManId - -#include "array_span.hpp" - -namespace MaximInterface { - -/// Standard container for a manufacturer ID. -typedef array_span<uint_least8_t, 2> ManId; - -} // namespace MaximInterface - -#endif
--- a/Utilities/RomId.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_RomId -#define MaximInterface_RomId - -#include "array_span.hpp" -#include "crc.hpp" - -namespace MaximInterface { - -/// Standard container for a 1-Wire ROM ID. -typedef array_span<uint_least8_t, 8> RomId; - -/// @name Family Code -/// @{ - -/// Get the Family Code byte. -inline RomId::element familyCode(RomId::const_span romId) { - return romId[0]; -} - -/// Set the Family Code byte. -inline void setFamilyCode(RomId::span romId, RomId::element familyCode) { - romId[0] = familyCode; -} - -/// @} - -/// @name CRC8 -/// @{ - -/// Get the CRC8 byte. -inline RomId::element crc8(RomId::const_span romId) { - return *romId.last<1>().data(); -} - -/// Set the CRC8 byte. -inline void setCrc8(RomId::span romId, RomId::element crc8) { - *romId.last<1>().data() = crc8; -} - -/// @} - -/// @brief Check if the ROM ID is valid (Family Code and CRC8 are both valid). -/// @returns True if the ROM ID is valid. -inline bool valid(RomId::const_span romId) { - return calculateCrc8(romId.first(romId.size() - 1)) == crc8(romId); -} - -} // namespace MaximInterface - -#endif
--- a/Utilities/SafeBool.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_SafeBool -#define MaximInterface_SafeBool - -#include <stddef.h> - -namespace MaximInterface { -namespace detail { - -// Implement SafeBool as a member function pointer since some compilers allow -// function pointer to void pointer conversion. -struct SafeBoolHelper { - void trueValue() const {} - -private: - SafeBoolHelper(); // deleted -}; - -} // namespace detail - -/// @brief Type definition for SafeBool. -/// @details -/// SafeBool is a boolean type that eliminates many error-prone implicit -/// conversions allowed by the fundamental bool type. -/// @note -/// SafeBool can be used to add an explicit bool conversion operator to a type. -typedef void (detail::SafeBoolHelper::*SafeBool)() const; - -/// Constructor for SafeBool. -inline SafeBool makeSafeBool(bool value) { - return value ? &detail::SafeBoolHelper::trueValue : NULL; -} - -} // namespace MaximInterface - -#endif
--- a/Utilities/Segment.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,135 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_Segment -#define MaximInterface_Segment - -#include <iterator> -#include <utility> -#include "type_traits.hpp" - -namespace MaximInterface { - -/// @brief -/// Advances a given iterator by a given number of elements with bounds checking. -/// @tparam InputIt Must meet the requirements of InputIterator. -/// @param[in,out] it Iterator to advance. -/// @param bound -/// Past-the-end boundary iterator. If distance is positive, bound must be -/// reachable by incrementing the given iterator. If distance is negative, bound -/// must be reachable by decrementing the given iterator. -/// @param distance -/// Number of elements to advance the given iterator. If distance is positive, -/// the given iterator is incremented. If distance is negative, the given -/// iterator is decremented, and InputIt must meet the requirements of -/// BidirectionalIterator. -/// @returns The number of elements that the given iterator was advanced. -template <typename InputIt> -typename std::iterator_traits<InputIt>::difference_type checkedAdvance( - InputIt & it, const InputIt bound, - typename std::iterator_traits<InputIt>::difference_type distance) { - typedef - typename std::iterator_traits<InputIt>::difference_type difference_type; - - // Use constant-time operations if InputIt is a random access iterator. - if (is_same<typename std::iterator_traits<InputIt>::iterator_category, - std::random_access_iterator_tag>::value) { - const difference_type boundDistance = std::distance(it, bound); - if (boundDistance >= 0) { - if (distance > boundDistance) { - distance = boundDistance; - } else if (distance < 0) { - distance = 0; - } - } else { - if (distance < boundDistance) { - distance = boundDistance; - } else if (distance > 0) { - distance = 0; - } - } - std::advance(it, distance); - } else { - const difference_type startingDistance = distance; - while (distance != 0 && it != bound) { - if (distance > 0) { - ++it; - --distance; - } else { - --it; - ++distance; - } - } - if (startingDistance > 0) { - distance = startingDistance - distance; - } else { - distance = startingDistance + distance; - } - } - return distance; -} - -/// @brief Locates an iterator sub-range using segment number addressing. -/// @details -/// Useful for devices that divide the memory space into uniform chunks such as -/// pages and segments. -/// @tparam ForwardIt Must meet the requirements of ForwardIterator. -/// @param begin Beginning of the input data range. -/// @param end End of the input data range. -/// @param segmentSize Number of elements contained in a segment. -/// @param segmentNum Zero-indexed number of the desired segment. -/// @returns -/// Pair of iterators representing the sub-range of the segment within -/// the input range. If the segment does not exist within the input range, both -/// iterators in the pair are set to the end iterator of the input range. -template <typename ForwardIt, typename Index> -std::pair<ForwardIt, ForwardIt> createSegment( - ForwardIt begin, const ForwardIt end, - const typename std::iterator_traits<ForwardIt>::difference_type segmentSize, - Index segmentNum) { - ForwardIt segmentEnd = begin; - typename std::iterator_traits<ForwardIt>::difference_type lastSegmentSize = - checkedAdvance(segmentEnd, end, segmentSize); - while (segmentNum > 0 && segmentEnd != end) { - begin = segmentEnd; - lastSegmentSize = checkedAdvance(segmentEnd, end, segmentSize); - --segmentNum; - } - if (segmentNum > 0 || lastSegmentSize != segmentSize) { - begin = segmentEnd; - } - return std::make_pair(begin, segmentEnd); -} - -} // namespace MaximInterface - -#endif \ No newline at end of file
--- a/Utilities/Sha256.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_Sha256 -#define MaximInterface_Sha256 - -#include <stdint.h> -#include "array_span.hpp" - -namespace MaximInterface { -namespace Sha256 { - -/// Container for a SHA-256 hash. -typedef array_span<uint_least8_t, 32> Hash; - -/// @brief Data for Compute Write MAC operation. -/// @details -/// Used by SHA-256 MAC authenticators including DS28E15/22/25 and DS2465. -typedef array_span<uint_least8_t, 20> WriteMacData; - -/// @brief Data for the Compute Auth. MAC and Compute Slave Secret operations. -/// @copydetails WriteMacData -typedef array_span<uint_least8_t, 76> AuthenticationData; - -} // namespace Sha256 -} // namespace MaximInterface - -#endif
--- a/Utilities/Uncopyable.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_Uncopyable -#define MaximInterface_Uncopyable - -namespace MaximInterface { - -class Uncopyable { -protected: - Uncopyable() {} - ~Uncopyable() {} - -private: - Uncopyable(const Uncopyable &); - const Uncopyable & operator=(const Uncopyable &); -}; - -} // namespace MaximInterface - -#endif
--- a/Utilities/WriteMessage.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_WriteMessage -#define MaximInterface_WriteMessage - -#include <string> -#include "Function.hpp" - -namespace MaximInterface { - -/// Writes a message string to an output. -typedef Function<void(const std::string &)> WriteMessage; - -} - -#endif
--- a/Utilities/array.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,191 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_array -#define MaximInterface_array - -#include <stddef.h> -#include <stdint.h> -#include <algorithm> -#include <iterator> - -namespace MaximInterface { - -/// Generic array class similar to std::array. -template <typename T, size_t N> class array { -public: - typedef T value_type; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef value_type & reference; - typedef const value_type & const_reference; - typedef value_type * pointer; - typedef const value_type * const_pointer; - typedef pointer iterator; - typedef const_pointer const_iterator; - typedef std::reverse_iterator<iterator> reverse_iterator; - typedef std::reverse_iterator<const_iterator> const_reverse_iterator; - - /// @name Element access - /// @{ - - reference operator[](size_type pos) { - return const_cast<reference>( - static_cast<const array &>(*this).operator[](pos)); - } - - const_reference operator[](size_type pos) const { return data()[pos]; } - - reference front() { - return const_cast<reference>(static_cast<const array &>(*this).front()); - } - - const_reference front() const { return operator[](0); } - - reference back() { - return const_cast<reference>(static_cast<const array &>(*this).back()); - } - - const_reference back() const { return operator[](size() - 1); } - - pointer data() { - return const_cast<pointer>(static_cast<const array &>(*this).data()); - } - - const_pointer data() const { return _buffer; } - - /// @} - - /// @name Iterators - /// @{ - - iterator begin() { - return const_cast<iterator>(static_cast<const array &>(*this).cbegin()); - } - - const_iterator begin() const { return cbegin(); } - - const_iterator cbegin() const { return data(); } - - iterator end() { - return const_cast<iterator>(static_cast<const array &>(*this).cend()); - } - - const_iterator end() const { return cend(); } - - const_iterator cend() const { return cbegin() + size(); } - - reverse_iterator rbegin() { return reverse_iterator(end()); } - - const_reverse_iterator rbegin() const { - return const_reverse_iterator(end()); - } - - const_reverse_iterator crbegin() const { return rbegin(); } - - reverse_iterator rend() { return reverse_iterator(begin()); } - - const_reverse_iterator rend() const { - return const_reverse_iterator(begin()); - } - - const_reverse_iterator crend() const { return rend(); } - - /// @} - - /// @name Capacity - /// @{ - - static bool empty() { return size() == 0; } - - static size_type size() { return N; } - - static size_type max_size() { return size(); } - - /// Alternative to size() when a constant expression is required. - static const size_type csize = N; - - /// @} - - /// @name Operations - /// @{ - - void fill(const_reference value) { std::fill(begin(), end(), value); } - - void swap(array & other) { std::swap_ranges(begin(), end(), other.begin()); } - - /// @} - - /// @private - /// @note Implementation detail set public to allow aggregate initialization. - T _buffer[N]; -}; - -template <typename T, size_t N> -inline bool operator==(const array<T, N> & lhs, const array<T, N> & rhs) { - return std::equal(lhs.begin(), lhs.end(), rhs.begin()); -} - -template <typename T, size_t N> -inline bool operator!=(const array<T, N> & lhs, const array<T, N> & rhs) { - return !operator==(lhs, rhs); -} - -template <typename T, size_t N> -inline bool operator<(const array<T, N> & lhs, const array<T, N> & rhs) { - return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), - rhs.end()); -} - -template <typename T, size_t N> -inline bool operator>(const array<T, N> & lhs, const array<T, N> & rhs) { - return operator<(rhs, lhs); -} - -template <typename T, size_t N> -inline bool operator<=(const array<T, N> & lhs, const array<T, N> & rhs) { - return !operator>(lhs, rhs); -} - -template <typename T, size_t N> -inline bool operator>=(const array<T, N> & lhs, const array<T, N> & rhs) { - return !operator<(lhs, rhs); -} - -template <typename T, size_t N> -inline void swap(array<T, N> & lhs, array<T, N> & rhs) { - lhs.swap(rhs); -} - -} // namespace MaximInterface - -#endif
--- a/Utilities/array_span.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_array_span -#define MaximInterface_array_span - -#include "array.hpp" -#include "span.hpp" -#include "type_traits.hpp" - -namespace MaximInterface { - -/// @brief -/// Defines a standard set of types for data fields that are represented as a -/// fixed-size array of elements. -/// @tparam T A const qualifier is not allowed. -template <typename T, size_t N> struct array_span { - typedef typename remove_volatile<T>::type element; - static const size_t size = N; - - typedef MaximInterface::array<element, N> array; - typedef MaximInterface::span<const T, N> const_span; - typedef MaximInterface::span<T, N> span; - -private: - array_span(); // deleted -}; - -// Specialization for "const T" is not defined. -template <typename T, size_t N> struct array_span<const T, N>; - -} - -#endif
--- a/Utilities/crc.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include "crc.hpp" - -namespace MaximInterface { - -uint_fast8_t calculateCrc8(uint_fast8_t data, uint_fast8_t crc) { - // See Application Note 27 - crc ^= data; - crc &= 0xff; - for (int i = 0; i < 8; i++) { - if (crc & 1) { - crc = (crc >> 1) ^ 0x8c; - } else { - crc = (crc >> 1); - } - } - return crc; -} - -uint_fast8_t calculateCrc8(span<const uint_least8_t> data, uint_fast8_t crc) { - for (span<const uint_least8_t>::index_type i = 0; i < data.size(); ++i) { - crc = calculateCrc8(data[i], crc); - } - return crc; -} - -uint_fast16_t calculateCrc16(uint_fast8_t data, uint_fast16_t crc) { - const uint_least8_t oddparity[] = {0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0}; - - uint_fast16_t data16 = (data ^ crc) & 0xff; - crc = (crc >> 8) & 0xff; - - if (oddparity[data16 & 0xf] ^ oddparity[data16 >> 4]) { - crc ^= 0xc001; - } - - data16 <<= 6; - crc ^= data16; - data16 <<= 1; - crc ^= data16; - - return crc; -} - -uint_fast16_t calculateCrc16(span<const uint_least8_t> data, - uint_fast16_t crc) { - for (span<const uint_least8_t>::index_type i = 0; i < data.size(); ++i) { - crc = calculateCrc16(data[i], crc); - } - return crc; -} - -} // namespace MaximInterface
--- a/Utilities/crc.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_crc -#define MaximInterface_crc - -#include <stddef.h> -#include <stdint.h> -#include <MaximInterface/Utilities/Export.h> -#include "span.hpp" - -namespace MaximInterface { - -/// @brief Perform a CRC8 calculation. -/// @param data Data to pass though the CRC generator. -/// @param crc Beginning state of the CRC generator. -/// @returns The calculated CRC8. -MaximInterface_EXPORT uint_fast8_t calculateCrc8(uint_fast8_t data, - uint_fast8_t crc = 0); - -/// @brief Perform a CRC8 calculation with variable length data. -/// @param[in] data Data array to pass through the CRC generator. -/// @param crc Beginning state of the CRC generator. -/// @returns The calculated CRC8. -MaximInterface_EXPORT uint_fast8_t calculateCrc8(span<const uint_least8_t> data, - uint_fast8_t crc = 0); - -/// @brief Perform a CRC16 calculation. -/// @param data Data to pass though the CRC generator. -/// @param crc Beginning state of the CRC generator. -/// @returns The calculated CRC16. -MaximInterface_EXPORT uint_fast16_t calculateCrc16(uint_fast8_t data, - uint_fast16_t crc = 0); - -/// @brief Perform a CRC16 calculation with variable length data. -/// @param[in] data Data array to pass through the CRC generator. -/// @param crc Beginning state of the CRC generator. -/// @returns The calculated CRC16. -MaximInterface_EXPORT uint_fast16_t -calculateCrc16(span<const uint_least8_t> data, uint_fast16_t crc = 0); - -} // namespace MaximInterface - -#endif
--- a/Utilities/optional.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,318 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_optional -#define MaximInterface_optional - -#include "SafeBool.hpp" - -// Include for std::swap. -#include <algorithm> -#include <utility> - -namespace MaximInterface { - -struct nullopt_t { - explicit nullopt_t(int) {} -}; - -static const nullopt_t nullopt(0); - -/// @brief Optional value container similar to std::optional. -/// @details -/// To prevent the need for aligned storage, this implementation imposes that -/// types must be DefaultConstructible, CopyConstructible, and CopyAssignable. -/// No exceptions are thrown when accessing a valueless optional. -template <typename T> class optional { -public: - typedef T value_type; - - optional() : value_(), has_value_(false) {} - - optional(nullopt_t) : value_(), has_value_(false) {} - - optional(const T & value) : value_(value), has_value_(true) {} - - template <typename U> - explicit optional(const optional<U> & other) - : value_(other.value_), has_value_(other.has_value_) {} - - optional & operator=(nullopt_t) { - reset(); - return *this; - } - - optional & operator=(const T & value) { - value_ = value; - has_value_ = true; - return *this; - } - - template <typename U> optional & operator=(const optional<U> & other) { - if (has_value_ || other.has_value_) { - value_ = other.value_; - has_value_ = other.has_value_; - } - return *this; - } - - bool has_value() const { return has_value_; } - - operator SafeBool() const { return makeSafeBool(has_value()); } - - const T & value() const { return value_; } - - T & value() { - return const_cast<T &>(static_cast<const optional &>(*this).value()); - } - - const T & operator*() const { return value(); } - - T & operator*() { - return const_cast<T &>(static_cast<const optional &>(*this).operator*()); - } - - const T * operator->() const { return &value(); } - - T * operator->() { - return const_cast<T *>(static_cast<const optional &>(*this).operator->()); - } - - const T & value_or(const T & default_value) const { - return has_value() ? value() : default_value; - } - - void swap(optional & other) { - if (has_value_ || other.has_value_) { - using std::swap; - swap(value_, other.value_); - swap(has_value_, other.has_value_); - } - } - - void reset() { - if (has_value_) { - has_value_ = false; - value_ = T(); - } - } - -private: - T value_; - bool has_value_; -}; - -template <typename T> optional<T> make_optional(const T & value) { - return value; -} - -template <typename T> void swap(optional<T> & lhs, optional<T> & rhs) { - lhs.swap(rhs); -} - -template <typename T, typename U> -bool operator==(const optional<T> & lhs, const optional<U> & rhs) { - if (lhs.has_value() != rhs.has_value()) { - return false; - } - if (!lhs.has_value()) { - return true; - } - return lhs.value() == rhs.value(); -} - -template <typename T, typename U> -bool operator!=(const optional<T> & lhs, const optional<U> & rhs) { - if (lhs.has_value() != rhs.has_value()) { - return true; - } - if (!lhs.has_value()) { - return false; - } - return lhs.value() != rhs.value(); -} - -template <typename T, typename U> -bool operator<(const optional<T> & lhs, const optional<U> & rhs) { - if (!rhs.has_value()) { - return false; - } - if (!lhs.has_value()) { - return true; - } - return lhs.value() < rhs.value(); -} - -template <typename T, typename U> -bool operator<=(const optional<T> & lhs, const optional<U> & rhs) { - if (!lhs.has_value()) { - return true; - } - if (!rhs.has_value()) { - return false; - } - return lhs.value() <= rhs.value(); -} - -template <typename T, typename U> -bool operator>(const optional<T> & lhs, const optional<U> & rhs) { - if (!lhs.has_value()) { - return false; - } - if (!rhs.has_value()) { - return true; - } - return lhs.value() > rhs.value(); -} - -template <typename T, typename U> -bool operator>=(const optional<T> & lhs, const optional<U> & rhs) { - if (!rhs.has_value()) { - return true; - } - if (!lhs.has_value()) { - return false; - } - return lhs.value() >= rhs.value(); -} - -template <typename T> bool operator==(const optional<T> & opt, nullopt_t) { - return !opt.has_value(); -} - -template <typename T> bool operator==(nullopt_t, const optional<T> & opt) { - return operator==(opt, nullopt); -} - -template <typename T> bool operator!=(const optional<T> & opt, nullopt_t) { - return !operator==(opt, nullopt); -} - -template <typename T> bool operator!=(nullopt_t, const optional<T> & opt) { - return operator!=(opt, nullopt); -} - -template <typename T> bool operator<(const optional<T> &, nullopt_t) { - return false; -} - -template <typename T> bool operator<(nullopt_t, const optional<T> & opt) { - return opt.has_value(); -} - -template <typename T> bool operator<=(const optional<T> & opt, nullopt_t) { - return !operator>(opt, nullopt); -} - -template <typename T> bool operator<=(nullopt_t, const optional<T> & opt) { - return !operator>(nullopt, opt); -} - -template <typename T> bool operator>(const optional<T> & opt, nullopt_t) { - return operator<(nullopt, opt); -} - -template <typename T> bool operator>(nullopt_t, const optional<T> & opt) { - return operator<(opt, nullopt); -} - -template <typename T> bool operator>=(const optional<T> & opt, nullopt_t) { - return !operator<(opt, nullopt); -} - -template <typename T> bool operator>=(nullopt_t, const optional<T> & opt) { - return !operator<(nullopt, opt); -} - -template <typename T, typename U> -bool operator==(const optional<T> & opt, const U & value) { - return opt.has_value() ? opt.value() == value : false; -} - -template <typename T, typename U> -bool operator==(const T & value, const optional<U> & opt) { - return operator==(opt, value); -} - -template <typename T, typename U> -bool operator!=(const optional<T> & opt, const U & value) { - return opt.has_value() ? opt.value() != value : true; -} - -template <typename T, typename U> -bool operator!=(const T & value, const optional<U> & opt) { - return operator!=(opt, value); -} - -template <typename T, typename U> -bool operator<(const optional<T> & opt, const U & value) { - return opt.has_value() ? opt.value() < value : true; -} - -template <typename T, typename U> -bool operator<(const T & value, const optional<U> & opt) { - return opt.has_value() ? value < opt.value() : false; -} - -template <typename T, typename U> -bool operator<=(const optional<T> & opt, const U & value) { - return opt.has_value() ? opt.value() <= value : true; -} - -template <typename T, typename U> -bool operator<=(const T & value, const optional<U> & opt) { - return opt.has_value() ? value <= opt.value() : false; -} - -template <typename T, typename U> -bool operator>(const optional<T> & opt, const U & value) { - return opt.has_value() ? opt.value() > value : false; -} - -template <typename T, typename U> -bool operator>(const T & value, const optional<U> & opt) { - return opt.has_value() ? value > opt.value() : true; -} - -template <typename T, typename U> -bool operator>=(const optional<T> & opt, const U & value) { - return opt.has_value() ? opt.value() >= value : false; -} - -template <typename T, typename U> -bool operator>=(const T & value, const optional<U> & opt) { - return opt.has_value() ? value >= opt.value() : true; -} - -} // namespace MaximInterface - -#endif
--- a/Utilities/span.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,366 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_span -#define MaximInterface_span - -#include <stddef.h> -#include <algorithm> -#include <iterator> -#include <vector> -#include "array.hpp" -#include "type_traits.hpp" - -namespace MaximInterface { - -static const ptrdiff_t dynamic_extent = -1; - -struct with_container_t { - explicit with_container_t(int) {} -}; - -static const with_container_t with_container(0); - -namespace detail { - -template <template <typename, ptrdiff_t = MaximInterface::dynamic_extent> - class span, - typename T, ptrdiff_t Extent> -class span_base { -public: - typedef T element_type; - typedef typename remove_cv<element_type>::type value_type; - typedef ptrdiff_t index_type; - typedef ptrdiff_t difference_type; - typedef element_type * pointer; - typedef element_type & reference; - typedef element_type * iterator; - typedef const element_type * const_iterator; - typedef std::reverse_iterator<iterator> reverse_iterator; - typedef std::reverse_iterator<const_iterator> const_reverse_iterator; - - static const index_type extent = Extent; - -protected: - span_base(pointer data) : data_(data) {} - ~span_base() {} - -public: - /// @name Iterators - /// @{ - - iterator begin() const { - return const_cast<iterator>(static_cast<const span_base &>(*this).cbegin()); - } - - const_iterator cbegin() const { return data(); } - - iterator end() const { - return const_cast<iterator>(static_cast<const span_base &>(*this).cend()); - } - - const_iterator cend() const { return cbegin() + size(); } - - reverse_iterator rbegin() const { return reverse_iterator(end()); } - - const_reverse_iterator crbegin() const { - return const_reverse_iterator(cend()); - } - - reverse_iterator rend() const { return reverse_iterator(begin()); } - - const_reverse_iterator crend() const { - return const_reverse_iterator(cbegin()); - } - - /// @} - - /// @name Element access - /// @{ - - reference operator[](index_type idx) const { return data()[idx]; } - - reference operator()(index_type idx) const { return operator[](idx); } - - pointer data() const { return data_; } - - /// @} - - /// @name Subviews - /// @{ - - template <index_type Count> span<element_type, Count> first() const { - return subspan<0, Count>(); - } - - span<element_type> first(index_type Count) const { return subspan(0, Count); } - - span<element_type> last(index_type Count) const { - return subspan(size() - Count, Count); - } - - template <index_type Offset, index_type Count> - span<element_type, Count> subspan() const { - return span<element_type, Count>(data() + Offset, Count); - } - - span<element_type> subspan(index_type Offset, - index_type Count = dynamic_extent) const { - return span<element_type>( - data() + Offset, Count == dynamic_extent ? size() - Offset : Count); - } - - /// @} - -private: - index_type size() const { - return static_cast<const span<T, Extent> &>(*this).size(); - } - - pointer data_; -}; - -} // namespace detail - -/// Generic memory span class similar to gsl::span or the proposed std::span. -template <typename T, ptrdiff_t Extent = dynamic_extent> -class span : public detail::span_base<MaximInterface::span, T, Extent> { - typedef detail::span_base<MaximInterface::span, T, Extent> span_base; - -public: - using span_base::extent; - using typename span_base::element_type; - using typename span_base::index_type; - using typename span_base::pointer; - using typename span_base::value_type; - - span(pointer data, index_type) : span_base(data) {} - - span(pointer begin, pointer) : span_base(begin) {} - - span(element_type (&arr)[extent]) : span_base(arr) {} - - span(array<value_type, extent> & arr) : span_base(arr.data()) {} - - span(const array<value_type, extent> & arr) : span_base(arr.data()) {} - - template <typename U> span(const span<U, extent> & s) : span_base(s.data()) {} - - template <typename Allocator> - explicit span(std::vector<value_type, Allocator> & vec) - : span_base(&vec.front()) {} - - template <typename Allocator> - explicit span(const std::vector<value_type, Allocator> & vec) - : span_base(&vec.front()) {} - - template <typename Container> - span(with_container_t, Container & cont) : span_base(cont.data()) {} - - template <typename Container> - span(with_container_t, const Container & cont) : span_base(cont.data()) {} - - /// @name Observers - /// @{ - - static index_type size() { return extent; } - - static index_type size_bytes() { return size() * sizeof(element_type); } - - static bool empty() { return size() == 0; } - - /// @} - - /// @name Subviews - /// @{ - - template <index_type Count> span<element_type, Count> last() const { - return this->template subspan<extent - Count, Count>(); - } - - /// @} -}; - -template <typename T> -class span<T, dynamic_extent> - : public detail::span_base<MaximInterface::span, T, dynamic_extent> { - typedef detail::span_base<MaximInterface::span, T, dynamic_extent> span_base; - -public: - using typename span_base::element_type; - using typename span_base::index_type; - using typename span_base::pointer; - using typename span_base::value_type; - - span() : span_base(NULL), size_(0) {} - - span(pointer data, index_type size) : span_base(data), size_(size) {} - - span(pointer begin, pointer end) : span_base(begin), size_(end - begin) {} - - template <size_t N> span(element_type (&arr)[N]) : span_base(arr), size_(N) {} - - template <size_t N> - span(array<value_type, N> & arr) : span_base(arr.data()), size_(N) {} - - template <size_t N> - span(const array<value_type, N> & arr) : span_base(arr.data()), size_(N) {} - - template <typename U, ptrdiff_t N> - span(const span<U, N> & s) : span_base(s.data()), size_(s.size()) {} - - template <typename Allocator> - span(std::vector<value_type, Allocator> & vec) - : span_base(vec.empty() ? NULL : &vec.front()), size_(vec.size()) {} - - template <typename Allocator> - span(const std::vector<value_type, Allocator> & vec) - : span_base(vec.empty() ? NULL : &vec.front()), size_(vec.size()) {} - - template <typename Container> - span(with_container_t, Container & cont) - : span_base(cont.data()), size_(cont.size()) {} - - template <typename Container> - span(with_container_t, const Container & cont) - : span_base(cont.data()), size_(cont.size()) {} - - /// @name Observers - /// @{ - - index_type size() const { return size_; } - - index_type size_bytes() const { return size() * sizeof(element_type); } - - bool empty() const { return size() == 0; } - - /// @} - - /// @name Subviews - /// @{ - - template <index_type Count> span<element_type, Count> last() const { - return span<element_type, Count>(this->data() + (size() - Count), Count); - } - - /// @} - -private: - index_type size_; -}; - -template <typename T, ptrdiff_t Extent, typename U> -bool operator==(span<T, Extent> lhs, span<U, Extent> rhs) { - return lhs.size() == rhs.size() && - std::equal(lhs.begin(), lhs.end(), rhs.begin()); -} - -template <typename T, ptrdiff_t Extent, typename U> -bool operator!=(span<T, Extent> lhs, span<U, Extent> rhs) { - return !operator==(lhs, rhs); -} - -template <typename T, ptrdiff_t Extent, typename U> -bool operator<(span<T, Extent> lhs, span<U, Extent> rhs) { - return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), - rhs.end()); -} - -template <typename T, ptrdiff_t Extent, typename U> -bool operator>(span<T, Extent> lhs, span<U, Extent> rhs) { - return operator<(rhs, lhs); -} - -template <typename T, ptrdiff_t Extent, typename U> -bool operator<=(span<T, Extent> lhs, span<U, Extent> rhs) { - return !operator>(lhs, rhs); -} - -template <typename T, ptrdiff_t Extent, typename U> -bool operator>=(span<T, Extent> lhs, span<U, Extent> rhs) { - return !operator<(lhs, rhs); -} - -template <typename T> -span<T> make_span(T * data, typename span<T>::index_type size) { - return span<T>(data, size); -} - -template <typename T> span<T> make_span(T * begin, T * end) { - return span<T>(begin, end); -} - -template <typename T, size_t N> span<T, N> make_span(T (&arr)[N]) { - return span<T, N>(arr); -} - -template <typename T, size_t N> span<T, N> make_span(array<T, N> & arr) { - return arr; -} - -template <typename T, size_t N> -span<const T, N> make_span(const array<T, N> & arr) { - return arr; -} - -template <typename T, typename Allocator> -span<T> make_span(std::vector<T, Allocator> & vec) { - return vec; -} - -template <typename T, typename Allocator> -span<const T> make_span(const std::vector<T, Allocator> & vec) { - return vec; -} - -template <typename Container> -span<typename Container::value_type> make_span(with_container_t, - Container & cont) { - return span<typename Container::value_type>(with_container, cont); -} - -template <typename Container> -span<const typename Container::value_type> make_span(with_container_t, - const Container & cont) { - return span<const typename Container::value_type>(with_container, cont); -} - -/// Deep copy between static spans of the same size. -template <typename T, ptrdiff_t Extent, typename U> -typename enable_if<Extent != dynamic_extent>::type copy(span<T, Extent> src, - span<U, Extent> dst) { - std::copy(src.begin(), src.end(), dst.begin()); -} - -} // namespace MaximInterface - -#endif
--- a/Utilities/system_error.cpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#include "Error.hpp" -#include "system_error.hpp" - -namespace MaximInterface { - -using std::string; - -error_condition error_category::default_error_condition(int code) const { - return error_condition(code, *this); -} - -bool error_category::equivalent(int code, - const error_condition & condition) const { - return default_error_condition(code) == condition; -} - -bool error_category::equivalent(const error_code & code, int condition) const { - return *this == code.category() && code.value() == condition; -} - -const error_category & system_category() { - static class : public error_category { - public: - virtual const char * name() const { return "system"; } - - virtual string message(int condition) const { - return defaultErrorMessage(condition); - } - } instance; - return instance; -} - -static string formatWhat(const error_code & ec) { - return string(ec.category().name()) + ' ' + ec.message(); -} - -template <typename T> -static string formatWhat(const error_code & ec, const T & what_arg) { - return string(what_arg) + ": " + formatWhat(ec); -} - -system_error::system_error(const error_code & ec) - : runtime_error(formatWhat(ec)), code_(ec) {} - -system_error::system_error(const error_code & ec, const string & what_arg) - : runtime_error(formatWhat(ec, what_arg)), code_(ec) {} - -system_error::system_error(const error_code & ec, const char * what_arg) - : runtime_error(formatWhat(ec, what_arg)), code_(ec) {} - -system_error::system_error(int ev, const error_category & ecat) - : runtime_error(formatWhat(error_code(ev, ecat))), code_(ev, ecat) {} - -system_error::system_error(int ev, const error_category & ecat, - const string & what_arg) - : runtime_error(formatWhat(error_code(ev, ecat), what_arg)), - code_(ev, ecat) {} - -system_error::system_error(int ev, const error_category & ecat, - const char * what_arg) - : runtime_error(formatWhat(error_code(ev, ecat), what_arg)), - code_(ev, ecat) {} - -} // namespace MaximInterface
--- a/Utilities/system_error.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,227 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -/// @file -/// @brief -/// Error handling constructs similar to std::error_code, std::error_condition, -/// and std::error_category. - -#ifndef MaximInterface_system_error -#define MaximInterface_system_error - -#include <stdexcept> -#include <string> -#include "Export.h" -#include "SafeBool.hpp" -#include "Uncopyable.hpp" - -namespace MaximInterface { - -class error_condition; -class error_code; - -class error_category : private Uncopyable { -public: - virtual ~error_category() {} - - virtual const char * name() const = 0; - - MaximInterface_EXPORT virtual error_condition - default_error_condition(int code) const; - - MaximInterface_EXPORT virtual bool - equivalent(int code, const error_condition & condition) const; - - MaximInterface_EXPORT virtual bool equivalent(const error_code & code, - int condition) const; - - virtual std::string message(int condition) const = 0; -}; - -inline bool operator==(const error_category & lhs, const error_category & rhs) { - return &lhs == &rhs; -} - -inline bool operator!=(const error_category & lhs, const error_category & rhs) { - return !operator==(lhs, rhs); -} - -inline bool operator<(const error_category & lhs, const error_category & rhs) { - return &lhs < &rhs; -} - -MaximInterface_EXPORT const error_category & system_category(); - -class error_condition { -public: - error_condition() : value_(0), category_(&system_category()) {} - - error_condition(int value, const error_category & category) - : value_(value), category_(&category) {} - - void assign(int value, const error_category & category) { - value_ = value; - category_ = &category; - } - - void clear() { - value_ = 0; - category_ = &system_category(); - } - - int value() const { return value_; } - - const error_category & category() const { return *category_; } - - std::string message() const { return category().message(value()); } - - operator SafeBool() const { return makeSafeBool(value() != 0); } - -private: - int value_; - const error_category * category_; -}; - -inline bool operator==(const error_condition & lhs, - const error_condition & rhs) { - return (lhs.value() == rhs.value()) && (lhs.category() == rhs.category()); -} - -inline bool operator!=(const error_condition & lhs, - const error_condition & rhs) { - return !operator==(lhs, rhs); -} - -inline bool operator<(const error_condition & lhs, - const error_condition & rhs) { - return (lhs.category() < rhs.category()) || - ((lhs.category() == rhs.category()) && (lhs.value() < rhs.value())); -} - -class error_code { -public: - error_code() : value_(0), category_(&system_category()) {} - - error_code(int value, const error_category & category) - : value_(value), category_(&category) {} - - void assign(int value, const error_category & category) { - value_ = value; - category_ = &category; - } - - void clear() { - value_ = 0; - category_ = &system_category(); - } - - int value() const { return value_; } - - const error_category & category() const { return *category_; } - - error_condition default_error_condition() const { - return category().default_error_condition(value()); - } - - std::string message() const { return category().message(value()); } - - operator SafeBool() const { return makeSafeBool(value() != 0); } - -private: - int value_; - const error_category * category_; -}; - -inline bool operator==(const error_code & lhs, const error_code & rhs) { - return (lhs.value() == rhs.value()) && (lhs.category() == rhs.category()); -} - -inline bool operator!=(const error_code & lhs, const error_code & rhs) { - return !operator==(lhs, rhs); -} - -inline bool operator<(const error_code & lhs, const error_code & rhs) { - return (lhs.category() < rhs.category()) || - ((lhs.category() == rhs.category()) && (lhs.value() < rhs.value())); -} - -template <typename CharT, typename Traits> -std::basic_ostream<CharT, Traits> & -operator<<(std::basic_ostream<CharT, Traits> & os, const error_code & ec) { - os << ec.category().name() << ':' << ec.value(); - return os; -} - -inline bool operator==(const error_code & lhs, const error_condition & rhs) { - return lhs.category().equivalent(lhs.value(), rhs) || - rhs.category().equivalent(lhs, rhs.value()); -} - -inline bool operator!=(const error_code & lhs, const error_condition & rhs) { - return !operator==(lhs, rhs); -} - -inline bool operator==(const error_condition & lhs, const error_code & rhs) { - return operator==(rhs, lhs); -} - -inline bool operator!=(const error_condition & lhs, const error_code & rhs) { - return !operator==(lhs, rhs); -} - -class system_error : public std::runtime_error { -public: - MaximInterface_EXPORT system_error(const error_code & ec); - - MaximInterface_EXPORT system_error(const error_code & ec, - const std::string & what_arg); - - MaximInterface_EXPORT system_error(const error_code & ec, - const char * what_arg); - - MaximInterface_EXPORT system_error(int ev, const error_category & ecat); - - MaximInterface_EXPORT system_error(int ev, const error_category & ecat, - const std::string & what_arg); - - MaximInterface_EXPORT system_error(int ev, const error_category & ecat, - const char * what_arg); - - const error_code & code() const { return code_; } - -private: - error_code code_; -}; - -} // namespace MaximInterface - -#endif
--- a/Utilities/type_traits.hpp Mon Mar 04 08:10:00 2019 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -/******************************************************************************* -* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included -* in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES -* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -* OTHER DEALINGS IN THE SOFTWARE. -* -* Except as contained in this notice, the name of Maxim Integrated -* Products, Inc. shall not be used except as stated in the Maxim Integrated -* Products, Inc. Branding Policy. -* -* The mere transfer of this software does not imply any licenses -* of trade secrets, proprietary technology, copyrights, patents, -* trademarks, maskwork rights, or any other form of intellectual -* property whatsoever. Maxim Integrated Products, Inc. retains all -* ownership rights. -*******************************************************************************/ - -#ifndef MaximInterface_type_traits -#define MaximInterface_type_traits - -namespace MaximInterface { - -template <typename T, T v> struct integral_constant { - static const T value = v; - typedef T value_type; - typedef integral_constant<T, v> type; - operator value_type() const { return value; } - value_type operator()() const { return value; } -}; - -typedef integral_constant<bool, true> true_type; -typedef integral_constant<bool, false> false_type; - -template <typename T, typename U> struct is_same : false_type {}; -template <typename T> struct is_same<T, T> : true_type {}; - -template <bool B, typename T, typename F> struct conditional { - typedef T type; -}; -template <typename T, typename F> struct conditional<false, T, F> { - typedef F type; -}; - -template <bool B, typename T = void> struct enable_if {}; -template <typename T> struct enable_if<true, T> { typedef T type; }; - -namespace detail { - -template <typename T> struct alignment_of_helper { - char a; - T b; -}; - -} // namespace detail - -template <typename T> -struct alignment_of - : integral_constant<size_t, - sizeof(detail::alignment_of_helper<T>) - sizeof(T)> {}; - -template <typename T> struct remove_const { typedef T type; }; -template <typename T> struct remove_const<const T> { typedef T type; }; - -template <typename T> struct remove_volatile { typedef T type; }; -template <typename T> struct remove_volatile<volatile T> { typedef T type; }; - -template <typename T> struct remove_cv { - typedef typename remove_volatile<typename remove_const<T>::type>::type type; -}; - -} // namespace MaximInterface - -#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed_lib.json Mon Jul 22 11:44:07 2019 -0500 @@ -0,0 +1,4 @@ +{ + "name": "MaximInterface", + "macros": ["__STDC_LIMIT_MACROS"] +} \ No newline at end of file