Extended MaximInterface

Dependents:   mbed_DS28EC20_GPIO

Revision:
6:a8c83a2e6fa4
Parent:
0:f77ad7f72d04
Child:
7:471901a04573
--- a/Devices/DS28E15_22_25.hpp	Fri Jan 19 10:25:02 2018 -0600
+++ b/Devices/DS28E15_22_25.hpp	Wed Jan 23 13:11:04 2019 -0600
@@ -33,10 +33,11 @@
 #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.hpp>
+#include <MaximInterface/Utilities/array_span.hpp>
 #include <MaximInterface/Utilities/Export.h>
 #include <MaximInterface/Utilities/ManId.hpp>
 #include <MaximInterface/Utilities/Sha256.hpp>
@@ -50,146 +51,43 @@
   enum ErrorValue { CrcError = 1, OperationFailure };
 
   /// Holds the contents of a device memory segment.
-  typedef array<uint_least8_t, 4> Segment;
+  typedef array_span<uint_least8_t, 4> Segment;
 
   /// Holds the contents of a device memory page.
-  typedef array<uint_least8_t, 32> Page;
+  typedef array_span<uint_least8_t, 32> Page;
 
   /// Number of segments per page.
-  static const int segmentsPerPage = Page::csize / Segment::csize;
+  static const int segmentsPerPage = Page::size / Segment::size;
 
   /// Holds the contents of the device scratchpad.
-  typedef array<uint_least8_t, 32> Scratchpad;
+  typedef array_span<uint_least8_t, 32> Scratchpad;
 
-  /// Container for the device personality. 
+  /// Container for the device personality.
   struct Personality {
     uint_least8_t PB1;
     uint_least8_t PB2;
-    ManId manId;
-    
+    ManId::array manId;
+
     bool secretLocked() const { return PB2 & 0x01; }
   };
 
   /// Represents the status of a memory protection block.
-  class BlockProtection {
-  private:
-    static const unsigned int readProtectionMask = 0x80,
-                              writeProtectionMask = 0x40,
-                              eepromEmulationMask = 0x20,
-                              authProtectionMask = 0x10,
-                              blockNumMask = 0x0F;
-    uint_least8_t status;
-
-  public:
-    explicit BlockProtection(uint_least8_t status = 0x00) : status(status) {}
-    MaximInterface_EXPORT BlockProtection(bool readProtection,
-                                          bool writeProtection,
-                                          bool eepromEmulation,
-                                          bool authProtection,
-                                          int blockNum);
-
-    /// Get the byte representation used by the device.
-    uint_least8_t statusByte() const { return status; }
-    /// Set the byte representation used by the device.
-    void setStatusByte(uint_least8_t status) { this->status = status; }
-
-    /// 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 void setBlockNum(int blockNum);
-
-    /// 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 void setReadProtection(bool readProtection);
-
-    /// 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 void setWriteProtection(bool writeProtection);
-
-    /// 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 void setEepromEmulation(bool eepromEmulation);
-
-    /// 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 void setAuthProtection(bool authProtection);
-
-    /// Check if no protection options are enabled.
-    /// @returns True if no protection options are enabled.
-    MaximInterface_EXPORT bool noProtection() const;
-  };
+  class BlockProtection;
 
   /// Format data to hash for an Authenticated Write to a memory segment.
-  /// @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] oldData Existing data contained in the segment.
-  /// @param[in] romId 1-Wire ROM ID of the device.
-  /// @param[in] manId Manufacturer ID of the device.
-  MaximInterface_EXPORT static Sha256::WriteMacData
-  createSegmentWriteMacData(int pageNum, int segmentNum,
-                            const Segment & newData, const Segment & oldData,
-                            const RomId & romId, const ManId & manId);
+  class SegmentWriteMacData;
 
   /// Format data to hash for an Authenticated Write to a memory protection block.
-  /// @param[in] newProtection New protection status to write.
-  /// @param[in] oldProtection Existing protection status in device.
-  /// @param[in] romId 1-Wire ROM ID of the device.
-  /// @param[in] manId Manufacturer ID of the device.
-  MaximInterface_EXPORT static Sha256::WriteMacData
-  createProtectionWriteMacData(const BlockProtection & newProtection,
-                               const BlockProtection & oldProtection,
-                               const RomId & romId, const ManId & manId);
-
-  /// Format data to hash to compute the next secret from the existing secret.
-  /// @param[in] bindingPage Binding data from a device memory page.
-  /// @param bindingPageNum Number of the page where the binding data is from.
-  /// @param[in] partialSecret Partial secret data from the device scratchpad.
-  /// @param[in] romId 1-Wire ROM ID of the device.
-  /// @param[in] manId Manufacturer ID of the device.
-  MaximInterface_EXPORT static Sha256::SlaveSecretData
-  createSlaveSecretData(const Page & bindingPage, int bindingPageNum,
-                        const Scratchpad & partialSecret, const RomId & romId,
-                        const ManId & manId);
+  class ProtectionWriteMacData;
 
-  /// Format data to hash for device authentication.
-  /// @param[in] pageData Data from a device memory page.
-  /// @param pageNum Number of the page to use data from.
-  /// @param[in] challenge Random challenge to prevent replay attacks.
-  /// @param[in] romId 1-Wire ROM ID of the device.
-  /// @param[in] manId Manufacturer ID of the device.
-  MaximInterface_EXPORT static Sha256::AuthMacData
-  createAuthMacData(const Page & pageData, int pageNum,
-                    const Scratchpad & challenge, const RomId & romId,
-                    const ManId & manId);
+  /// Format data to hash for device authentication or computing the next secret
+  /// from the existing secret.
+  class AuthenticationData;
 
-  /// Format datat to hash for device authentication using anonymous mode.
-  /// @param[in] pageData Data from a device memory page.
-  /// @param pageNum Number of the page to use data from.
-  /// @param[in] challenge Random challenge to prevent replay attacks.
-  /// @param[in] manId Manufacturer ID of the device.
-  MaximInterface_EXPORT static Sha256::AuthMacData
-  createAnonAuthMacData(const Page & pageData, int pageNum,
-                        const Scratchpad & challenge, const ManId & manId);
-
-  void setSleep(const Sleep & sleep) { this->sleep = &sleep; }
+  void setSleep(Sleep & sleep) { this->sleep = &sleep; }
+  
   void setMaster(OneWireMaster & master) { this->master = &master; }
+  
   void setSelectRom(const SelectRom & selectRom) {
     this->selectRom = selectRom;
   }
@@ -202,12 +100,13 @@
   /// @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 & data) const;
+                                               Segment::span data) const;
 
   /// 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 & data) const;
+  MaximInterface_EXPORT error_code
+  continueReadSegment(Segment::span data) const;
 
   /// Write memory segment using the Write Memory command.
   /// @note 1-Wire ROM selection should have already occurred.
@@ -215,44 +114,44 @@
   /// @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,
-                                                const Segment & data);
+                                                Segment::const_span data);
 
   /// Continue an in-progress Write Memory command.
   /// @param[in] data Data to write to the memory segment.
-  MaximInterface_EXPORT error_code continueWriteSegment(const Segment & data);
+  MaximInterface_EXPORT error_code
+  continueWriteSegment(Segment::const_span data);
 
   /// 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 & rdbuf) const;
+  MaximInterface_EXPORT error_code readPage(int pageNum,
+                                            Page::span rdbuf) const;
 
   /// Continue an in-progress readPageOperation.
   /// @param[out] rdbuf Buffer to read data from the page into.
-  MaximInterface_EXPORT error_code continueReadPage(Page & rdbuf) const;
+  MaximInterface_EXPORT error_code continueReadPage(Page::span rdbuf) const;
 
   /// 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 & mac) const;
+  MaximInterface_EXPORT error_code
+  computeReadPageMac(int pageNum, bool anon, Sha256::Hash::span mac) const;
 
   /// Update the status of a memory protection block using the
   /// Write Page Protection command.
-  /// @param[in] Desired protection status for the block.
-  ///            It is not possible to disable existing protections.
-  /// @param continuing True to continue a previous Write Page Protection command.
-  ///                   False to begin a new command.
+  /// @param protection Desired protection status for the block.
+  ///                   It is not possible to disable existing protections.
   MaximInterface_EXPORT error_code
-  writeBlockProtection(const BlockProtection & protection);
+  writeBlockProtection(BlockProtection protection);
 
   /// Update the status of a memory protection block using the
   /// Authenticated Write Page Protection command.
-  /// @param[in] newProtection New protection status to write.
+  /// @param newProtection New protection status to write.
   /// @param[in] mac Write MAC computed for this operation.
   MaximInterface_EXPORT error_code writeAuthBlockProtection(
-      const BlockProtection & newProtection, const Sha256::Hash & mac);
+      BlockProtection newProtection, Sha256::Hash::const_span mac);
 
   /// Perform Load and Lock Secret command on the device.
   /// @note The secret should already be stored in the scratchpad on the device.
@@ -274,27 +173,28 @@
 protected:
   enum Variant { DS28E15, DS28E22, DS28E25 };
 
-  DS28E15_22_25(const Sleep & sleep, OneWireMaster & master,
+  DS28E15_22_25(Sleep & sleep, OneWireMaster & master,
                 const SelectRom & selectRom)
       : selectRom(selectRom), master(&master), sleep(&sleep) {}
+      
+  ~DS28E15_22_25() {}
 
-  error_code doWriteScratchpad(const Scratchpad & data, Variant variant);
+  error_code doWriteScratchpad(Scratchpad::const_span data, Variant variant);
 
-  error_code doReadScratchpad(Scratchpad & data, Variant variant) const;
+  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,
-                                const Segment & newData,
-                                const Sha256::Hash & mac, Variant variant);
+                                Segment::const_span newData,
+                                Sha256::Hash::const_span mac, Variant variant);
 
-  error_code doContinueWriteAuthSegment(const Segment & newData,
-                                        const Sha256::Hash & mac,
+  error_code doContinueWriteAuthSegment(Segment::const_span newData,
+                                        Sha256::Hash::const_span mac,
                                         Variant variant);
 
-  error_code doReadAllBlockProtection(BlockProtection * protection,
-                                      size_t protectionLen,
+  error_code doReadAllBlockProtection(span<BlockProtection> protection,
                                       Variant variant) const;
 
   error_code doLoadSecret(bool lock, bool lowPower);
@@ -315,8 +215,8 @@
     AuthWriteBlockProtection = 0xCC,
   };
 
-  error_code doWriteAuthSegment(const Segment & newData,
-                                const Sha256::Hash & mac, Variant variant,
+  error_code doWriteAuthSegment(Segment::const_span newData,
+                                Sha256::Hash::const_span mac, Variant variant,
                                 bool continuing);
 
   error_code writeCommandWithCrc(
@@ -325,23 +225,13 @@
 
   SelectRom selectRom;
   OneWireMaster * master;
-  const Sleep * sleep;
+  Sleep * sleep;
 };
 
 inline error_code make_error_code(DS28E15_22_25::ErrorValue e) {
   return error_code(e, DS28E15_22_25::errorCategory());
 }
 
-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);
-}
-
 /// Interface to the DS28EL15 (low power) authenticator.
 class DS28EL15 : public DS28E15_22_25 {
 public:
@@ -349,17 +239,16 @@
   static const int memoryPages = 2;
   static const int protectionBlocks = 4;
 
-  DS28EL15(const Sleep & sleep, OneWireMaster & master,
-           const SelectRom & selectRom)
+  DS28EL15(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
       : DS28E15_22_25(sleep, master, selectRom) {}
 
   /// Perform Write Scratchpad operation on the device.
   /// @param[in] data Data to write to the scratchpad.
-  MaximInterface_EXPORT error_code writeScratchpad(const Scratchpad & data);
+  MaximInterface_EXPORT error_code writeScratchpad(Scratchpad::const_span data);
 
   /// 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 & data) const;
+  MaximInterface_EXPORT error_code readScratchpad(Scratchpad::span data) const;
 
   /// Read the status of a memory protection block using the Read Status command.
   /// @param blockNum Block number to to read status of.
@@ -372,27 +261,26 @@
   /// @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,
-                                                    const Segment & newData,
-                                                    const Sha256::Hash & mac);
+  MaximInterface_EXPORT error_code
+  writeAuthSegment(int pageNum, int segmentNum, Segment::const_span newData,
+                   Sha256::Hash::const_span mac);
 
   /// 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(const Segment & newData, const Sha256::Hash & mac);
+  MaximInterface_EXPORT error_code continueWriteAuthSegment(
+      Segment::const_span newData, Sha256::Hash::const_span mac);
 
   /// 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(
-      array<BlockProtection, protectionBlocks> & protection) const;
+      span<BlockProtection, protectionBlocks> protection) const;
 };
 
 /// Interface to the DS28E15 authenticator.
 class DS28E15 : public DS28EL15 {
 public:
-  DS28E15(const Sleep & sleep, OneWireMaster & master,
-          const SelectRom & selectRom)
+  DS28E15(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
       : DS28EL15(sleep, master, selectRom) {}
 
   /// Perform Load and Lock Secret command on the device.
@@ -413,17 +301,16 @@
   static const int memoryPages = 8;
   static const int protectionBlocks = 4;
 
-  DS28EL22(const Sleep & sleep, OneWireMaster & master,
-           const SelectRom & selectRom)
+  DS28EL22(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
       : DS28E15_22_25(sleep, master, selectRom) {}
 
   /// Perform Write Scratchpad operation on the device.
   /// @param[in] data Data to write to the scratchpad.
-  MaximInterface_EXPORT error_code writeScratchpad(const Scratchpad & data);
+  MaximInterface_EXPORT error_code writeScratchpad(Scratchpad::const_span data);
 
   /// 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 & data) const;
+  MaximInterface_EXPORT error_code readScratchpad(Scratchpad::span data) const;
 
   /// Read the status of a memory protection block using the Read Status command.
   /// @param blockNum Block number to to read status of.
@@ -436,27 +323,26 @@
   /// @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,
-                                                    const Segment & newData,
-                                                    const Sha256::Hash & mac);
+  MaximInterface_EXPORT error_code
+  writeAuthSegment(int pageNum, int segmentNum, Segment::const_span newData,
+                   Sha256::Hash::const_span mac);
 
   /// 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(const Segment & newData, const Sha256::Hash & mac);
+  MaximInterface_EXPORT error_code continueWriteAuthSegment(
+      Segment::const_span newData, Sha256::Hash::const_span mac);
 
   /// 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(
-      array<BlockProtection, protectionBlocks> & protection) const;
+      span<BlockProtection, protectionBlocks> protection) const;
 };
 
 /// Interface to the DS28E22 authenticator.
 class DS28E22 : public DS28EL22 {
 public:
-  DS28E22(const Sleep & sleep, OneWireMaster & master,
-          const SelectRom & selectRom)
+  DS28E22(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
       : DS28EL22(sleep, master, selectRom) {}
 
   /// Perform Load and Lock Secret command on the device.
@@ -477,17 +363,16 @@
   static const int memoryPages = 16;
   static const int protectionBlocks = 8;
 
-  DS28EL25(const Sleep & sleep, OneWireMaster & master,
-           const SelectRom & selectRom)
+  DS28EL25(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
       : DS28E15_22_25(sleep, master, selectRom) {}
 
   /// Perform Write Scratchpad operation on the device.
   /// @param[in] data Data to write to the scratchpad.
-  MaximInterface_EXPORT error_code writeScratchpad(const Scratchpad & data);
+  MaximInterface_EXPORT error_code writeScratchpad(Scratchpad::const_span data);
 
   /// 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 & data) const;
+  MaximInterface_EXPORT error_code readScratchpad(Scratchpad::span data) const;
 
   /// Read the status of a memory protection block using the Read Status command.
   /// @param blockNum Block number to to read status of.
@@ -500,27 +385,26 @@
   /// @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,
-                                                    const Segment & newData,
-                                                    const Sha256::Hash & mac);
+  MaximInterface_EXPORT error_code
+  writeAuthSegment(int pageNum, int segmentNum, Segment::const_span newData,
+                   Sha256::Hash::const_span mac);
 
   /// 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(const Segment & newData, const Sha256::Hash & mac);
+  MaximInterface_EXPORT error_code continueWriteAuthSegment(
+      Segment::const_span newData, Sha256::Hash::const_span mac);
 
   /// 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(
-      array<BlockProtection, protectionBlocks> & protection) const;
+      span<BlockProtection, protectionBlocks> protection) const;
 };
 
 /// Interface to the DS28E25 authenticator.
 class DS28E25 : public DS28EL25 {
 public:
-  DS28E25(const Sleep & sleep, OneWireMaster & master,
-          const SelectRom & selectRom)
+  DS28E25(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
       : DS28EL25(sleep, master, selectRom) {}
 
   /// Perform Load and Lock Secret command on the device.
@@ -534,6 +418,357 @@
   MaximInterface_EXPORT error_code computeSecret(int pageNum, bool lock);
 };
 
+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);
+
+  /// 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);
+
+  /// 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);
+
+  /// 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);
+
+  /// 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);
+
+  /// 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);
+}
+
+class DS28E15_22_25::SegmentWriteMacData {
+public:
+  SegmentWriteMacData() : result_() {}
+
+  /// Formatted data result.
+  Sha256::WriteMacData::const_span result() const { return result_; }
+
+  /// @{
+  /// 1-Wire ROM ID of the device.
+  RomId::span romId() {
+    return make_span(result_).subspan<romIdIdx, RomId::size>();
+  }
+  
+  RomId::const_span romId() const {
+    return const_cast<SegmentWriteMacData &>(*this).romId();
+  }
+  
+  SegmentWriteMacData & setRomId(RomId::const_span romId) {
+    copy(romId, this->romId());
+    return *this;
+  }
+  /// @}
+
+  /// @{
+  /// Manufacturer ID of the device.
+  ManId::span manId() {
+    return make_span(result_).subspan<manIdIdx, ManId::size>();
+  }
+  
+  ManId::const_span manId() const {
+    return const_cast<SegmentWriteMacData &>(*this).manId();
+  }
+  
+  SegmentWriteMacData & setManId(ManId::const_span manId) {
+    copy(manId, this->manId());
+    return *this;
+  }
+  /// @}
+
+  /// @{
+  /// Page number for write operation.
+  int pageNum() const { return result_[pageNumIdx]; }
+  
+  SegmentWriteMacData & setPageNum(int pageNum) {
+    result_[pageNumIdx] = pageNum;
+    return *this;
+  }
+  /// @}
+
+  /// @{
+  /// Segment number within page for write operation.
+  int segmentNum() const { return result_[segmentNumIdx]; }
+  
+  SegmentWriteMacData & setSegmentNum(int segmentNum) {
+    result_[segmentNumIdx] = segmentNum;
+    return *this;
+  }
+  /// @}
+
+  /// @{
+  /// Existing data contained in the segment.
+  Segment::span oldData() {
+    return make_span(result_).subspan<oldDataIdx, Segment::size>();
+  }
+  
+  Segment::const_span oldData() const {
+    return const_cast<SegmentWriteMacData &>(*this).oldData();
+  }
+  
+  SegmentWriteMacData & setOldData(Segment::const_span oldData) {
+    copy(oldData, this->oldData());
+    return *this;
+  }
+  /// @}
+
+  /// @{
+  /// New data to write to the segment.
+  Segment::span newData() {
+    return make_span(result_).subspan<newDataIdx, Segment::size>();
+  }
+  
+  Segment::const_span newData() const {
+    return const_cast<SegmentWriteMacData &>(*this).newData();
+  }
+  
+  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_;
+};
+
+class DS28E15_22_25::ProtectionWriteMacData {
+public:
+  MaximInterface_EXPORT ProtectionWriteMacData();
+
+  /// Formatted data result.
+  Sha256::WriteMacData::const_span result() const { return result_; }
+
+  /// @{
+  /// 1-Wire ROM ID of the device.
+  RomId::span romId() {
+    return make_span(result_).subspan<romIdIdx, RomId::size>();
+  }
+  
+  RomId::const_span romId() const {
+    return const_cast<ProtectionWriteMacData &>(*this).romId();
+  }
+  
+  ProtectionWriteMacData & setRomId(RomId::const_span romId) {
+    copy(romId, this->romId());
+    return *this;
+  }
+  /// @}
+
+  /// @{
+  /// Manufacturer ID of the device.
+  ManId::span manId() {
+    return make_span(result_).subspan<manIdIdx, ManId::size>();
+  }
+  
+  ManId::const_span manId() const {
+    return const_cast<ProtectionWriteMacData &>(*this).manId();
+  }
+  
+  ProtectionWriteMacData & setManId(ManId::const_span manId) {
+    copy(manId, this->manId());
+    return *this;
+  }
+  /// @}
+
+  /// @{
+  /// Existing protection status in device.
+  BlockProtection oldProtection() const { return oldProtection_; }
+  
+  MaximInterface_EXPORT ProtectionWriteMacData &
+  setOldProtection(BlockProtection oldProtection);
+  /// @}
+
+  /// @{
+  /// New protection status to write.
+  BlockProtection newProtection() const { return newProtection_; }
+  
+  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_;
+};
+
+class DS28E15_22_25::AuthenticationData {
+public:
+  AuthenticationData() : result_() {}
+
+  /// Formatted data result.
+  Sha256::AuthenticationData::const_span result() const { return result_; }
+
+  /// @{
+  /// Data from a device memory page.
+  Page::span page() {
+    return make_span(result_).subspan<pageIdx, Page::size>();
+  }
+  
+  Page::const_span page() const {
+    return const_cast<AuthenticationData &>(*this).page();
+  }
+  
+  AuthenticationData & setPage(Page::const_span page) {
+    copy(page, this->page());
+    return *this;
+  }
+  /// @}
+
+  /// @{
+  /// Data from device scratchpad used as a random challenge in device
+  /// authentication and a partial secret in secret computation.
+  Scratchpad::span scratchpad() {
+    return make_span(result_).subspan<scratchpadIdx, Scratchpad::size>();
+  }
+  
+  Scratchpad::const_span scratchpad() const {
+    return const_cast<AuthenticationData &>(*this).scratchpad();
+  }
+  
+  AuthenticationData & setScratchpad(Scratchpad::const_span scratchpad) {
+    copy(scratchpad, this->scratchpad());
+    return *this;
+  }
+  /// @}
+
+  /// @{
+  /// 1-Wire ROM ID of the device.
+  RomId::span romId() {
+    return make_span(result_).subspan<romIdIdx, RomId::size>();
+  }
+  
+  RomId::const_span romId() const {
+    return const_cast<AuthenticationData &>(*this).romId();
+  }
+  
+  AuthenticationData & setRomId(RomId::const_span romId) {
+    copy(romId, this->romId());
+    return *this;
+  }
+  
+  MaximInterface_EXPORT AuthenticationData & setAnonymousRomId();
+  /// @}
+
+  /// @{
+  /// Manufacturer ID of the device.
+  ManId::span manId() {
+    return make_span(result_).subspan<manIdIdx, ManId::size>();
+  }
+  
+  ManId::const_span manId() const {
+    return const_cast<AuthenticationData &>(*this).manId();
+  }
+  
+  AuthenticationData & setManId(ManId::const_span manId) {
+    copy(manId, this->manId());
+    return *this;
+  }
+  /// @}
+
+  /// @{
+  /// Number of the page to use data from.
+  int pageNum() const { return result_[pageNumIdx]; }
+  
+  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