diff --git a/sbp.cabal b/sbp.cabal
--- a/sbp.cabal
+++ b/sbp.cabal
@@ -1,6 +1,6 @@
 cabal-version: >=1.22
 name: sbp
-version: 2.4.0
+version: 2.4.6
 license: LGPL-3
 copyright: Copyright (C) 2015-2018 Swift Navigation, Inc.
 maintainer: Swift Navigation <dev@swiftnav.com>
@@ -34,6 +34,7 @@
         SwiftNav.SBP.Flash
         SwiftNav.SBP.Gnss
         SwiftNav.SBP.Imu
+        SwiftNav.SBP.Linux
         SwiftNav.SBP.Logging
         SwiftNav.SBP.Mag
         SwiftNav.SBP.Navigation
diff --git a/src/SwiftNav/SBP.hs b/src/SwiftNav/SBP.hs
--- a/src/SwiftNav/SBP.hs
+++ b/src/SwiftNav/SBP.hs
@@ -21,6 +21,7 @@
 import SwiftNav.SBP.Flash as Exports
 import SwiftNav.SBP.Gnss as Exports
 import SwiftNav.SBP.Imu as Exports
+import SwiftNav.SBP.Linux as Exports
 import SwiftNav.SBP.Logging as Exports
 import SwiftNav.SBP.Mag as Exports
 import SwiftNav.SBP.Navigation as Exports
diff --git a/src/SwiftNav/SBP/Imu.hs b/src/SwiftNav/SBP/Imu.hs
--- a/src/SwiftNav/SBP/Imu.hs
+++ b/src/SwiftNav/SBP/Imu.hs
@@ -42,7 +42,9 @@
 --
 -- Raw data from the Inertial Measurement Unit, containing accelerometer and
 -- gyroscope readings. The sense of the measurements are to be aligned with
--- the indications on the device itself.
+-- the indications on the device itself. Measurement units, which are specific
+-- to the device hardware and settings, are communicated via the MSG_IMU_AUX
+-- message.
 data MsgImuRaw = MsgImuRaw
   { _msgImuRaw_tow :: !Word32
     -- ^ Milliseconds since start of GPS week. If the high bit is set, the time
diff --git a/src/SwiftNav/SBP/Linux.hs b/src/SwiftNav/SBP/Linux.hs
new file mode 100644
--- /dev/null
+++ b/src/SwiftNav/SBP/Linux.hs
@@ -0,0 +1,367 @@
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+{-# LANGUAGE NoImplicitPrelude           #-}
+{-# LANGUAGE TemplateHaskell             #-}
+{-# LANGUAGE RecordWildCards             #-}
+
+-- |
+-- Module:      SwiftNav.SBP.Linux
+-- Copyright:   Copyright (C) 2015-2018 Swift Navigation, Inc.
+-- License:     LGPL-3
+-- Maintainer:  Swift Navigation <dev@swiftnav.com>
+-- Stability:   experimental
+-- Portability: portable
+--
+-- Linux state monitoring.
+
+module SwiftNav.SBP.Linux
+  ( module SwiftNav.SBP.Linux
+  ) where
+
+import BasicPrelude
+import Control.Lens
+import Control.Monad.Loops
+import Data.Binary
+import Data.Binary.Get
+import Data.Binary.IEEE754
+import Data.Binary.Put
+import Data.ByteString.Lazy    hiding (ByteString)
+import Data.Int
+import Data.Word
+import SwiftNav.SBP.TH
+import SwiftNav.SBP.Types
+
+{-# ANN module ("HLint: ignore Use camelCase"::String) #-}
+{-# ANN module ("HLint: ignore Redundant do"::String) #-}
+{-# ANN module ("HLint: ignore Use newtype instead of data"::String) #-}
+
+
+msgLinuxCpuState :: Word16
+msgLinuxCpuState = 0x7F00
+
+-- | SBP class for message MSG_LINUX_CPU_STATE (0x7F00).
+--
+-- This message indicates the process state of the top 10 heaviest consumers of
+-- CPU on the system.
+data MsgLinuxCpuState = MsgLinuxCpuState
+  { _msgLinuxCpuState_index :: !Word8
+    -- ^ sequence of this status message, values from 0-9
+  , _msgLinuxCpuState_pid   :: !Word16
+    -- ^ the PID of the process
+  , _msgLinuxCpuState_pcpu  :: !Word8
+    -- ^ percent of cpu used, expressed as a fraction of 256
+  , _msgLinuxCpuState_tname :: !Text
+    -- ^ fixed length string representing the thread name
+  , _msgLinuxCpuState_cmdline :: !Text
+    -- ^ the command line (as much as it fits in the remaining packet)
+  } deriving ( Show, Read, Eq )
+
+instance Binary MsgLinuxCpuState where
+  get = do
+    _msgLinuxCpuState_index <- getWord8
+    _msgLinuxCpuState_pid <- getWord16le
+    _msgLinuxCpuState_pcpu <- getWord8
+    _msgLinuxCpuState_tname <- decodeUtf8 <$> getByteString 15
+    _msgLinuxCpuState_cmdline <- decodeUtf8 . toStrict <$> getRemainingLazyByteString
+    pure MsgLinuxCpuState {..}
+
+  put MsgLinuxCpuState {..} = do
+    putWord8 _msgLinuxCpuState_index
+    putWord16le _msgLinuxCpuState_pid
+    putWord8 _msgLinuxCpuState_pcpu
+    putByteString $ encodeUtf8 _msgLinuxCpuState_tname
+    putByteString $ encodeUtf8 _msgLinuxCpuState_cmdline
+
+$(makeSBP 'msgLinuxCpuState ''MsgLinuxCpuState)
+$(makeJSON "_msgLinuxCpuState_" ''MsgLinuxCpuState)
+$(makeLenses ''MsgLinuxCpuState)
+
+msgLinuxMemState :: Word16
+msgLinuxMemState = 0x7F01
+
+-- | SBP class for message MSG_LINUX_MEM_STATE (0x7F01).
+--
+-- This message indicates the process state of the top 10 heaviest consumers of
+-- memory on the system.
+data MsgLinuxMemState = MsgLinuxMemState
+  { _msgLinuxMemState_index :: !Word8
+    -- ^ sequence of this status message, values from 0-9
+  , _msgLinuxMemState_pid   :: !Word16
+    -- ^ the PID of the process
+  , _msgLinuxMemState_pmem  :: !Word8
+    -- ^ percent of memory used, expressed as a fraction of 256
+  , _msgLinuxMemState_tname :: !Text
+    -- ^ fixed length string representing the thread name
+  , _msgLinuxMemState_cmdline :: !Text
+    -- ^ the command line (as much as it fits in the remaining packet)
+  } deriving ( Show, Read, Eq )
+
+instance Binary MsgLinuxMemState where
+  get = do
+    _msgLinuxMemState_index <- getWord8
+    _msgLinuxMemState_pid <- getWord16le
+    _msgLinuxMemState_pmem <- getWord8
+    _msgLinuxMemState_tname <- decodeUtf8 <$> getByteString 15
+    _msgLinuxMemState_cmdline <- decodeUtf8 . toStrict <$> getRemainingLazyByteString
+    pure MsgLinuxMemState {..}
+
+  put MsgLinuxMemState {..} = do
+    putWord8 _msgLinuxMemState_index
+    putWord16le _msgLinuxMemState_pid
+    putWord8 _msgLinuxMemState_pmem
+    putByteString $ encodeUtf8 _msgLinuxMemState_tname
+    putByteString $ encodeUtf8 _msgLinuxMemState_cmdline
+
+$(makeSBP 'msgLinuxMemState ''MsgLinuxMemState)
+$(makeJSON "_msgLinuxMemState_" ''MsgLinuxMemState)
+$(makeLenses ''MsgLinuxMemState)
+
+msgLinuxSysState :: Word16
+msgLinuxSysState = 0x7F02
+
+-- | SBP class for message MSG_LINUX_SYS_STATE (0x7F02).
+--
+-- This presents a summary of CPU and memory utilization.
+data MsgLinuxSysState = MsgLinuxSysState
+  { _msgLinuxSysState_mem_total    :: !Word16
+    -- ^ total system memory
+  , _msgLinuxSysState_pcpu         :: !Word8
+    -- ^ percent of total cpu currently utilized
+  , _msgLinuxSysState_pmem         :: !Word8
+    -- ^ percent of total memory currently utilized
+  , _msgLinuxSysState_procs_starting :: !Word16
+    -- ^ number of processes that started during collection phase
+  , _msgLinuxSysState_procs_stopping :: !Word16
+    -- ^ number of processes that stopped during collection phase
+  , _msgLinuxSysState_pid_count    :: !Word16
+    -- ^ the count of processes on the system
+  } deriving ( Show, Read, Eq )
+
+instance Binary MsgLinuxSysState where
+  get = do
+    _msgLinuxSysState_mem_total <- getWord16le
+    _msgLinuxSysState_pcpu <- getWord8
+    _msgLinuxSysState_pmem <- getWord8
+    _msgLinuxSysState_procs_starting <- getWord16le
+    _msgLinuxSysState_procs_stopping <- getWord16le
+    _msgLinuxSysState_pid_count <- getWord16le
+    pure MsgLinuxSysState {..}
+
+  put MsgLinuxSysState {..} = do
+    putWord16le _msgLinuxSysState_mem_total
+    putWord8 _msgLinuxSysState_pcpu
+    putWord8 _msgLinuxSysState_pmem
+    putWord16le _msgLinuxSysState_procs_starting
+    putWord16le _msgLinuxSysState_procs_stopping
+    putWord16le _msgLinuxSysState_pid_count
+
+$(makeSBP 'msgLinuxSysState ''MsgLinuxSysState)
+$(makeJSON "_msgLinuxSysState_" ''MsgLinuxSysState)
+$(makeLenses ''MsgLinuxSysState)
+
+msgLinuxProcessSocketCounts :: Word16
+msgLinuxProcessSocketCounts = 0x7F03
+
+-- | SBP class for message MSG_LINUX_PROCESS_SOCKET_COUNTS (0x7F03).
+--
+-- Top 10 list of processes with high socket counts.
+data MsgLinuxProcessSocketCounts = MsgLinuxProcessSocketCounts
+  { _msgLinuxProcessSocketCounts_index       :: !Word8
+    -- ^ sequence of this status message, values from 0-9
+  , _msgLinuxProcessSocketCounts_pid         :: !Word16
+    -- ^ the PID of the process in question
+  , _msgLinuxProcessSocketCounts_socket_count :: !Word16
+    -- ^ the number of sockets the process is using
+  , _msgLinuxProcessSocketCounts_socket_types :: !Word16
+    -- ^ A bitfield indicating the socket types used:   0x1 (tcp), 0x2 (udp), 0x4
+    -- (unix stream), 0x8 (unix dgram), 0x10 (netlink),   and 0x8000 (unknown)
+  , _msgLinuxProcessSocketCounts_socket_states :: !Word16
+    -- ^ A bitfield indicating the socket states:   0x1 (established), 0x2 (syn-
+    -- sent), 0x4 (syn-recv), 0x8 (fin-wait-1),   0x10 (fin-wait-2), 0x20
+    -- (time-wait), 0x40 (closed), 0x80 (close-wait),   0x100 (last-ack), 0x200
+    -- (listen), 0x400 (closing), 0x800 (unconnected),   and 0x8000 (unknown)
+  , _msgLinuxProcessSocketCounts_cmdline     :: !Text
+    -- ^ the command line of the process in question
+  } deriving ( Show, Read, Eq )
+
+instance Binary MsgLinuxProcessSocketCounts where
+  get = do
+    _msgLinuxProcessSocketCounts_index <- getWord8
+    _msgLinuxProcessSocketCounts_pid <- getWord16le
+    _msgLinuxProcessSocketCounts_socket_count <- getWord16le
+    _msgLinuxProcessSocketCounts_socket_types <- getWord16le
+    _msgLinuxProcessSocketCounts_socket_states <- getWord16le
+    _msgLinuxProcessSocketCounts_cmdline <- decodeUtf8 . toStrict <$> getRemainingLazyByteString
+    pure MsgLinuxProcessSocketCounts {..}
+
+  put MsgLinuxProcessSocketCounts {..} = do
+    putWord8 _msgLinuxProcessSocketCounts_index
+    putWord16le _msgLinuxProcessSocketCounts_pid
+    putWord16le _msgLinuxProcessSocketCounts_socket_count
+    putWord16le _msgLinuxProcessSocketCounts_socket_types
+    putWord16le _msgLinuxProcessSocketCounts_socket_states
+    putByteString $ encodeUtf8 _msgLinuxProcessSocketCounts_cmdline
+
+$(makeSBP 'msgLinuxProcessSocketCounts ''MsgLinuxProcessSocketCounts)
+$(makeJSON "_msgLinuxProcessSocketCounts_" ''MsgLinuxProcessSocketCounts)
+$(makeLenses ''MsgLinuxProcessSocketCounts)
+
+msgLinuxProcessSocketQueues :: Word16
+msgLinuxProcessSocketQueues = 0x7F04
+
+-- | SBP class for message MSG_LINUX_PROCESS_SOCKET_QUEUES (0x7F04).
+--
+-- Top 10 list of sockets with deep queues.
+data MsgLinuxProcessSocketQueues = MsgLinuxProcessSocketQueues
+  { _msgLinuxProcessSocketQueues_index            :: !Word8
+    -- ^ sequence of this status message, values from 0-9
+  , _msgLinuxProcessSocketQueues_pid              :: !Word16
+    -- ^ the PID of the process in question
+  , _msgLinuxProcessSocketQueues_recv_queued      :: !Word16
+    -- ^ the total amount of receive data queued for this process
+  , _msgLinuxProcessSocketQueues_send_queued      :: !Word16
+    -- ^ the total amount of send data queued for this process
+  , _msgLinuxProcessSocketQueues_socket_types     :: !Word16
+    -- ^ A bitfield indicating the socket types used:   0x1 (tcp), 0x2 (udp), 0x4
+    -- (unix stream), 0x8 (unix dgram), 0x10 (netlink),   and 0x8000 (unknown)
+  , _msgLinuxProcessSocketQueues_socket_states    :: !Word16
+    -- ^ A bitfield indicating the socket states:   0x1 (established), 0x2 (syn-
+    -- sent), 0x4 (syn-recv), 0x8 (fin-wait-1),   0x10 (fin-wait-2), 0x20
+    -- (time-wait), 0x40 (closed), 0x80 (close-wait),   0x100 (last-ack), 0x200
+    -- (listen), 0x400 (closing), 0x800 (unconnected),   and 0x8000 (unknown)
+  , _msgLinuxProcessSocketQueues_address_of_largest :: !Text
+    -- ^ Address of the largest queue, remote or local depending on the
+    -- directionality of the connection.
+  , _msgLinuxProcessSocketQueues_cmdline          :: !Text
+    -- ^ the command line of the process in question
+  } deriving ( Show, Read, Eq )
+
+instance Binary MsgLinuxProcessSocketQueues where
+  get = do
+    _msgLinuxProcessSocketQueues_index <- getWord8
+    _msgLinuxProcessSocketQueues_pid <- getWord16le
+    _msgLinuxProcessSocketQueues_recv_queued <- getWord16le
+    _msgLinuxProcessSocketQueues_send_queued <- getWord16le
+    _msgLinuxProcessSocketQueues_socket_types <- getWord16le
+    _msgLinuxProcessSocketQueues_socket_states <- getWord16le
+    _msgLinuxProcessSocketQueues_address_of_largest <- decodeUtf8 <$> getByteString 64
+    _msgLinuxProcessSocketQueues_cmdline <- decodeUtf8 . toStrict <$> getRemainingLazyByteString
+    pure MsgLinuxProcessSocketQueues {..}
+
+  put MsgLinuxProcessSocketQueues {..} = do
+    putWord8 _msgLinuxProcessSocketQueues_index
+    putWord16le _msgLinuxProcessSocketQueues_pid
+    putWord16le _msgLinuxProcessSocketQueues_recv_queued
+    putWord16le _msgLinuxProcessSocketQueues_send_queued
+    putWord16le _msgLinuxProcessSocketQueues_socket_types
+    putWord16le _msgLinuxProcessSocketQueues_socket_states
+    putByteString $ encodeUtf8 _msgLinuxProcessSocketQueues_address_of_largest
+    putByteString $ encodeUtf8 _msgLinuxProcessSocketQueues_cmdline
+
+$(makeSBP 'msgLinuxProcessSocketQueues ''MsgLinuxProcessSocketQueues)
+$(makeJSON "_msgLinuxProcessSocketQueues_" ''MsgLinuxProcessSocketQueues)
+$(makeLenses ''MsgLinuxProcessSocketQueues)
+
+msgLinuxSocketUsage :: Word16
+msgLinuxSocketUsage = 0x7F05
+
+-- | SBP class for message MSG_LINUX_SOCKET_USAGE (0x7F05).
+--
+-- Summaries the socket usage across the system.
+data MsgLinuxSocketUsage = MsgLinuxSocketUsage
+  { _msgLinuxSocketUsage_avg_queue_depth   :: !Word32
+    -- ^ average socket queue depths across all sockets on the system
+  , _msgLinuxSocketUsage_max_queue_depth   :: !Word32
+    -- ^ the max queue depth seen within the reporting period
+  , _msgLinuxSocketUsage_socket_state_counts :: ![Word16]
+    -- ^ A count for each socket type reported in the `socket_types_reported`
+    -- field, the first entry corresponds to the first enabled bit in
+    -- `types_reported`.
+  , _msgLinuxSocketUsage_socket_type_counts :: ![Word16]
+    -- ^ A count for each socket type reported in the `socket_types_reported`
+    -- field, the first entry corresponds to the first enabled bit in
+    -- `types_reported`.
+  } deriving ( Show, Read, Eq )
+
+instance Binary MsgLinuxSocketUsage where
+  get = do
+    _msgLinuxSocketUsage_avg_queue_depth <- getWord32le
+    _msgLinuxSocketUsage_max_queue_depth <- getWord32le
+    _msgLinuxSocketUsage_socket_state_counts <- replicateM 16 getWord16le
+    _msgLinuxSocketUsage_socket_type_counts <- replicateM 16 getWord16le
+    pure MsgLinuxSocketUsage {..}
+
+  put MsgLinuxSocketUsage {..} = do
+    putWord32le _msgLinuxSocketUsage_avg_queue_depth
+    putWord32le _msgLinuxSocketUsage_max_queue_depth
+    mapM_ putWord16le _msgLinuxSocketUsage_socket_state_counts
+    mapM_ putWord16le _msgLinuxSocketUsage_socket_type_counts
+
+$(makeSBP 'msgLinuxSocketUsage ''MsgLinuxSocketUsage)
+$(makeJSON "_msgLinuxSocketUsage_" ''MsgLinuxSocketUsage)
+$(makeLenses ''MsgLinuxSocketUsage)
+
+msgLinuxProcessFdCount :: Word16
+msgLinuxProcessFdCount = 0x7F06
+
+-- | SBP class for message MSG_LINUX_PROCESS_FD_COUNT (0x7F06).
+--
+-- Top 10 list of processes with a large number of open file descriptors.
+data MsgLinuxProcessFdCount = MsgLinuxProcessFdCount
+  { _msgLinuxProcessFdCount_index  :: !Word8
+    -- ^ sequence of this status message, values from 0-9
+  , _msgLinuxProcessFdCount_pid    :: !Word16
+    -- ^ the PID of the process in question
+  , _msgLinuxProcessFdCount_fd_count :: !Word16
+    -- ^ a count of the number of file descriptors opened by the process
+  , _msgLinuxProcessFdCount_cmdline :: !Text
+    -- ^ the command line of the process in question
+  } deriving ( Show, Read, Eq )
+
+instance Binary MsgLinuxProcessFdCount where
+  get = do
+    _msgLinuxProcessFdCount_index <- getWord8
+    _msgLinuxProcessFdCount_pid <- getWord16le
+    _msgLinuxProcessFdCount_fd_count <- getWord16le
+    _msgLinuxProcessFdCount_cmdline <- decodeUtf8 . toStrict <$> getRemainingLazyByteString
+    pure MsgLinuxProcessFdCount {..}
+
+  put MsgLinuxProcessFdCount {..} = do
+    putWord8 _msgLinuxProcessFdCount_index
+    putWord16le _msgLinuxProcessFdCount_pid
+    putWord16le _msgLinuxProcessFdCount_fd_count
+    putByteString $ encodeUtf8 _msgLinuxProcessFdCount_cmdline
+
+$(makeSBP 'msgLinuxProcessFdCount ''MsgLinuxProcessFdCount)
+$(makeJSON "_msgLinuxProcessFdCount_" ''MsgLinuxProcessFdCount)
+$(makeLenses ''MsgLinuxProcessFdCount)
+
+msgLinuxProcessFdSummary :: Word16
+msgLinuxProcessFdSummary = 0x7F07
+
+-- | SBP class for message MSG_LINUX_PROCESS_FD_SUMMARY (0x7F07).
+--
+-- Summary of open file descriptors on the system.
+data MsgLinuxProcessFdSummary = MsgLinuxProcessFdSummary
+  { _msgLinuxProcessFdSummary_sys_fd_count :: !Word32
+    -- ^ count of total FDs open on the system
+  , _msgLinuxProcessFdSummary_most_opened :: !Text
+    -- ^ A null delimited list of strings which alternates between a string
+    -- representation of the process count and the file name whose count it
+    -- being reported.  That is, in C string syntax
+    -- "32\0/var/log/syslog\012\0/tmp/foo\0" with the end of the list being 2
+    -- NULL terminators in a row.
+  } deriving ( Show, Read, Eq )
+
+instance Binary MsgLinuxProcessFdSummary where
+  get = do
+    _msgLinuxProcessFdSummary_sys_fd_count <- getWord32le
+    _msgLinuxProcessFdSummary_most_opened <- decodeUtf8 . toStrict <$> getRemainingLazyByteString
+    pure MsgLinuxProcessFdSummary {..}
+
+  put MsgLinuxProcessFdSummary {..} = do
+    putWord32le _msgLinuxProcessFdSummary_sys_fd_count
+    putByteString $ encodeUtf8 _msgLinuxProcessFdSummary_most_opened
+
+$(makeSBP 'msgLinuxProcessFdSummary ''MsgLinuxProcessFdSummary)
+$(makeJSON "_msgLinuxProcessFdSummary_" ''MsgLinuxProcessFdSummary)
+$(makeLenses ''MsgLinuxProcessFdSummary)
diff --git a/src/SwiftNav/SBP/Msg.hs b/src/SwiftNav/SBP/Msg.hs
--- a/src/SwiftNav/SBP/Msg.hs
+++ b/src/SwiftNav/SBP/Msg.hs
@@ -31,6 +31,7 @@
 import SwiftNav.SBP.Flash
 import SwiftNav.SBP.Gnss
 import SwiftNav.SBP.Imu
+import SwiftNav.SBP.Linux
 import SwiftNav.SBP.Logging
 import SwiftNav.SBP.Mag
 import SwiftNav.SBP.Navigation
@@ -82,6 +83,8 @@
    | SBPMsgCommandOutput MsgCommandOutput Msg
    | SBPMsgCommandReq MsgCommandReq Msg
    | SBPMsgCommandResp MsgCommandResp Msg
+   | SBPMsgCsacTelemetry MsgCsacTelemetry Msg
+   | SBPMsgCsacTelemetryLabels MsgCsacTelemetryLabels Msg
    | SBPMsgCwResults MsgCwResults Msg
    | SBPMsgCwStart MsgCwStart Msg
    | SBPMsgDeviceMonitor MsgDeviceMonitor Msg
@@ -133,6 +136,14 @@
    | SBPMsgInitBase MsgInitBase Msg
    | SBPMsgInsStatus MsgInsStatus Msg
    | SBPMsgIono MsgIono Msg
+   | SBPMsgLinuxCpuState MsgLinuxCpuState Msg
+   | SBPMsgLinuxMemState MsgLinuxMemState Msg
+   | SBPMsgLinuxProcessFdCount MsgLinuxProcessFdCount Msg
+   | SBPMsgLinuxProcessFdSummary MsgLinuxProcessFdSummary Msg
+   | SBPMsgLinuxProcessSocketCounts MsgLinuxProcessSocketCounts Msg
+   | SBPMsgLinuxProcessSocketQueues MsgLinuxProcessSocketQueues Msg
+   | SBPMsgLinuxSocketUsage MsgLinuxSocketUsage Msg
+   | SBPMsgLinuxSysState MsgLinuxSysState Msg
    | SBPMsgLog MsgLog Msg
    | SBPMsgM25FlashWriteStatus MsgM25FlashWriteStatus Msg
    | SBPMsgMagRaw MsgMagRaw Msg
@@ -177,6 +188,7 @@
    | SBPMsgSpecanDep MsgSpecanDep Msg
    | SBPMsgSsrCodeBiases MsgSsrCodeBiases Msg
    | SBPMsgSsrOrbitClock MsgSsrOrbitClock Msg
+   | SBPMsgSsrOrbitClockDepA MsgSsrOrbitClockDepA Msg
    | SBPMsgSsrPhaseBiases MsgSsrPhaseBiases Msg
    | SBPMsgStartup MsgStartup Msg
    | SBPMsgStmFlashLockSector MsgStmFlashLockSector Msg
@@ -246,6 +258,8 @@
           | _msgSBPType == msgCommandOutput = SBPMsgCommandOutput (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgCommandReq = SBPMsgCommandReq (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgCommandResp = SBPMsgCommandResp (decode (fromStrict (unBytes _msgSBPPayload))) m
+          | _msgSBPType == msgCsacTelemetry = SBPMsgCsacTelemetry (decode (fromStrict (unBytes _msgSBPPayload))) m
+          | _msgSBPType == msgCsacTelemetryLabels = SBPMsgCsacTelemetryLabels (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgCwResults = SBPMsgCwResults (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgCwStart = SBPMsgCwStart (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgDeviceMonitor = SBPMsgDeviceMonitor (decode (fromStrict (unBytes _msgSBPPayload))) m
@@ -297,6 +311,14 @@
           | _msgSBPType == msgInitBase = SBPMsgInitBase (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgInsStatus = SBPMsgInsStatus (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgIono = SBPMsgIono (decode (fromStrict (unBytes _msgSBPPayload))) m
+          | _msgSBPType == msgLinuxCpuState = SBPMsgLinuxCpuState (decode (fromStrict (unBytes _msgSBPPayload))) m
+          | _msgSBPType == msgLinuxMemState = SBPMsgLinuxMemState (decode (fromStrict (unBytes _msgSBPPayload))) m
+          | _msgSBPType == msgLinuxProcessFdCount = SBPMsgLinuxProcessFdCount (decode (fromStrict (unBytes _msgSBPPayload))) m
+          | _msgSBPType == msgLinuxProcessFdSummary = SBPMsgLinuxProcessFdSummary (decode (fromStrict (unBytes _msgSBPPayload))) m
+          | _msgSBPType == msgLinuxProcessSocketCounts = SBPMsgLinuxProcessSocketCounts (decode (fromStrict (unBytes _msgSBPPayload))) m
+          | _msgSBPType == msgLinuxProcessSocketQueues = SBPMsgLinuxProcessSocketQueues (decode (fromStrict (unBytes _msgSBPPayload))) m
+          | _msgSBPType == msgLinuxSocketUsage = SBPMsgLinuxSocketUsage (decode (fromStrict (unBytes _msgSBPPayload))) m
+          | _msgSBPType == msgLinuxSysState = SBPMsgLinuxSysState (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgLog = SBPMsgLog (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgM25FlashWriteStatus = SBPMsgM25FlashWriteStatus (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgMagRaw = SBPMsgMagRaw (decode (fromStrict (unBytes _msgSBPPayload))) m
@@ -341,6 +363,7 @@
           | _msgSBPType == msgSpecanDep = SBPMsgSpecanDep (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgSsrCodeBiases = SBPMsgSsrCodeBiases (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgSsrOrbitClock = SBPMsgSsrOrbitClock (decode (fromStrict (unBytes _msgSBPPayload))) m
+          | _msgSBPType == msgSsrOrbitClockDepA = SBPMsgSsrOrbitClockDepA (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgSsrPhaseBiases = SBPMsgSsrPhaseBiases (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgStartup = SBPMsgStartup (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgStmFlashLockSector = SBPMsgStmFlashLockSector (decode (fromStrict (unBytes _msgSBPPayload))) m
@@ -402,6 +425,8 @@
       encoder (SBPMsgCommandOutput _ m) = put m
       encoder (SBPMsgCommandReq _ m) = put m
       encoder (SBPMsgCommandResp _ m) = put m
+      encoder (SBPMsgCsacTelemetry _ m) = put m
+      encoder (SBPMsgCsacTelemetryLabels _ m) = put m
       encoder (SBPMsgCwResults _ m) = put m
       encoder (SBPMsgCwStart _ m) = put m
       encoder (SBPMsgDeviceMonitor _ m) = put m
@@ -453,6 +478,14 @@
       encoder (SBPMsgInitBase _ m) = put m
       encoder (SBPMsgInsStatus _ m) = put m
       encoder (SBPMsgIono _ m) = put m
+      encoder (SBPMsgLinuxCpuState _ m) = put m
+      encoder (SBPMsgLinuxMemState _ m) = put m
+      encoder (SBPMsgLinuxProcessFdCount _ m) = put m
+      encoder (SBPMsgLinuxProcessFdSummary _ m) = put m
+      encoder (SBPMsgLinuxProcessSocketCounts _ m) = put m
+      encoder (SBPMsgLinuxProcessSocketQueues _ m) = put m
+      encoder (SBPMsgLinuxSocketUsage _ m) = put m
+      encoder (SBPMsgLinuxSysState _ m) = put m
       encoder (SBPMsgLog _ m) = put m
       encoder (SBPMsgM25FlashWriteStatus _ m) = put m
       encoder (SBPMsgMagRaw _ m) = put m
@@ -497,6 +530,7 @@
       encoder (SBPMsgSpecanDep _ m) = put m
       encoder (SBPMsgSsrCodeBiases _ m) = put m
       encoder (SBPMsgSsrOrbitClock _ m) = put m
+      encoder (SBPMsgSsrOrbitClockDepA _ m) = put m
       encoder (SBPMsgSsrPhaseBiases _ m) = put m
       encoder (SBPMsgStartup _ m) = put m
       encoder (SBPMsgStmFlashLockSector _ m) = put m
@@ -562,6 +596,8 @@
         | msgType == msgCommandOutput = SBPMsgCommandOutput <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgCommandReq = SBPMsgCommandReq <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgCommandResp = SBPMsgCommandResp <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
+        | msgType == msgCsacTelemetry = SBPMsgCsacTelemetry <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
+        | msgType == msgCsacTelemetryLabels = SBPMsgCsacTelemetryLabels <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgCwResults = SBPMsgCwResults <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgCwStart = SBPMsgCwStart <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgDeviceMonitor = SBPMsgDeviceMonitor <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
@@ -613,6 +649,14 @@
         | msgType == msgInitBase = SBPMsgInitBase <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgInsStatus = SBPMsgInsStatus <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgIono = SBPMsgIono <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
+        | msgType == msgLinuxCpuState = SBPMsgLinuxCpuState <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
+        | msgType == msgLinuxMemState = SBPMsgLinuxMemState <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
+        | msgType == msgLinuxProcessFdCount = SBPMsgLinuxProcessFdCount <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
+        | msgType == msgLinuxProcessFdSummary = SBPMsgLinuxProcessFdSummary <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
+        | msgType == msgLinuxProcessSocketCounts = SBPMsgLinuxProcessSocketCounts <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
+        | msgType == msgLinuxProcessSocketQueues = SBPMsgLinuxProcessSocketQueues <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
+        | msgType == msgLinuxSocketUsage = SBPMsgLinuxSocketUsage <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
+        | msgType == msgLinuxSysState = SBPMsgLinuxSysState <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgLog = SBPMsgLog <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgM25FlashWriteStatus = SBPMsgM25FlashWriteStatus <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgMagRaw = SBPMsgMagRaw <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
@@ -657,6 +701,7 @@
         | msgType == msgSpecanDep = SBPMsgSpecanDep <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgSsrCodeBiases = SBPMsgSsrCodeBiases <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgSsrOrbitClock = SBPMsgSsrOrbitClock <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
+        | msgType == msgSsrOrbitClockDepA = SBPMsgSsrOrbitClockDepA <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgSsrPhaseBiases = SBPMsgSsrPhaseBiases <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgStartup = SBPMsgStartup <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgStmFlashLockSector = SBPMsgStmFlashLockSector <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
@@ -723,6 +768,8 @@
   toJSON (SBPMsgCommandOutput n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgCommandReq n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgCommandResp n m) = toJSON n <<>> toJSON m
+  toJSON (SBPMsgCsacTelemetry n m) = toJSON n <<>> toJSON m
+  toJSON (SBPMsgCsacTelemetryLabels n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgCwResults n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgCwStart n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgDeviceMonitor n m) = toJSON n <<>> toJSON m
@@ -774,6 +821,14 @@
   toJSON (SBPMsgInitBase n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgInsStatus n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgIono n m) = toJSON n <<>> toJSON m
+  toJSON (SBPMsgLinuxCpuState n m) = toJSON n <<>> toJSON m
+  toJSON (SBPMsgLinuxMemState n m) = toJSON n <<>> toJSON m
+  toJSON (SBPMsgLinuxProcessFdCount n m) = toJSON n <<>> toJSON m
+  toJSON (SBPMsgLinuxProcessFdSummary n m) = toJSON n <<>> toJSON m
+  toJSON (SBPMsgLinuxProcessSocketCounts n m) = toJSON n <<>> toJSON m
+  toJSON (SBPMsgLinuxProcessSocketQueues n m) = toJSON n <<>> toJSON m
+  toJSON (SBPMsgLinuxSocketUsage n m) = toJSON n <<>> toJSON m
+  toJSON (SBPMsgLinuxSysState n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgLog n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgM25FlashWriteStatus n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgMagRaw n m) = toJSON n <<>> toJSON m
@@ -818,6 +873,7 @@
   toJSON (SBPMsgSpecanDep n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgSsrCodeBiases n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgSsrOrbitClock n m) = toJSON n <<>> toJSON m
+  toJSON (SBPMsgSsrOrbitClockDepA n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgSsrPhaseBiases n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgStartup n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgStmFlashLockSector n m) = toJSON n <<>> toJSON m
@@ -878,6 +934,8 @@
   msg f (SBPMsgCommandOutput n m) = SBPMsgCommandOutput n <$> f m
   msg f (SBPMsgCommandReq n m) = SBPMsgCommandReq n <$> f m
   msg f (SBPMsgCommandResp n m) = SBPMsgCommandResp n <$> f m
+  msg f (SBPMsgCsacTelemetry n m) = SBPMsgCsacTelemetry n <$> f m
+  msg f (SBPMsgCsacTelemetryLabels n m) = SBPMsgCsacTelemetryLabels n <$> f m
   msg f (SBPMsgCwResults n m) = SBPMsgCwResults n <$> f m
   msg f (SBPMsgCwStart n m) = SBPMsgCwStart n <$> f m
   msg f (SBPMsgDeviceMonitor n m) = SBPMsgDeviceMonitor n <$> f m
@@ -929,6 +987,14 @@
   msg f (SBPMsgInitBase n m) = SBPMsgInitBase n <$> f m
   msg f (SBPMsgInsStatus n m) = SBPMsgInsStatus n <$> f m
   msg f (SBPMsgIono n m) = SBPMsgIono n <$> f m
+  msg f (SBPMsgLinuxCpuState n m) = SBPMsgLinuxCpuState n <$> f m
+  msg f (SBPMsgLinuxMemState n m) = SBPMsgLinuxMemState n <$> f m
+  msg f (SBPMsgLinuxProcessFdCount n m) = SBPMsgLinuxProcessFdCount n <$> f m
+  msg f (SBPMsgLinuxProcessFdSummary n m) = SBPMsgLinuxProcessFdSummary n <$> f m
+  msg f (SBPMsgLinuxProcessSocketCounts n m) = SBPMsgLinuxProcessSocketCounts n <$> f m
+  msg f (SBPMsgLinuxProcessSocketQueues n m) = SBPMsgLinuxProcessSocketQueues n <$> f m
+  msg f (SBPMsgLinuxSocketUsage n m) = SBPMsgLinuxSocketUsage n <$> f m
+  msg f (SBPMsgLinuxSysState n m) = SBPMsgLinuxSysState n <$> f m
   msg f (SBPMsgLog n m) = SBPMsgLog n <$> f m
   msg f (SBPMsgM25FlashWriteStatus n m) = SBPMsgM25FlashWriteStatus n <$> f m
   msg f (SBPMsgMagRaw n m) = SBPMsgMagRaw n <$> f m
@@ -973,6 +1039,7 @@
   msg f (SBPMsgSpecanDep n m) = SBPMsgSpecanDep n <$> f m
   msg f (SBPMsgSsrCodeBiases n m) = SBPMsgSsrCodeBiases n <$> f m
   msg f (SBPMsgSsrOrbitClock n m) = SBPMsgSsrOrbitClock n <$> f m
+  msg f (SBPMsgSsrOrbitClockDepA n m) = SBPMsgSsrOrbitClockDepA n <$> f m
   msg f (SBPMsgSsrPhaseBiases n m) = SBPMsgSsrPhaseBiases n <$> f m
   msg f (SBPMsgStartup n m) = SBPMsgStartup n <$> f m
   msg f (SBPMsgStmFlashLockSector n m) = SBPMsgStmFlashLockSector n <$> f m
diff --git a/src/SwiftNav/SBP/Navigation.hs b/src/SwiftNav/SBP/Navigation.hs
--- a/src/SwiftNav/SBP/Navigation.hs
+++ b/src/SwiftNav/SBP/Navigation.hs
@@ -24,7 +24,7 @@
 -- by device settings.  By default, the vehicle body frame is configured to be
 -- coincident with the antenna phase center.  When there is no inertial
 -- navigation, the solution will be reported at the phase center of the
--- antenna.
+-- antenna. There is no inertial navigation capability on Piksi Multi or Duro.
 
 module SwiftNav.SBP.Navigation
   ( module SwiftNav.SBP.Navigation
@@ -818,7 +818,9 @@
 -- of the vehicle. Since this is a right handed system, z should point out the
 -- bottom of the vehicle. The orientation and origin of the Vehicle Body Frame
 -- are specified via the device settings. The full GPS time is given by the
--- preceding MSG_GPS_TIME with the matching time-of-week (tow).
+-- preceding MSG_GPS_TIME with the matching time-of-week (tow). This message is
+-- only produced by inertial versions of Swift products and is not available
+-- from Piksi Multi or Duro.
 data MsgVelBody = MsgVelBody
   { _msgVelBody_tow   :: !Word32
     -- ^ GPS Time of Week
diff --git a/src/SwiftNav/SBP/Observation.hs b/src/SwiftNav/SBP/Observation.hs
--- a/src/SwiftNav/SBP/Observation.hs
+++ b/src/SwiftNav/SBP/Observation.hs
@@ -89,7 +89,9 @@
 --
 -- Pseudorange and carrier phase observation for a satellite being tracked. The
 -- observations are interoperable with 3rd party receivers and conform with
--- typical RTCMv3 GNSS observations.
+-- typical RTCM 3.1 message GPS/GLO observations.  Carrier phase observations
+-- are not guaranteed to be aligned to the RINEX 3 or RTCM 3.3 MSM reference
+-- signal and no 1/4 cycle adjustments are currently peformed.
 data PackedObsContent = PackedObsContent
   { _packedObsContent_P   :: !Word32
     -- ^ Pseudorange observation
@@ -2750,7 +2752,7 @@
 
 -- | SBP class for message MSG_GLO_BIASES (0x0075).
 --
--- The GLONASS L1/L2 Code-Phase biases allows to perform  GPS+GLONASS integer
+-- The GLONASS L1/L2 Code-Phase biases allows to perform GPS+GLONASS integer
 -- ambiguity resolution for baselines with mixed receiver types (e.g. receiver
 -- of different manufacturers)
 data MsgGloBiases = MsgGloBiases
diff --git a/src/SwiftNav/SBP/Orientation.hs b/src/SwiftNav/SBP/Orientation.hs
--- a/src/SwiftNav/SBP/Orientation.hs
+++ b/src/SwiftNav/SBP/Orientation.hs
@@ -80,7 +80,8 @@
 -- This message reports the quaternion vector describing the vehicle body
 -- frame's orientation with respect to a local-level NED frame. The components
 -- of the vector should sum to a unit vector assuming that the LSB of each
--- component as a value of 2^-31.
+-- component as a value of 2^-31. This message will only be available in future
+-- INS versions of Swift Products and is not produced by Piksi Multi  or Duro.
 data MsgOrientQuat = MsgOrientQuat
   { _msgOrientQuat_tow      :: !Word32
     -- ^ GPS Time of Week
@@ -142,7 +143,9 @@
 -- This message reports the yaw, pitch, and roll angles of the vehicle body
 -- frame. The rotations should applied intrinsically in the order yaw, pitch,
 -- and roll  in order to rotate the from a frame aligned with the local-level
--- NED frame  to the vehicle body frame.
+-- NED frame  to the vehicle body frame.  This message will only be available
+-- in future  INS versions of Swift Products and is not produced by Piksi Multi
+-- or Duro.
 data MsgOrientEuler = MsgOrientEuler
   { _msgOrientEuler_tow          :: !Word32
     -- ^ GPS Time of Week
@@ -200,6 +203,8 @@
 -- By convention, the vehicle x-axis is expected to be aligned with the forward
 -- direction, while the vehicle y-axis is expected to be aligned with the right
 -- direction, and the vehicle z-axis should be aligned with the down direction.
+-- This message will only be available in future INS versions of Swift Products
+-- and is not produced by Piksi Multi or Duro.
 data MsgAngularRate = MsgAngularRate
   { _msgAngularRate_tow :: !Word32
     -- ^ GPS Time of Week
diff --git a/src/SwiftNav/SBP/Ssr.hs b/src/SwiftNav/SBP/Ssr.hs
--- a/src/SwiftNav/SBP/Ssr.hs
+++ b/src/SwiftNav/SBP/Ssr.hs
@@ -98,9 +98,9 @@
 $(makeLenses ''PhaseBiasesContent)
 
 msgSsrOrbitClock :: Word16
-msgSsrOrbitClock = 0x05DC
+msgSsrOrbitClock = 0x05DD
 
--- | SBP class for message MSG_SSR_ORBIT_CLOCK (0x05DC).
+-- | SBP class for message MSG_SSR_ORBIT_CLOCK (0x05DD).
 --
 -- The precise orbit and clock correction message is  to be applied as a delta
 -- correction to broadcast  ephemeris and is typically an equivalent to the
@@ -115,8 +115,8 @@
   , _msgSsrOrbitClock_iod_ssr       :: !Word8
     -- ^ IOD of the SSR correction. A change of Issue Of Data SSR is used to
     -- indicate a change in the SSR  generating configuration
-  , _msgSsrOrbitClock_iod           :: !Word8
-    -- ^ Issue of broadcast ephemeris data
+  , _msgSsrOrbitClock_iod           :: !Word32
+    -- ^ Issue of broadcast ephemeris data or IODCRC (Beidou)
   , _msgSsrOrbitClock_radial        :: !Int32
     -- ^ Orbit radial delta correction
   , _msgSsrOrbitClock_along         :: !Int32
@@ -143,7 +143,7 @@
     _msgSsrOrbitClock_sid <- get
     _msgSsrOrbitClock_update_interval <- getWord8
     _msgSsrOrbitClock_iod_ssr <- getWord8
-    _msgSsrOrbitClock_iod <- getWord8
+    _msgSsrOrbitClock_iod <- getWord32le
     _msgSsrOrbitClock_radial <- fromIntegral <$> getWord32le
     _msgSsrOrbitClock_along <- fromIntegral <$> getWord32le
     _msgSsrOrbitClock_cross <- fromIntegral <$> getWord32le
@@ -160,7 +160,7 @@
     put _msgSsrOrbitClock_sid
     putWord8 _msgSsrOrbitClock_update_interval
     putWord8 _msgSsrOrbitClock_iod_ssr
-    putWord8 _msgSsrOrbitClock_iod
+    putWord32le _msgSsrOrbitClock_iod
     putWord32le $ fromIntegral _msgSsrOrbitClock_radial
     putWord32le $ fromIntegral _msgSsrOrbitClock_along
     putWord32le $ fromIntegral _msgSsrOrbitClock_cross
@@ -174,6 +174,84 @@
 $(makeSBP 'msgSsrOrbitClock ''MsgSsrOrbitClock)
 $(makeJSON "_msgSsrOrbitClock_" ''MsgSsrOrbitClock)
 $(makeLenses ''MsgSsrOrbitClock)
+
+msgSsrOrbitClockDepA :: Word16
+msgSsrOrbitClockDepA = 0x05DC
+
+-- | SBP class for message MSG_SSR_ORBIT_CLOCK_DEP_A (0x05DC).
+--
+-- The precise orbit and clock correction message is  to be applied as a delta
+-- correction to broadcast  ephemeris and is typically an equivalent to the
+-- 1060 and 1066 RTCM message types
+data MsgSsrOrbitClockDepA = MsgSsrOrbitClockDepA
+  { _msgSsrOrbitClockDepA_time          :: !GpsTimeSec
+    -- ^ GNSS reference time of the correction
+  , _msgSsrOrbitClockDepA_sid           :: !GnssSignal
+    -- ^ GNSS signal identifier (16 bit)
+  , _msgSsrOrbitClockDepA_update_interval :: !Word8
+    -- ^ Update interval between consecutive corrections
+  , _msgSsrOrbitClockDepA_iod_ssr       :: !Word8
+    -- ^ IOD of the SSR correction. A change of Issue Of Data SSR is used to
+    -- indicate a change in the SSR  generating configuration
+  , _msgSsrOrbitClockDepA_iod           :: !Word8
+    -- ^ Issue of broadcast ephemeris data
+  , _msgSsrOrbitClockDepA_radial        :: !Int32
+    -- ^ Orbit radial delta correction
+  , _msgSsrOrbitClockDepA_along         :: !Int32
+    -- ^ Orbit along delta correction
+  , _msgSsrOrbitClockDepA_cross         :: !Int32
+    -- ^ Orbit along delta correction
+  , _msgSsrOrbitClockDepA_dot_radial    :: !Int32
+    -- ^ Velocity of orbit radial delta correction
+  , _msgSsrOrbitClockDepA_dot_along     :: !Int32
+    -- ^ Velocity of orbit along delta correction
+  , _msgSsrOrbitClockDepA_dot_cross     :: !Int32
+    -- ^ Velocity of orbit cross delta correction
+  , _msgSsrOrbitClockDepA_c0            :: !Int32
+    -- ^ C0 polynomial coefficient for correction of broadcast satellite clock
+  , _msgSsrOrbitClockDepA_c1            :: !Int32
+    -- ^ C1 polynomial coefficient for correction of broadcast satellite clock
+  , _msgSsrOrbitClockDepA_c2            :: !Int32
+    -- ^ C2 polynomial coefficient for correction of broadcast satellite clock
+  } deriving ( Show, Read, Eq )
+
+instance Binary MsgSsrOrbitClockDepA where
+  get = do
+    _msgSsrOrbitClockDepA_time <- get
+    _msgSsrOrbitClockDepA_sid <- get
+    _msgSsrOrbitClockDepA_update_interval <- getWord8
+    _msgSsrOrbitClockDepA_iod_ssr <- getWord8
+    _msgSsrOrbitClockDepA_iod <- getWord8
+    _msgSsrOrbitClockDepA_radial <- fromIntegral <$> getWord32le
+    _msgSsrOrbitClockDepA_along <- fromIntegral <$> getWord32le
+    _msgSsrOrbitClockDepA_cross <- fromIntegral <$> getWord32le
+    _msgSsrOrbitClockDepA_dot_radial <- fromIntegral <$> getWord32le
+    _msgSsrOrbitClockDepA_dot_along <- fromIntegral <$> getWord32le
+    _msgSsrOrbitClockDepA_dot_cross <- fromIntegral <$> getWord32le
+    _msgSsrOrbitClockDepA_c0 <- fromIntegral <$> getWord32le
+    _msgSsrOrbitClockDepA_c1 <- fromIntegral <$> getWord32le
+    _msgSsrOrbitClockDepA_c2 <- fromIntegral <$> getWord32le
+    pure MsgSsrOrbitClockDepA {..}
+
+  put MsgSsrOrbitClockDepA {..} = do
+    put _msgSsrOrbitClockDepA_time
+    put _msgSsrOrbitClockDepA_sid
+    putWord8 _msgSsrOrbitClockDepA_update_interval
+    putWord8 _msgSsrOrbitClockDepA_iod_ssr
+    putWord8 _msgSsrOrbitClockDepA_iod
+    putWord32le $ fromIntegral _msgSsrOrbitClockDepA_radial
+    putWord32le $ fromIntegral _msgSsrOrbitClockDepA_along
+    putWord32le $ fromIntegral _msgSsrOrbitClockDepA_cross
+    putWord32le $ fromIntegral _msgSsrOrbitClockDepA_dot_radial
+    putWord32le $ fromIntegral _msgSsrOrbitClockDepA_dot_along
+    putWord32le $ fromIntegral _msgSsrOrbitClockDepA_dot_cross
+    putWord32le $ fromIntegral _msgSsrOrbitClockDepA_c0
+    putWord32le $ fromIntegral _msgSsrOrbitClockDepA_c1
+    putWord32le $ fromIntegral _msgSsrOrbitClockDepA_c2
+
+$(makeSBP 'msgSsrOrbitClockDepA ''MsgSsrOrbitClockDepA)
+$(makeJSON "_msgSsrOrbitClockDepA_" ''MsgSsrOrbitClockDepA)
+$(makeLenses ''MsgSsrOrbitClockDepA)
 
 msgSsrCodeBiases :: Word16
 msgSsrCodeBiases = 0x05E1
diff --git a/src/SwiftNav/SBP/System.hs b/src/SwiftNav/SBP/System.hs
--- a/src/SwiftNav/SBP/System.hs
+++ b/src/SwiftNav/SBP/System.hs
@@ -157,3 +157,63 @@
 $(makeSBP 'msgInsStatus ''MsgInsStatus)
 $(makeJSON "_msgInsStatus_" ''MsgInsStatus)
 $(makeLenses ''MsgInsStatus)
+
+msgCsacTelemetry :: Word16
+msgCsacTelemetry = 0xFF04
+
+-- | SBP class for message MSG_CSAC_TELEMETRY (0xFF04).
+--
+-- The CSAC telemetry message has an implementation defined telemetry string
+-- from a device. It is not produced or available on general Swift Products. It
+-- is intended to be a low rate message for status purposes.
+data MsgCsacTelemetry = MsgCsacTelemetry
+  { _msgCsacTelemetry_id      :: !Word8
+    -- ^ Index representing the type of telemetry in use.  It is implemention
+    -- defined.
+  , _msgCsacTelemetry_telemetry :: !Text
+    -- ^ Comma separated list of values as defined by the index
+  } deriving ( Show, Read, Eq )
+
+instance Binary MsgCsacTelemetry where
+  get = do
+    _msgCsacTelemetry_id <- getWord8
+    _msgCsacTelemetry_telemetry <- decodeUtf8 . toStrict <$> getRemainingLazyByteString
+    pure MsgCsacTelemetry {..}
+
+  put MsgCsacTelemetry {..} = do
+    putWord8 _msgCsacTelemetry_id
+    putByteString $ encodeUtf8 _msgCsacTelemetry_telemetry
+
+$(makeSBP 'msgCsacTelemetry ''MsgCsacTelemetry)
+$(makeJSON "_msgCsacTelemetry_" ''MsgCsacTelemetry)
+$(makeLenses ''MsgCsacTelemetry)
+
+msgCsacTelemetryLabels :: Word16
+msgCsacTelemetryLabels = 0xFF05
+
+-- | SBP class for message MSG_CSAC_TELEMETRY_LABELS (0xFF05).
+--
+-- The CSAC telemetry message provides labels for each member of the string
+-- produced by MSG_CSAC_TELEMETRY. It should be provided by a device at a lower
+-- rate than the MSG_CSAC_TELEMETRY.
+data MsgCsacTelemetryLabels = MsgCsacTelemetryLabels
+  { _msgCsacTelemetryLabels_id             :: !Word8
+    -- ^ Index representing the type of telemetry in use.  It is implemention
+    -- defined.
+  , _msgCsacTelemetryLabels_telemetry_labels :: !Text
+    -- ^ Comma separated list of telemetry field values
+  } deriving ( Show, Read, Eq )
+
+instance Binary MsgCsacTelemetryLabels where
+  get = do
+    _msgCsacTelemetryLabels_id <- getWord8
+    _msgCsacTelemetryLabels_telemetry_labels <- decodeUtf8 . toStrict <$> getRemainingLazyByteString
+    pure MsgCsacTelemetryLabels {..}
+
+  put MsgCsacTelemetryLabels {..} = do
+    putWord8 _msgCsacTelemetryLabels_id
+    putByteString $ encodeUtf8 _msgCsacTelemetryLabels_telemetry_labels
+
+$(makeSBP 'msgCsacTelemetryLabels ''MsgCsacTelemetryLabels)
+$(makeJSON "_msgCsacTelemetryLabels_" ''MsgCsacTelemetryLabels)
+$(makeLenses ''MsgCsacTelemetryLabels)
