Device interface library for multiple platforms including Mbed.

Dependents:   DeepCover Embedded Security in IoT MaximInterface MAXREFDES155#

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DS2465.hpp Source File

DS2465.hpp

00001 /*******************************************************************************
00002 * Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
00003 *
00004 * Permission is hereby granted, free of charge, to any person obtaining a
00005 * copy of this software and associated documentation files (the "Software"),
00006 * to deal in the Software without restriction, including without limitation
00007 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008 * and/or sell copies of the Software, and to permit persons to whom the
00009 * Software is furnished to do so, subject to the following conditions:
00010 *
00011 * The above copyright notice and this permission notice shall be included
00012 * in all copies or substantial portions of the Software.
00013 *
00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00015 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00017 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
00018 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00019 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00020 * OTHER DEALINGS IN THE SOFTWARE.
00021 *
00022 * Except as contained in this notice, the name of Maxim Integrated
00023 * Products, Inc. shall not be used except as stated in the Maxim Integrated
00024 * Products, Inc. Branding Policy.
00025 *
00026 * The mere transfer of this software does not imply any licenses
00027 * of trade secrets, proprietary technology, copyrights, patents,
00028 * trademarks, maskwork rights, or any other form of intellectual
00029 * property whatsoever. Maxim Integrated Products, Inc. retains all
00030 * ownership rights.
00031 *******************************************************************************/
00032 
00033 #ifndef MaximInterfaceDevices_DS2465_hpp
00034 #define MaximInterfaceDevices_DS2465_hpp
00035 
00036 #include <MaximInterfaceCore/array_span.hpp>
00037 #include <MaximInterfaceCore/I2CMaster.hpp>
00038 #include <MaximInterfaceCore/OneWireMaster.hpp>
00039 #include <MaximInterfaceCore/Sleep.hpp>
00040 #include "Config.hpp"
00041 
00042 namespace MaximInterfaceDevices {
00043 
00044 /// @brief Interface to the DS2465 1-Wire master and SHA-256 coprocessor.
00045 /// @details
00046 /// Const member functions should not change the settings of the DS2465 or
00047 /// affect the state of the 1-Wire bus. Read pointer, scratchpad, MAC output
00048 /// register, and command register on the DS2465 are considered mutable.
00049 class DS2465 : public Core::OneWireMaster {
00050 public:
00051   enum ErrorValue { HardwareError = 1, ArgumentOutOfRangeError };
00052 
00053   /// @brief 1-Wire port adjustment parameters.
00054   /// @note See datasheet page 13.
00055   enum PortParameter {
00056     tRSTL_STD,
00057     tRSTL_OD,
00058     tMSP_STD,
00059     tMSP_OD,
00060     tW0L_STD,
00061     tW0L_OD,
00062     tREC0,
00063     RWPU,
00064     tW1L_OD
00065   };
00066 
00067   /// Page region to use for swapping.
00068   enum PageRegion { FullPage = 0x03, FirstHalf = 0x01, SecondHalf = 0x02 };
00069 
00070   /// Holds the contents of a device memory segment.
00071   typedef Core::array_span<uint_least8_t, 4> Segment;
00072 
00073   /// Holds the contents of a device memory page.
00074   typedef Core::array_span<uint_least8_t, 32> Page;
00075 
00076   /// Data for Compute Write MAC operation.
00077   typedef Core::array_span<uint_least8_t, 20> WriteMacData;
00078 
00079   /// Data for the Compute Auth. MAC and Compute Slave Secret operations.
00080   typedef Core::array_span<uint_least8_t, 76> AuthenticationData;
00081 
00082   static const int memoryPages = 2;
00083   static const int segmentsPerPage = Page::size / Segment::size;
00084 
00085   /// Represents a DS2465 configuration.
00086   class Config {
00087   public:
00088     /// Default construct with power-on config.
00089     explicit Config(uint_least8_t readByte = optionAPU)
00090         : readByte_(readByte & 0xF) {}
00091 
00092     /// @name 1WS
00093     /// @brief 1-Wire Speed
00094     /// @{
00095 
00096     /// Get 1WS bit.
00097     bool get1WS() const { return (readByte_ & option1WS) == option1WS; }
00098 
00099     /// Set 1WS bit.
00100     Config & set1WS(bool new1WS) {
00101       if (new1WS) {
00102         readByte_ |= option1WS;
00103       } else {
00104         readByte_ &= ~option1WS;
00105       }
00106       return *this;
00107     }
00108 
00109     /// @}
00110 
00111     /// @name SPU
00112     /// @brief Strong Pullup
00113     /// @{
00114 
00115     /// Get SPU bit.
00116     bool getSPU() const { return (readByte_ & optionSPU) == optionSPU; }
00117 
00118     /// Set SPU bit.
00119     Config & setSPU(bool newSPU) {
00120       if (newSPU) {
00121         readByte_ |= optionSPU;
00122       } else {
00123         readByte_ &= ~optionSPU;
00124       }
00125       return *this;
00126     }
00127 
00128     /// @}
00129 
00130     /// @name PDN
00131     /// @brief 1-Wire Power Down
00132     /// @{
00133 
00134     /// Get PDN bit.
00135     bool getPDN() const { return (readByte_ & optionPDN) == optionPDN; }
00136 
00137     /// Set PDN bit.
00138     Config & setPDN(bool newPDN) {
00139       if (newPDN) {
00140         readByte_ |= optionPDN;
00141       } else {
00142         readByte_ &= ~optionPDN;
00143       }
00144       return *this;
00145     }
00146 
00147     /// @}
00148 
00149     /// @name APU
00150     /// @brief Active Pullup
00151     /// @{
00152 
00153     /// Get APU bit.
00154     bool getAPU() const { return (readByte_ & optionAPU) == optionAPU; }
00155 
00156     /// Set APU bit.
00157     Config & setAPU(bool newAPU) {
00158       if (newAPU) {
00159         readByte_ |= optionAPU;
00160       } else {
00161         readByte_ &= ~optionAPU;
00162       }
00163       return *this;
00164     }
00165 
00166     /// @}
00167 
00168     /// Byte representation that is read from the DS2465.
00169     uint_least8_t readByte() const { return readByte_; }
00170 
00171   private:
00172     static const unsigned int option1WS = 0x8;
00173     static const unsigned int optionSPU = 0x4;
00174     static const unsigned int optionPDN = 0x2;
00175     static const unsigned int optionAPU = 0x1;
00176 
00177     uint_least8_t readByte_;
00178   };
00179 
00180   DS2465(Core::Sleep & sleep, Core::I2CMaster & master,
00181          uint_least8_t address = 0x30)
00182       : sleep(&sleep), master(&master), address_(address & 0xFE) {}
00183 
00184   void setSleep(Core::Sleep & sleep) { this->sleep = &sleep; }
00185 
00186   void setMaster(Core::I2CMaster & master) { this->master = &master; }
00187 
00188   uint_least8_t address() const { return address_; }
00189 
00190   void setAddress(uint_least8_t address) { address_ = address & 0xFE; }
00191 
00192   /// Initialize hardware for use.
00193   MaximInterfaceDevices_EXPORT Core::Result<void>
00194   initialize(Config config = Config());
00195 
00196   /// @brief Write a new configuration to the DS2465.
00197   /// @param[in] config New configuration to write.
00198   MaximInterfaceDevices_EXPORT Core::Result<void> writeConfig(Config config);
00199 
00200   /// @brief Write a new port configuration parameter to the DS2465.
00201   /// @param[in] param Parameter to adjust.
00202   /// @param[in] val
00203   /// New parameter value to set. Consult datasheet for value mappings.
00204   MaximInterfaceDevices_EXPORT Core::Result<void>
00205   writePortParameter(PortParameter param, int val);
00206 
00207   // 1-Wire Master Commands
00208 
00209   MaximInterfaceDevices_EXPORT virtual Core::Result<void> reset();
00210 
00211   MaximInterfaceDevices_EXPORT virtual Core::Result<bool>
00212   touchBitSetLevel(bool sendBit, Level afterLevel);
00213 
00214   MaximInterfaceDevices_EXPORT virtual Core::Result<uint_least8_t>
00215   readByteSetLevel(Level afterLevel);
00216 
00217   MaximInterfaceDevices_EXPORT virtual Core::Result<void>
00218   writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
00219 
00220   MaximInterfaceDevices_EXPORT virtual Core::Result<void>
00221   readBlock(Core::span<uint_least8_t> recvBuf);
00222 
00223   MaximInterfaceDevices_EXPORT virtual Core::Result<void>
00224   writeBlock(Core::span<const uint_least8_t> sendBuf);
00225 
00226   MaximInterfaceDevices_EXPORT virtual Core::Result<void>
00227   setSpeed(Speed newSpeed);
00228 
00229   /// @copydoc Core::OneWireMaster::setLevel
00230   /// @note
00231   /// The DS2465 only supports enabling strong pullup following a 1-Wire read or
00232   /// write operation.
00233   MaximInterfaceDevices_EXPORT virtual Core::Result<void>
00234   setLevel (Level newLevel);
00235 
00236   MaximInterfaceDevices_EXPORT virtual Core::Result<TripletData>
00237   triplet(bool sendBit);
00238 
00239   // DS2465 Coprocessor Commands
00240 
00241   /// @brief Read data from an EEPROM memory page.
00242   /// @param pageNum Page number to read from.
00243   /// @returns Data that was read.
00244   MaximInterfaceDevices_EXPORT Core::Result<Page::array>
00245   readPage(int pageNum) const;
00246 
00247   /// @brief Write data to an EEPROM memory page.
00248   /// @param pageNum Page number to copy to.
00249   /// @param data Data to write.
00250   MaximInterfaceDevices_EXPORT Core::Result<void>
00251   writePage(int pageNum, Page::const_span data);
00252 
00253   /// @brief Write data to an EEPROM memory segment.
00254   /// @param pageNum Page number to copy to.
00255   /// @param segmentNum Segment number to copy to.
00256   /// @param data Data to write.
00257   MaximInterfaceDevices_EXPORT Core::Result<void>
00258   writeSegment(int pageNum, int segmentNum, Segment::const_span data);
00259 
00260   /// Write data to the secret EEPROM memory page.
00261   MaximInterfaceDevices_EXPORT Core::Result<void>
00262   writeMasterSecret(Page::const_span masterSecret);
00263 
00264   /// @brief Compute Next Master Secret.
00265   /// @param data Combined data fields for computation.
00266   MaximInterfaceDevices_EXPORT Core::Result<void>
00267   computeNextMasterSecret(AuthenticationData::const_span data);
00268 
00269   /// @brief Compute Next Master Secret with page swapping.
00270   /// @param data Combined data fields for computation.
00271   /// @param pageNum Page number to swap in.
00272   /// @param region Region of the page to swap in.
00273   MaximInterfaceDevices_EXPORT Core::Result<void>
00274   computeNextMasterSecretWithSwap(AuthenticationData::const_span data,
00275                                   int pageNum, PageRegion region);
00276 
00277   /// @brief Compute Write MAC.
00278   /// @param data Combined data fields for computation.
00279   /// @returns Computed Write MAC.
00280   MaximInterfaceDevices_EXPORT Core::Result<Page::array>
00281   computeWriteMac(WriteMacData::const_span data) const;
00282 
00283   /// @brief Compute Write MAC.
00284   /// @param data Combined data fields for computation.
00285   MaximInterfaceDevices_EXPORT Core::Result<void>
00286   computeAndTransmitWriteMac(WriteMacData::const_span data);
00287 
00288   /// @brief Compute Write MAC with page swapping.
00289   /// @param data Combined data fields for computation.
00290   /// @param pageNum Page number to swap in.
00291   /// @param segmentNum Segment number to swap in.
00292   /// @returns Computed Write MAC.
00293   MaximInterfaceDevices_EXPORT Core::Result<Page::array>
00294   computeWriteMacWithSwap(WriteMacData::const_span data, int pageNum,
00295                           int segmentNum) const;
00296 
00297   /// @brief Compute Write MAC with page swapping.
00298   /// @param data Combined data fields for computation.
00299   /// @param pageNum Page number to swap in.
00300   /// @param segmentNum Segment number to swap in.
00301   MaximInterfaceDevices_EXPORT Core::Result<void>
00302   computeAndTransmitWriteMacWithSwap(WriteMacData::const_span data, int pageNum,
00303                                      int segmentNum);
00304 
00305   /// @brief Compute Slave Secret (S-Secret).
00306   /// @param data Combined data fields for computation.
00307   MaximInterfaceDevices_EXPORT Core::Result<void>
00308   computeSlaveSecret(AuthenticationData::const_span data);
00309 
00310   /// @brief Compute Slave Secret (S-Secret) with page swapping.
00311   /// @param data Combined data fields for computation.
00312   /// @param pageNum Page number to swap in.
00313   /// @param region Region of the page to swap in.
00314   MaximInterfaceDevices_EXPORT Core::Result<void>
00315   computeSlaveSecretWithSwap(AuthenticationData::const_span data, int pageNum,
00316                              PageRegion region);
00317 
00318   /// @brief Compute Authentication MAC.
00319   /// @param data Combined data fields for computation.
00320   /// @returns Computed Auth MAC.
00321   MaximInterfaceDevices_EXPORT Core::Result<Page::array>
00322   computeAuthMac(AuthenticationData::const_span data) const;
00323 
00324   /// @brief Compute Authentication MAC.
00325   /// @param data Combined data fields for computation.
00326   MaximInterfaceDevices_EXPORT Core::Result<void>
00327   computeAndTransmitAuthMac(AuthenticationData::const_span data);
00328 
00329   /// @brief Compute Authentication MAC with page swapping.
00330   /// @param data Combined data fields for computation.
00331   /// @param pageNum Page number to swap in.
00332   /// @param region Region of the page to swap in.
00333   /// @returns Computed Auth MAC.
00334   MaximInterfaceDevices_EXPORT Core::Result<Page::array>
00335   computeAuthMacWithSwap(AuthenticationData::const_span data, int pageNum,
00336                          PageRegion region) const;
00337 
00338   /// @brief Compute Authentication MAC with page swapping.
00339   /// @param data Combined data fields for computation.
00340   /// @param pageNum Page number to swap in.
00341   /// @param region Region of the page to swap in.
00342   MaximInterfaceDevices_EXPORT Core::Result<void>
00343   computeAndTransmitAuthMacWithSwap(AuthenticationData::const_span data,
00344                                     int pageNum, PageRegion region);
00345 
00346   MaximInterfaceDevices_EXPORT static const Core::error_category &
00347   errorCategory();
00348 
00349 private:
00350   const Core::Sleep * sleep;
00351   Core::I2CMaster * master;
00352   uint_least8_t address_;
00353   Config curConfig;
00354 
00355   /// @brief Performs a soft reset on the DS2465.
00356   /// @note This is not a 1-Wire Reset.
00357   Core::Result<void> resetDevice();
00358 
00359   /// @brief
00360   /// Polls the DS2465 status waiting for the 1-Wire Busy bit (1WB) to be cleared.
00361   /// @returns Status byte or TimeoutError if poll limit reached.
00362   Core::Result<uint_least8_t> pollBusy() const;
00363 
00364   /// @brief Ensure that the desired 1-Wire level is set in the configuration.
00365   /// @param level Desired 1-Wire level.
00366   Core::Result<void> configureLevel(Level level);
00367 
00368   /// @note Const since only for internal use.
00369   Core::Result<void> writeMemory(uint_least8_t addr,
00370                                  Core::span<const uint_least8_t> buf) const;
00371 
00372   /// @brief Read memory from the DS2465.
00373   /// @param addr Address to begin reading from.
00374   /// @param[out] buf Buffer to hold read data.
00375   Core::Result<void> readMemory(uint_least8_t addr,
00376                                 Core::span<uint_least8_t> buf) const;
00377 
00378   /// @brief Read memory from the DS2465 at the current pointer.
00379   /// @param[out] buf Buffer to hold read data.
00380   Core::Result<void> readMemory(Core::span<uint_least8_t> buf) const;
00381 
00382   /// Write the last computed MAC to the 1-Wire bus.
00383   Core::Result<void> writeMacBlock();
00384 
00385   Core::Result<void> doComputeWriteMac(WriteMacData::const_span data) const;
00386 
00387   Core::Result<void> doComputeWriteMacWithSwap(WriteMacData::const_span data,
00388                                                int pageNum,
00389                                                int segmentNum) const;
00390 
00391   Core::Result<void>
00392   doComputeAuthMac(AuthenticationData::const_span data) const;
00393 
00394   Core::Result<void>
00395   doComputeAuthMacWithSwap(AuthenticationData::const_span data, int pageNum,
00396                            PageRegion region) const;
00397 
00398   // Legacy implementations
00399   Core::Result<void> copyScratchpad(bool destSecret, int pageNum, bool notFull,
00400                                     int segmentNum);
00401 
00402   Core::Result<void> computeNextMasterSecret(bool swap, int pageNum,
00403                                              PageRegion region);
00404 
00405   Core::Result<void> computeWriteMac(bool regwrite, bool swap, int pageNum,
00406                                      int segmentNum) const;
00407 
00408   Core::Result<void> computeSlaveSecret(bool swap, int pageNum,
00409                                         PageRegion region);
00410 
00411   Core::Result<void> computeAuthMac(bool swap, int pageNum,
00412                                     PageRegion region) const;
00413 };
00414 
00415 } // namespace MaximInterfaceDevices
00416 namespace MaximInterfaceCore {
00417 
00418 template <>
00419 struct is_error_code_enum<MaximInterfaceDevices::DS2465::ErrorValue>
00420     : true_type {};
00421 
00422 } // namespace MaximInterfaceCore
00423 namespace MaximInterfaceDevices {
00424 
00425 inline Core::error_code make_error_code(DS2465::ErrorValue e) {
00426   return Core::error_code(e, DS2465::errorCategory());
00427 }
00428 
00429 } // namespace MaximInterfaceDevices
00430 
00431 #endif