#pragma once #include #include #include #include "secsgem/hsms/types.hpp" namespace secsgem::hsms { // The fixed 10-byte HSMS message header (SEMI E37). The interpretation of // byte2/byte3 depends on `stype`: for data messages byte2 = (W<<7)|stream and // byte3 = function; for control messages they carry status / reason codes. struct Header { uint16_t session_id = kControlSessionId; uint8_t byte2 = 0; uint8_t byte3 = 0; uint8_t ptype = kPTypeSecsII; SType stype = SType::Data; uint32_t system_bytes = 0; // Data-message field views. bool w_bit() const { return (byte2 & 0x80) != 0; } uint8_t stream() const { return byte2 & 0x7F; } uint8_t function() const { return byte3; } static Header data_message(uint16_t session_id, uint8_t stream, uint8_t function, bool reply_expected, uint32_t system_bytes) { Header h; h.session_id = session_id; h.byte2 = static_cast((reply_expected ? 0x80 : 0x00) | (stream & 0x7F)); h.byte3 = function; h.ptype = kPTypeSecsII; h.stype = SType::Data; h.system_bytes = system_bytes; return h; } static Header control(SType stype, uint32_t system_bytes, uint16_t session_id = kControlSessionId, uint8_t byte2 = 0, uint8_t byte3 = 0) { Header h; h.session_id = session_id; h.byte2 = byte2; h.byte3 = byte3; h.ptype = kPTypeSecsII; h.stype = stype; h.system_bytes = system_bytes; return h; } std::array encode() const; static Header decode(const uint8_t* data); // reads exactly 10 bytes std::string describe() const; bool operator==(const Header&) const = default; }; } // namespace secsgem::hsms