Update pica to v0.1.9 from upstream

Merge remote-tracking branch 'aosp/upstream-main' into pica-update

Test: TreeHugger
Test: atest CtsUwbTestCases
Change-Id: Icd5f2ef8e5443ce800cfdce15a96d3ff171132b2
diff --git a/Cargo.lock b/Cargo.lock
index a59c5c0..ca8765e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -648,7 +648,7 @@
 
 [[package]]
 name = "pica"
-version = "0.1.7"
+version = "0.1.9"
 dependencies = [
  "anyhow",
  "bytes",
diff --git a/Cargo.toml b/Cargo.toml
index 7fea374..d27cd71 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "pica"
-version = "0.1.8"
+version = "0.1.9"
 edition = "2021"
 description = "Pica is a virtual UWB Controller implementing the FiRa UCI specification."
 repository = "https://github.com/google/pica"
diff --git a/METADATA b/METADATA
index 36c8e14..46cbcbf 100644
--- a/METADATA
+++ b/METADATA
@@ -12,7 +12,7 @@
     type: GIT
     value: "https://github.com/google/pica.git"
   }
-  version: "v0.1.8"
+  version: "v0.1.9"
   license_type: NOTICE
-  last_upgrade_date { year: 2024 month: 3 day: 13 }
+  last_upgrade_date { year: 2024 month: 4 day: 5 }
 }
diff --git a/py/pica/pica/packets/uci.py b/py/pica/pica/packets/uci.py
index 32ffbdc..574feab 100644
--- a/py/pica/pica/packets/uci.py
+++ b/py/pica/pica/packets/uci.py
@@ -94,16 +94,30 @@
             raise exn
 
 
+class MessageType(enum.IntEnum):
+    DATA = 0x0
+    COMMAND = 0x1
+    RESPONSE = 0x2
+    NOTIFICATION = 0x3
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'MessageType']:
+        try:
+            return MessageType(v)
+        except ValueError as exn:
+            raise exn
+
+
 class GroupId(enum.IntEnum):
     CORE = 0x0
     SESSION_CONFIG = 0x1
     SESSION_CONTROL = 0x2
     DATA_CONTROL = 0x3
-    TEST = 0xd
     VENDOR_RESERVED_9 = 0x9
     VENDOR_RESERVED_A = 0xa
     VENDOR_RESERVED_B = 0xb
     VENDOR_ANDROID = 0xc
+    TEST = 0xd
     VENDOR_RESERVED_E = 0xe
     VENDOR_RESERVED_F = 0xf
 
@@ -127,154 +141,112 @@
             raise exn
 
 
-class GroupIdOrDataPacketFormat(enum.IntEnum):
-    CORE = 0x0
-    SESSION_CONFIG_OR_DATA_SND = 0x1
-    SESSION_CONTROL_OR_DATA_RCV = 0x2
-    DATA_CONTROL = 0x3
-    TEST = 0xd
-    VENDOR_RESERVED_9 = 0x9
-    VENDOR_RESERVED_A = 0xa
-    VENDOR_RESERVED_B = 0xb
-    VENDOR_ANDROID = 0xc
-    VENDOR_RESERVED_E = 0xe
-    VENDOR_RESERVED_F = 0xf
+class CoreOpcodeId(enum.IntEnum):
+    DEVICE_RESET = 0x0
+    DEVICE_STATUS = 0x1
+    GET_DEVICE_INFO = 0x2
+    GET_CAPS_INFO = 0x3
+    SET_CONFIG = 0x4
+    GET_CONFIG = 0x5
+    GENERIC_ERROR = 0x7
+    QUERY_UWBS_TIMESTAMP = 0x8
 
     @staticmethod
-    def from_int(v: int) -> Union[int, 'GroupIdOrDataPacketFormat']:
+    def from_int(v: int) -> Union[int, 'CoreOpcodeId']:
         try:
-            return GroupIdOrDataPacketFormat(v)
+            return CoreOpcodeId(v)
         except ValueError as exn:
             raise exn
 
 
-class CoreOpCode(enum.IntEnum):
-    CORE_DEVICE_RESET = 0x0
-    CORE_DEVICE_STATUS_NTF = 0x1
-    CORE_DEVICE_INFO = 0x2
-    CORE_GET_CAPS_INFO = 0x3
-    CORE_SET_CONFIG = 0x4
-    CORE_GET_CONFIG = 0x5
-    CORE_DEVICE_SUSPEND = 0x6
-    CORE_GENERIC_ERROR_NTF = 0x7
-    CORE_QUERY_UWBS_TIMESTAMP = 0x8
+class SessionConfigOpcodeId(enum.IntEnum):
+    INIT = 0x0
+    DEINIT = 0x1
+    STATUS = 0x2
+    SET_APP_CONFIG = 0x3
+    GET_APP_CONFIG = 0x4
+    GET_COUNT = 0x5
+    GET_STATE = 0x6
+    UPDATE_CONTROLLER_MULTICAST_LIST = 0x7
+    UPDATE_DT_ANCHOR_RANGING_ROUNDS = 0x8
+    UPDATE_DT_TAG_RANGING_ROUNDS = 0x9
+    QUERY_DATA_SIZE_IN_RANGING = 0xb
 
     @staticmethod
-    def from_int(v: int) -> Union[int, 'CoreOpCode']:
+    def from_int(v: int) -> Union[int, 'SessionConfigOpcodeId']:
         try:
-            return CoreOpCode(v)
+            return SessionConfigOpcodeId(v)
         except ValueError as exn:
             raise exn
 
 
-class SessionConfigOpCode(enum.IntEnum):
-    SESSION_INIT = 0x0
-    SESSION_DEINIT = 0x1
-    SESSION_STATUS_NTF = 0x2
-    SESSION_SET_APP_CONFIG = 0x3
-    SESSION_GET_APP_CONFIG = 0x4
-    SESSION_GET_COUNT = 0x5
-    SESSION_GET_STATE = 0x6
-    SESSION_UPDATE_CONTROLLER_MULTICAST_LIST = 0x7
-    SESSION_UPDATE_ACTIVE_ROUNDS_ANCHOR = 0x8
-    SESSION_UPDATE_ACTIVE_ROUNDS_DT_TAG = 0x9
-    SESSION_SET_INITIATOR_DT_ANCHOR_RR_RDM_LIST = 0xa
-    SESSION_QUERY_DATA_SIZE_IN_RANGING = 0xb
-    SESSION_SET_HUS_CONFIG = 0xc
+class SessionControlOpcodeId(enum.IntEnum):
+    START = 0x0
+    STOP = 0x1
+    GET_RANGING_COUNT = 0x3
+    DATA_CREDIT = 0x4
+    DATA_TRANSFER_STATUS = 0x5
 
     @staticmethod
-    def from_int(v: int) -> Union[int, 'SessionConfigOpCode']:
+    def from_int(v: int) -> Union[int, 'SessionControlOpcodeId']:
         try:
-            return SessionConfigOpCode(v)
+            return SessionControlOpcodeId(v)
         except ValueError as exn:
             raise exn
 
 
-class SessionControlOpCode(enum.IntEnum):
-    SESSION_START = 0x0
-    SESSION_STOP = 0x1
-    SESSION_RESERVED = 0x2
-    SESSION_GET_RANGING_COUNT = 0x3
-    SESSION_DATA_CREDIT_NTF = 0x4
-    SESSION_DATA_TRANSFER_STATUS_NTF = 0x5
+class AndroidOpcodeId(enum.IntEnum):
+    GET_POWER_STATS = 0x0
+    SET_COUNTRY_CODE = 0x1
+    FIRA_RANGE_DIAGNOSTICS = 0x2
 
     @staticmethod
-    def from_int(v: int) -> Union[int, 'SessionControlOpCode']:
+    def from_int(v: int) -> Union[int, 'AndroidOpcodeId']:
         try:
-            return SessionControlOpCode(v)
+            return AndroidOpcodeId(v)
         except ValueError as exn:
             raise exn
 
 
-class AppDataOpCode(enum.IntEnum):
-    APP_DATA_TX = 0x0
-    APP_DATA_RX = 0x1
+class Status(enum.IntEnum):
+    OK = 0x0
+    REJECTED = 0x1
+    FAILED = 0x2
+    SYNTAX_ERROR = 0x3
+    INVALID_PARAM = 0x4
+    INVALID_RANGE = 0x5
+    INVALID_MESSAGE_SIZE = 0x6
+    UNKNOWN_GID = 0x7
+    UNKNOWN_OID = 0x8
+    READ_ONLY = 0x9
+    UCI_MESSAGE_RETRY = 0xa
+    UNKNOWN = 0xb
+    NOT_APPLICABLE = 0xc
+    ERROR_SESSION_NOT_EXIST = 0x11
+    ERROR_SESSION_DUPLICATE = 0x12
+    ERROR_SESSION_ACTIVE = 0x13
+    ERROR_MAX_SESSIONS_EXCEEDED = 0x14
+    ERROR_SESSION_NOT_CONFIGURED = 0x15
+    ERROR_ACTIVE_SESSIONS_ONGOING = 0x16
+    ERROR_MULTICAST_LIST_FULL = 0x17
+    ERROR_UWB_INITIATION_TIME_TOO_OLD = 0x1a
+    OK_NEGATIVE_DISTANCE_REPORT = 0x1b
+    RANGING_TX_FAILED = 0x20
+    RANGING_RX_TIMEOUT = 0x21
+    RANGING_RX_PHY_DEC_FAILED = 0x22
+    RANGING_RX_PHY_TOA_FAILED = 0x23
+    RANGING_RX_PHY_STS_FAILED = 0x24
+    RANGING_RX_MAC_DEC_FAILED = 0x25
+    RANGING_RX_MAC_IE_DEC_FAILED = 0x26
+    RANGING_RX_MAC_IE_MISSING = 0x27
+    ERROR_ROUND_INDEX_NOT_ACTIVATED = 0x28
+    ERROR_NUMBER_OF_ACTIVE_RANGING_ROUNDS_EXCEEDED = 0x29
+    ERROR_DL_TDOA_DEVICE_ADDRESS_NOT_MATCHING_IN_REPLY_TIME_LIST = 0x2a
 
     @staticmethod
-    def from_int(v: int) -> Union[int, 'AppDataOpCode']:
+    def from_int(v: int) -> Union[int, 'Status']:
         try:
-            return AppDataOpCode(v)
-        except ValueError as exn:
-            raise exn
-
-
-class AndroidOpCode(enum.IntEnum):
-    ANDROID_GET_POWER_STATS = 0x0
-    ANDROID_SET_COUNTRY_CODE = 0x1
-    ANDROID_FIRA_RANGE_DIAGNOSTICS = 0x2
-
-    @staticmethod
-    def from_int(v: int) -> Union[int, 'AndroidOpCode']:
-        try:
-            return AndroidOpCode(v)
-        except ValueError as exn:
-            raise exn
-
-
-class StatusCode(enum.IntEnum):
-    UCI_STATUS_OK = 0x0
-    UCI_STATUS_REJECTED = 0x1
-    UCI_STATUS_FAILED = 0x2
-    UCI_STATUS_SYNTAX_ERROR = 0x3
-    UCI_STATUS_INVALID_PARAM = 0x4
-    UCI_STATUS_INVALID_RANGE = 0x5
-    UCI_STATUS_INVALID_MSG_SIZE = 0x6
-    UCI_STATUS_UNKNOWN_GID = 0x7
-    UCI_STATUS_UNKNOWN_OID = 0x8
-    UCI_STATUS_READ_ONLY = 0x9
-    UCI_STATUS_COMMAND_RETRY = 0xa
-    UCI_STATUS_UNKNOWN = 0xb
-    UCI_STATUS_NOT_APPLICABLE = 0xc
-    UCI_STATUS_SESSION_NOT_EXIST = 0x11
-    UCI_STATUS_SESSION_DUPLICATE = 0x12
-    UCI_STATUS_SESSION_ACTIVE = 0x13
-    UCI_STATUS_MAX_SESSIONS_EXCEEDED = 0x14
-    UCI_STATUS_SESSION_NOT_CONFIGURED = 0x15
-    UCI_STATUS_ACTIVE_SESSIONS_ONGOING = 0x16
-    UCI_STATUS_MULTICAST_LIST_FULL = 0x17
-    UCI_STATUS_ADDRESS_NOT_FOUND = 0x18
-    UCI_STATUS_ADDRESS_ALREADY_PRESENT = 0x19
-    UCI_STATUS_ERROR_UWB_INITIATION_TIME_TOO_OLD = 0x1a
-    UCI_STATUS_OK_NEGATIVE_DISTANCE_REPORT = 0x1b
-    UCI_STATUS_RANGING_TX_FAILED = 0x20
-    UCI_STATUS_RANGING_RX_TIMEOUT = 0x21
-    UCI_STATUS_RANGING_RX_PHY_DEC_FAILED = 0x22
-    UCI_STATUS_RANGING_RX_PHY_TOA_FAILED = 0x23
-    UCI_STATUS_RANGING_RX_PHY_STS_FAILED = 0x24
-    UCI_STATUS_RANGING_RX_MAC_DEC_FAILED = 0x25
-    UCI_STATUS_RANGING_RX_MAC_IE_DEC_FAILED = 0x26
-    UCI_STATUS_RANGING_RX_MAC_IE_MISSING = 0x27
-    UCI_STATUS_ERROR_ROUND_INDEX_NOT_ACTIVATED = 0x28
-    UCI_STATUS_ERROR_NUMBER_OF_ACTIVE_RANGING_ROUNDS_EXCEEDED = 0x29
-    UCI_STATUS_ERROR_DL_TDOA_DEVICE_ADDRESS_NOT_MATCHING_IN_REPLY_TIME_LIST = 0x2a
-    UCI_STATUS_DATA_MAX_TX_PSDU_SIZE_EXCEEDED = 0x30
-    UCI_STATUS_DATA_RX_CRC_ERROR = 0x31
-    VENDOR_SPECIFIC_STATUS_CODE_2 = 0xff
-
-    @staticmethod
-    def from_int(v: int) -> Union[int, 'StatusCode']:
-        try:
-            return StatusCode(v)
+            return Status(v)
         except ValueError as exn:
             return v
 
@@ -333,25 +305,13 @@
             raise exn
 
 
-class DeviceConfigId(enum.IntEnum):
-    DEVICE_STATE = 0x0
-    LOW_POWER_MODE = 0x1
-
-    @staticmethod
-    def from_int(v: int) -> Union[int, 'DeviceConfigId']:
-        try:
-            return DeviceConfigId(v)
-        except ValueError as exn:
-            raise exn
-
-
 class AppConfigTlvType(enum.IntEnum):
     DEVICE_TYPE = 0x0
     RANGING_ROUND_USAGE = 0x1
     STS_CONFIG = 0x2
     MULTI_NODE_MODE = 0x3
     CHANNEL_NUMBER = 0x4
-    NO_OF_CONTROLEE = 0x5
+    NUMBER_OF_CONTROLEES = 0x5
     DEVICE_MAC_ADDRESS = 0x6
     DST_MAC_ADDRESS = 0x7
     SLOT_DURATION = 0x8
@@ -360,9 +320,9 @@
     MAC_FCS_TYPE = 0xb
     RANGING_ROUND_CONTROL = 0xc
     AOA_RESULT_REQ = 0xd
-    RNG_DATA_NTF = 0xe
-    RNG_DATA_NTF_PROXIMITY_NEAR = 0xf
-    RNG_DATA_NTF_PROXIMITY_FAR = 0x10
+    SESSION_INFO_NTF_CONFIG = 0xe
+    NEAR_PROXIMITY_CONFIG = 0xf
+    FAR_PROXIMITY_CONFIG = 0x10
     DEVICE_ROLE = 0x11
     RFRAME_CONFIG = 0x12
     RSSI_REPORTING = 0x13
@@ -374,13 +334,11 @@
     DATA_REPETITION_COUNT = 0x19
     RANGING_TIME_STRUCT = 0x1a
     SLOTS_PER_RR = 0x1b
-    TX_ADAPTIVE_PAYLOAD_POWER = 0x1c
-    RNG_DATA_NTF_AOA_BOUND = 0x1d
-    RESPONDER_SLOT_INDEX = 0x1e
+    AOA_BOUND_CONFIG = 0x1d
     PRF_MODE = 0x1f
     CAP_SIZE_RANGE = 0x20
     TX_JITTER_WINDOW_SIZE = 0x21
-    SCHEDULED_MODE = 0x22
+    SCHEDULE_MODE = 0x22
     KEY_ROTATION = 0x23
     KEY_ROTATION_RATE = 0x24
     SESSION_PRIORITY = 0x25
@@ -397,13 +355,7 @@
     SUB_SESSION_ID = 0x30
     BPRF_PHR_DATA_RATE = 0x31
     MAX_NUMBER_OF_MEASUREMENTS = 0x32
-    UL_TDOA_TX_INTERVAL = 0x33
-    UL_TDOA_RANDOM_WINDOW = 0x34
     STS_LENGTH = 0x35
-    SUSPEND_RANGING_ROUNDS = 0x36
-    UL_TDOA_NTF_REPORT_CONFIG = 0x37
-    UL_TDOA_DEVICE_ID = 0x38
-    UL_TDOA_TX_TIMESTAMP = 0x39
     MIN_FRAMES_PER_RR = 0x3a
     MTU_SIZE = 0x3b
     INTER_FRAME_INTERVAL = 0x3c
@@ -413,10 +365,10 @@
     DL_TDOA_ANCHOR_CFO = 0x40
     DL_TDOA_ANCHOR_LOCATION = 0x41
     DL_TDOA_TX_ACTIVE_RANGING_ROUNDS = 0x42
-    DL_TDOA_BLOCK_STRIDING = 0x43
+    DL_TDOA_BLOCK_SKIPPING = 0x43
     DL_TDOA_TIME_REFERENCE_ANCHOR = 0x44
     SESSION_KEY = 0x45
-    SUBSESSION_KEY = 0x46
+    SUB_SESSION_KEY = 0x46
     SESSION_DATA_TRANSFER_STATUS_NTF_CONFIG = 0x47
     SESSION_TIME_BASE = 0x48
     DL_TDOA_RESPONDER_TOF = 0x49
@@ -433,15 +385,434 @@
             return v
 
 
-class FrameReportTlvType(enum.IntEnum):
-    RSSI = 0x0
-    AOA = 0x1
-    CIR = 0x2
+class DeviceType(enum.IntEnum):
+    CONTROLEE = 0x0
+    CONTROLLER = 0x1
 
     @staticmethod
-    def from_int(v: int) -> Union[int, 'FrameReportTlvType']:
+    def from_int(v: int) -> Union[int, 'DeviceType']:
         try:
-            return FrameReportTlvType(v)
+            return DeviceType(v)
+        except ValueError as exn:
+            raise exn
+
+
+class RangingRoundUsage(enum.IntEnum):
+    SS_TWR_DEFERRED_MODE = 0x1
+    DS_TWR_DEFERRED_MODE = 0x2
+    SS_TWR_NON_DEFERRED_MODE = 0x3
+    DS_TWR_NON_DEFERRED_MODE = 0x4
+    ON_WAY_RANGING_DL_TDOA = 0x5
+    OWR_AOA_MEASUREMENT = 0x6
+    ESS_TWR_NON_DEFERRED = 0x7
+    ADS_TWR_NON_DEFERRED = 0x8
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'RangingRoundUsage']:
+        try:
+            return RangingRoundUsage(v)
+        except ValueError as exn:
+            raise exn
+
+
+class StsConfig(enum.IntEnum):
+    STATIC = 0x0
+    DYNAMIC = 0x1
+    DYNAMIC_FOR_RESPONDER_SUB_SESSION_KEY = 0x2
+    PROVISIONED = 0x3
+    PROVISIONED_FOR_RESPONDER_SUB_SESSION_KEY = 0x4
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'StsConfig']:
+        try:
+            return StsConfig(v)
+        except ValueError as exn:
+            raise exn
+
+
+class MultiNodeMode(enum.IntEnum):
+    ONE_TO_ONE = 0x0
+    ONE_TO_MANY = 0x1
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'MultiNodeMode']:
+        try:
+            return MultiNodeMode(v)
+        except ValueError as exn:
+            raise exn
+
+
+class ChannelNumber(enum.IntEnum):
+    CHANNEL_NUMBER_5 = 0x5
+    CHANNEL_NUMBER_6 = 0x6
+    CHANNEL_NUMBER_8 = 0x8
+    CHANNEL_NUMBER_9 = 0x9
+    CHANNEL_NUMBER_10 = 0xa
+    CHANNEL_NUMBER_12 = 0xc
+    CHANNEL_NUMBER_13 = 0xd
+    CHANNEL_NUMBER_14 = 0xe
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'ChannelNumber']:
+        try:
+            return ChannelNumber(v)
+        except ValueError as exn:
+            raise exn
+
+
+class MacFcsType(enum.IntEnum):
+    CRC_16 = 0x0
+    CRC_32 = 0x1
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'MacFcsType']:
+        try:
+            return MacFcsType(v)
+        except ValueError as exn:
+            raise exn
+
+
+@dataclass
+class RangingRoundControl(Packet):
+    rrrm: int = field(kw_only=True, default=0)
+    rcp: int = field(kw_only=True, default=0)
+    mrp: int = field(kw_only=True, default=0)
+    mrm: int = field(kw_only=True, default=0)
+
+    def __post_init__(self):
+        pass
+
+    @staticmethod
+    def parse(span: bytes) -> Tuple['RangingRoundControl', bytes]:
+        fields = {'payload': None}
+        if len(span) < 1:
+            raise Exception('Invalid packet size')
+        fields['rrrm'] = (span[0] >> 0) & 0x1
+        if (span[0] >> 1) & 0x1 != 0x1:
+            raise Exception('Unexpected fixed field value')
+        fields['rcp'] = (span[0] >> 2) & 0x1
+        fields['mrp'] = (span[0] >> 6) & 0x1
+        fields['mrm'] = (span[0] >> 7) & 0x1
+        span = span[1:]
+        return RangingRoundControl(**fields), span
+
+    def serialize(self, payload: bytes = None) -> bytes:
+        _span = bytearray()
+        if self.rrrm > 1:
+            print(f"Invalid value for field RangingRoundControl::rrrm: {self.rrrm} > 1; the value will be truncated")
+            self.rrrm &= 1
+        if self.rcp > 1:
+            print(f"Invalid value for field RangingRoundControl::rcp: {self.rcp} > 1; the value will be truncated")
+            self.rcp &= 1
+        if self.mrp > 1:
+            print(f"Invalid value for field RangingRoundControl::mrp: {self.mrp} > 1; the value will be truncated")
+            self.mrp &= 1
+        if self.mrm > 1:
+            print(f"Invalid value for field RangingRoundControl::mrm: {self.mrm} > 1; the value will be truncated")
+            self.mrm &= 1
+        _value = (
+            (self.rrrm << 0) |
+            (1 << 1) |
+            (self.rcp << 2) |
+            (self.mrp << 6) |
+            (self.mrm << 7)
+        )
+        _span.append(_value)
+        return bytes(_span)
+
+    @property
+    def size(self) -> int:
+        return 1
+
+class AoaResultReq(enum.IntEnum):
+    AOA_DISABLED = 0x0
+    AOA_ENABLED = 0x1
+    AOA_ENABLED_AZIMUTH_ONLY = 0x2
+    AOA_ENABLED_ELEVATION_ONLY = 0x3
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'AoaResultReq']:
+        try:
+            return AoaResultReq(v)
+        except ValueError as exn:
+            raise exn
+
+
+class SessionInfoNtfConfig(enum.IntEnum):
+    DISABLE = 0x0
+    ENABLE = 0x1
+    ENABLE_PROXIMITY_TRIGGER = 0x2
+    ENABLE_AOA_TRIGGER = 0x3
+    ENABLE_PROXIMITY_AOA_TRIGGER = 0x4
+    ENABLE_PROXIMITY_EDGE_TRIGGER = 0x5
+    ENABLE_AOA_EDGE_TRIGGER = 0x6
+    ENABLE_PROXIMITY_AOA_EDGE_TRIGGER = 0x7
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'SessionInfoNtfConfig']:
+        try:
+            return SessionInfoNtfConfig(v)
+        except ValueError as exn:
+            raise exn
+
+
+class DeviceRole(enum.IntEnum):
+    RESPONDER = 0x0
+    INITIATOR = 0x1
+    ADVERTISER = 0x5
+    OBSERVER = 0x6
+    DT_ANCHOR = 0x7
+    DT_TAG = 0x8
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'DeviceRole']:
+        try:
+            return DeviceRole(v)
+        except ValueError as exn:
+            raise exn
+
+
+class RframeConfig(enum.IntEnum):
+    SP0 = 0x0
+    SP1 = 0x1
+    SP3 = 0x3
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'RframeConfig']:
+        try:
+            return RframeConfig(v)
+        except ValueError as exn:
+            raise exn
+
+
+class RssiReporting(enum.IntEnum):
+    DISABLE = 0x0
+    ENABLE = 0x1
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'RssiReporting']:
+        try:
+            return RssiReporting(v)
+        except ValueError as exn:
+            raise exn
+
+
+class PsduDataRate(enum.IntEnum):
+    DATA_RATE_6M81 = 0x0
+    DATA_RATE_7M80 = 0x1
+    DATA_RATE_27M2 = 0x2
+    DATA_RATE_31M2 = 0x3
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'PsduDataRate']:
+        try:
+            return PsduDataRate(v)
+        except ValueError as exn:
+            raise exn
+
+
+class PreambleDuration(enum.IntEnum):
+    DURATION_32_SYMBOLS = 0x0
+    DURATION_64_SYMBOLS = 0x1
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'PreambleDuration']:
+        try:
+            return PreambleDuration(v)
+        except ValueError as exn:
+            raise exn
+
+
+class LinkLayerMode(enum.IntEnum):
+    BYPASS_MODE = 0x0
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'LinkLayerMode']:
+        try:
+            return LinkLayerMode(v)
+        except ValueError as exn:
+            raise exn
+
+
+class RangingTimeStruct(enum.IntEnum):
+    BLOCK_BASED_SCHEDULING = 0x1
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'RangingTimeStruct']:
+        try:
+            return RangingTimeStruct(v)
+        except ValueError as exn:
+            raise exn
+
+
+class PrfMode(enum.IntEnum):
+    BPRF_MODE = 0x0
+    HPRF_MODE_124M8 = 0x1
+    HPRF_MODE_249M6 = 0x2
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'PrfMode']:
+        try:
+            return PrfMode(v)
+        except ValueError as exn:
+            raise exn
+
+
+class ScheduleMode(enum.IntEnum):
+    CONTENTION_BASED = 0x0
+    TIME_SCHEDULED = 0x1
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'ScheduleMode']:
+        try:
+            return ScheduleMode(v)
+        except ValueError as exn:
+            raise exn
+
+
+class KeyRotation(enum.IntEnum):
+    DISABLE = 0x0
+    ENABLE = 0x1
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'KeyRotation']:
+        try:
+            return KeyRotation(v)
+        except ValueError as exn:
+            raise exn
+
+
+class MacAddressMode(enum.IntEnum):
+    MODE_0 = 0x0
+    MODE_1 = 0x1
+    MODE_2 = 0x2
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'MacAddressMode']:
+        try:
+            return MacAddressMode(v)
+        except ValueError as exn:
+            raise exn
+
+
+class HoppingMode(enum.IntEnum):
+    DISABLE = 0x0
+    ENABLE = 0x1
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'HoppingMode']:
+        try:
+            return HoppingMode(v)
+        except ValueError as exn:
+            raise exn
+
+
+@dataclass
+class ResultReportConfig(Packet):
+    tof: int = field(kw_only=True, default=0)
+    aoa_azimuth: int = field(kw_only=True, default=0)
+    aoa_elevation: int = field(kw_only=True, default=0)
+    aoa_fom: int = field(kw_only=True, default=0)
+
+    def __post_init__(self):
+        pass
+
+    @staticmethod
+    def parse(span: bytes) -> Tuple['ResultReportConfig', bytes]:
+        fields = {'payload': None}
+        if len(span) < 1:
+            raise Exception('Invalid packet size')
+        fields['tof'] = (span[0] >> 0) & 0x1
+        fields['aoa_azimuth'] = (span[0] >> 1) & 0x1
+        fields['aoa_elevation'] = (span[0] >> 2) & 0x1
+        fields['aoa_fom'] = (span[0] >> 3) & 0x1
+        span = span[1:]
+        return ResultReportConfig(**fields), span
+
+    def serialize(self, payload: bytes = None) -> bytes:
+        _span = bytearray()
+        if self.tof > 1:
+            print(f"Invalid value for field ResultReportConfig::tof: {self.tof} > 1; the value will be truncated")
+            self.tof &= 1
+        if self.aoa_azimuth > 1:
+            print(f"Invalid value for field ResultReportConfig::aoa_azimuth: {self.aoa_azimuth} > 1; the value will be truncated")
+            self.aoa_azimuth &= 1
+        if self.aoa_elevation > 1:
+            print(f"Invalid value for field ResultReportConfig::aoa_elevation: {self.aoa_elevation} > 1; the value will be truncated")
+            self.aoa_elevation &= 1
+        if self.aoa_fom > 1:
+            print(f"Invalid value for field ResultReportConfig::aoa_fom: {self.aoa_fom} > 1; the value will be truncated")
+            self.aoa_fom &= 1
+        _value = (
+            (self.tof << 0) |
+            (self.aoa_azimuth << 1) |
+            (self.aoa_elevation << 2) |
+            (self.aoa_fom << 3)
+        )
+        _span.append(_value)
+        return bytes(_span)
+
+    @property
+    def size(self) -> int:
+        return 1
+
+class BprfPhrDataRate(enum.IntEnum):
+    DATA_RATE_850K = 0x0
+    DATA_RATE_6M81 = 0x1
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'BprfPhrDataRate']:
+        try:
+            return BprfPhrDataRate(v)
+        except ValueError as exn:
+            raise exn
+
+
+class StsLength(enum.IntEnum):
+    LENGTH_32_SYMBOLS = 0x0
+    LENGTH_64_SYMBOLS = 0x1
+    LENGTH_128_SYMBOLS = 0x2
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'StsLength']:
+        try:
+            return StsLength(v)
+        except ValueError as exn:
+            raise exn
+
+
+class DlTdoaRangingMethod(enum.IntEnum):
+    SS_TWR = 0x0
+    DS_TWR = 0x1
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'DlTdoaRangingMethod']:
+        try:
+            return DlTdoaRangingMethod(v)
+        except ValueError as exn:
+            raise exn
+
+
+class DlTdoaAnchorCfo(enum.IntEnum):
+    ANCHOR_CFO_NOT_INCLUDED = 0x0
+    ANCHOR_CFO_INCLUDED = 0x1
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'DlTdoaAnchorCfo']:
+        try:
+            return DlTdoaAnchorCfo(v)
+        except ValueError as exn:
+            raise exn
+
+
+class SessionDataTransferStatusNtfConfig(enum.IntEnum):
+    DISABLE = 0x0
+    ENABLE = 0x1
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'SessionDataTransferStatusNtfConfig']:
+        try:
+            return SessionDataTransferStatusNtfConfig(v)
         except ValueError as exn:
             raise exn
 
@@ -571,20 +942,21 @@
             return v
 
 
-class MulticastUpdateStatusCode(enum.IntEnum):
-    STATUS_OK_MULTICAST_LIST_UPDATE = 0x0
-    STATUS_ERROR_MULTICAST_LIST_FULL = 0x1
-    STATUS_ERROR_KEY_FETCH_FAIL = 0x2
-    STATUS_ERROR_SUB_SESSION_ID_NOT_FOUND = 0x3
-    STATUS_ERROR_SUB_SESSION_KEY_NOT_FOUND = 0x5
-    STATUS_ERROR_SUB_SESSION_KEY_NOT_APPLICABLE = 0x6
-    STATUS_ERROR_SESSION_KEY_NOT_FOUND = 0x7
-    STATUS_ERROR_ADDRESS_ALREADY_PRESENT = 0x8
+class MulticastUpdateStatus(enum.IntEnum):
+    OK_MULTICAST_LIST_UPDATE = 0x0
+    ERROR_MULTICAST_LIST_FULL = 0x1
+    ERROR_KEY_FETCH_FAIL = 0x2
+    ERROR_SUB_SESSION_ID_NOT_FOUND = 0x3
+    ERROR_SUB_SESSION_KEY_NOT_FOUND = 0x4
+    ERROR_SUB_SESSION_KEY_NOT_APPLICABLE = 0x5
+    ERROR_SESSION_KEY_NOT_FOUND = 0x6
+    ERROR_ADDRESS_NOT_FOUND = 0x7
+    ERROR_ADDRESS_ALREADY_PRESENT = 0x8
 
     @staticmethod
-    def from_int(v: int) -> Union[int, 'MulticastUpdateStatusCode']:
+    def from_int(v: int) -> Union[int, 'MulticastUpdateStatus']:
         try:
-            return MulticastUpdateStatusCode(v)
+            return MulticastUpdateStatus(v)
         except ValueError as exn:
             raise exn
 
@@ -619,22 +991,6 @@
             raise exn
 
 
-class MessageType(enum.IntEnum):
-    DATA = 0x0
-    COMMAND = 0x1
-    RESPONSE = 0x2
-    NOTIFICATION = 0x3
-    RESERVED_FOR_TESTING_1 = 0x4
-    RESERVED_FOR_TESTING_2 = 0x5
-
-    @staticmethod
-    def from_int(v: int) -> Union[int, 'MessageType']:
-        try:
-            return MessageType(v)
-        except ValueError as exn:
-            raise exn
-
-
 @dataclass
 class CommonPacketHeader(Packet):
     pbf: PacketBoundaryFlag = field(kw_only=True, default=PacketBoundaryFlag.COMPLETE)
@@ -748,7 +1104,6 @@
 class ControlPacket(Packet):
     gid: GroupId = field(kw_only=True, default=GroupId.CORE)
     mt: MessageType = field(kw_only=True, default=MessageType.DATA)
-    opcode: int = field(kw_only=True, default=0)
 
     def __post_init__(self):
         pass
@@ -756,210 +1111,28 @@
     @staticmethod
     def parse(span: bytes) -> Tuple['ControlPacket', bytes]:
         fields = {'payload': None}
-        if len(span) < 4:
+        if len(span) < 1:
             raise Exception('Invalid packet size')
         fields['gid'] = GroupId.from_int((span[0] >> 0) & 0xf)
         fields['mt'] = MessageType.from_int((span[0] >> 5) & 0x7)
-        fields['opcode'] = (span[1] >> 0) & 0x3f
-        value_ = int.from_bytes(span[2:4], byteorder='little')
-        span = span[4:]
+        span = span[1:]
         payload = span
         span = bytes([])
         fields['payload'] = payload
         try:
-            return DeviceResetCmd.parse(fields.copy(), payload)
+            return CorePacket.parse(fields.copy(), payload)
         except Exception as exn:
             pass
         try:
-            return GetDeviceInfoCmd.parse(fields.copy(), payload)
+            return SessionConfigPacket.parse(fields.copy(), payload)
         except Exception as exn:
             pass
         try:
-            return GetCapsInfoCmd.parse(fields.copy(), payload)
+            return SessionControlPacket.parse(fields.copy(), payload)
         except Exception as exn:
             pass
         try:
-            return SetConfigCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return GetConfigCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return CoreQueryTimeStampCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionInitCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionDeinitCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionSetAppConfigCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionGetAppConfigCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionGetCountCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionGetStateCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionUpdateDtTagRangingRoundsCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionUpdateControllerMulticastListCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionSetHybridConfigCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionQueryMaxDataSizeCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionControlCommand.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return AndroidGetPowerStatsCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return AndroidSetCountryCodeCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return DeviceResetRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return GetDeviceInfoRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return GetCapsInfoRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SetConfigRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return GetConfigRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return CoreQueryTimeStampRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionInitRsp_V2.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionInitRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionDeinitRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionSetAppConfigRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionGetAppConfigRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionGetCountRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionGetStateRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionUpdateDtTagRangingRoundsRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionSetHybridConfigRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionUpdateControllerMulticastListRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionQueryMaxDataSizeRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionStartRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionStopRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionGetRangingCountRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return AndroidGetPowerStatsRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return AndroidSetCountryCodeRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return DeviceStatusNtf.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return GenericError.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionStatusNtf.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionUpdateControllerMulticastListNtf.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return DataCreditNtf.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return DataTransferStatusNtf.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionInfoNtf.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return AndroidRangeDiagnosticsNtf.parse(fields.copy(), payload)
+            return AndroidPacket.parse(fields.copy(), payload)
         except Exception as exn:
             pass
         return ControlPacket(**fields), span
@@ -971,17 +1144,12 @@
             (self.mt << 5)
         )
         _span.append(_value)
-        if self.opcode > 63:
-            print(f"Invalid value for field ControlPacket::opcode: {self.opcode} > 63; the value will be truncated")
-            self.opcode &= 63
-        _span.append((self.opcode << 0))
-        _span.extend([0] * 2)
         _span.extend(payload or self.payload or [])
         return bytes(_span)
 
     @property
     def size(self) -> int:
-        return len(self.payload) + 4
+        return len(self.payload) + 1
 
 @dataclass
 class DataPacket(Packet):
@@ -1089,7 +1257,7 @@
 @dataclass
 class DataMessageRcv(DataPacket):
     session_handle: int = field(kw_only=True, default=0)
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+    status: Status = field(kw_only=True, default=Status.OK)
     source_address: int = field(kw_only=True, default=0)
     data_sequence_number: int = field(kw_only=True, default=0)
     application_data: bytearray = field(kw_only=True, default_factory=bytearray)
@@ -1106,7 +1274,7 @@
             raise Exception('Invalid packet size')
         value_ = int.from_bytes(span[0:4], byteorder='little')
         fields['session_handle'] = value_
-        fields['status'] = StatusCode.from_int(span[4])
+        fields['status'] = Status.from_int(span[4])
         value_ = int.from_bytes(span[5:13], byteorder='little')
         fields['source_address'] = value_
         value_ = int.from_bytes(span[13:15], byteorder='little')
@@ -1144,37 +1312,70 @@
         return len(self.application_data) * 1 + 17
 
 @dataclass
-class UciCommand(ControlPacket):
-    
+class CorePacket(ControlPacket):
+    oid: CoreOpcodeId = field(kw_only=True, default=CoreOpcodeId.DEVICE_RESET)
 
     def __post_init__(self):
-        self.mt = MessageType.COMMAND
+        self.gid = GroupId.CORE
 
     @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['UciCommand', bytes]:
-        if fields['mt'] != MessageType.COMMAND:
+    def parse(fields: dict, span: bytes) -> Tuple['CorePacket', bytes]:
+        if fields['gid'] != GroupId.CORE:
             raise Exception("Invalid constraint field values")
+        if len(span) < 3:
+            raise Exception('Invalid packet size')
+        fields['oid'] = CoreOpcodeId.from_int((span[0] >> 0) & 0x3f)
+        value_ = int.from_bytes(span[1:3], byteorder='little')
+        span = span[3:]
         payload = span
         span = bytes([])
         fields['payload'] = payload
         try:
-            return DeviceResetCmd.parse(fields.copy(), payload)
+            return CoreDeviceResetCmd.parse(fields.copy(), payload)
         except Exception as exn:
             pass
         try:
-            return GetDeviceInfoCmd.parse(fields.copy(), payload)
+            return CoreDeviceResetRsp.parse(fields.copy(), payload)
         except Exception as exn:
             pass
         try:
-            return GetCapsInfoCmd.parse(fields.copy(), payload)
+            return CoreDeviceStatusNtf.parse(fields.copy(), payload)
         except Exception as exn:
             pass
         try:
-            return SetConfigCmd.parse(fields.copy(), payload)
+            return CoreGetDeviceInfoCmd.parse(fields.copy(), payload)
         except Exception as exn:
             pass
         try:
-            return GetConfigCmd.parse(fields.copy(), payload)
+            return CoreGetDeviceInfoRsp.parse(fields.copy(), payload)
+        except Exception as exn:
+            pass
+        try:
+            return CoreGetCapsInfoCmd.parse(fields.copy(), payload)
+        except Exception as exn:
+            pass
+        try:
+            return CoreGetCapsInfoRsp.parse(fields.copy(), payload)
+        except Exception as exn:
+            pass
+        try:
+            return CoreSetConfigCmd.parse(fields.copy(), payload)
+        except Exception as exn:
+            pass
+        try:
+            return CoreSetConfigRsp.parse(fields.copy(), payload)
+        except Exception as exn:
+            pass
+        try:
+            return CoreGetConfigCmd.parse(fields.copy(), payload)
+        except Exception as exn:
+            pass
+        try:
+            return CoreGetConfigRsp.parse(fields.copy(), payload)
+        except Exception as exn:
+            pass
+        try:
+            return CoreGenericErrorNtf.parse(fields.copy(), payload)
         except Exception as exn:
             pass
         try:
@@ -1182,104 +1383,43 @@
         except Exception as exn:
             pass
         try:
-            return SessionInitCmd.parse(fields.copy(), payload)
+            return CoreQueryTimeStampRsp.parse(fields.copy(), payload)
         except Exception as exn:
             pass
-        try:
-            return SessionDeinitCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionSetAppConfigCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionGetAppConfigCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionGetCountCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionGetStateCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionUpdateDtTagRangingRoundsCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionUpdateControllerMulticastListCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionSetHybridConfigCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionQueryMaxDataSizeCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionControlCommand.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return AndroidGetPowerStatsCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return AndroidSetCountryCodeCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        return UciCommand(**fields), span
+        return CorePacket(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
+        _span.append((self.oid << 0))
+        _span.extend([0] * 2)
         _span.extend(payload or self.payload or [])
         return ControlPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
-        return len(self.payload)
+        return len(self.payload) + 3
 
 @dataclass
-class UciResponse(ControlPacket):
-    
+class SessionConfigPacket(ControlPacket):
+    oid: SessionConfigOpcodeId = field(kw_only=True, default=SessionConfigOpcodeId.INIT)
 
     def __post_init__(self):
-        self.mt = MessageType.RESPONSE
+        self.gid = GroupId.SESSION_CONFIG
 
     @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['UciResponse', bytes]:
-        if fields['mt'] != MessageType.RESPONSE:
+    def parse(fields: dict, span: bytes) -> Tuple['SessionConfigPacket', bytes]:
+        if fields['gid'] != GroupId.SESSION_CONFIG:
             raise Exception("Invalid constraint field values")
+        if len(span) < 3:
+            raise Exception('Invalid packet size')
+        fields['oid'] = SessionConfigOpcodeId.from_int((span[0] >> 0) & 0x3f)
+        value_ = int.from_bytes(span[1:3], byteorder='little')
+        span = span[3:]
         payload = span
         span = bytes([])
         fields['payload'] = payload
         try:
-            return DeviceResetRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return GetDeviceInfoRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return GetCapsInfoRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SetConfigRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return GetConfigRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return CoreQueryTimeStampRsp.parse(fields.copy(), payload)
+            return SessionInitCmd.parse(fields.copy(), payload)
         except Exception as exn:
             pass
         try:
@@ -1291,31 +1431,67 @@
         except Exception as exn:
             pass
         try:
+            return SessionDeinitCmd.parse(fields.copy(), payload)
+        except Exception as exn:
+            pass
+        try:
             return SessionDeinitRsp.parse(fields.copy(), payload)
         except Exception as exn:
             pass
         try:
+            return SessionStatusNtf.parse(fields.copy(), payload)
+        except Exception as exn:
+            pass
+        try:
+            return SessionSetAppConfigCmd.parse(fields.copy(), payload)
+        except Exception as exn:
+            pass
+        try:
             return SessionSetAppConfigRsp.parse(fields.copy(), payload)
         except Exception as exn:
             pass
         try:
+            return SessionGetAppConfigCmd.parse(fields.copy(), payload)
+        except Exception as exn:
+            pass
+        try:
             return SessionGetAppConfigRsp.parse(fields.copy(), payload)
         except Exception as exn:
             pass
         try:
+            return SessionGetCountCmd.parse(fields.copy(), payload)
+        except Exception as exn:
+            pass
+        try:
             return SessionGetCountRsp.parse(fields.copy(), payload)
         except Exception as exn:
             pass
         try:
+            return SessionGetStateCmd.parse(fields.copy(), payload)
+        except Exception as exn:
+            pass
+        try:
             return SessionGetStateRsp.parse(fields.copy(), payload)
         except Exception as exn:
             pass
         try:
+            return SessionUpdateDtAnchorRangingRoundsCmd.parse(fields.copy(), payload)
+        except Exception as exn:
+            pass
+        try:
+            return SessionUpdateDtAnchorRangingRoundsRsp.parse(fields.copy(), payload)
+        except Exception as exn:
+            pass
+        try:
+            return SessionUpdateDtTagRangingRoundsCmd.parse(fields.copy(), payload)
+        except Exception as exn:
+            pass
+        try:
             return SessionUpdateDtTagRangingRoundsRsp.parse(fields.copy(), payload)
         except Exception as exn:
             pass
         try:
-            return SessionSetHybridConfigRsp.parse(fields.copy(), payload)
+            return SessionUpdateControllerMulticastListCmd.parse(fields.copy(), payload)
         except Exception as exn:
             pass
         try:
@@ -1323,7 +1499,59 @@
         except Exception as exn:
             pass
         try:
-            return SessionQueryMaxDataSizeRsp.parse(fields.copy(), payload)
+            return SessionUpdateControllerMulticastListNtf.parse(fields.copy(), payload)
+        except Exception as exn:
+            pass
+        try:
+            return SessionQueryMaxDataSizeInRangingCmd.parse(fields.copy(), payload)
+        except Exception as exn:
+            pass
+        try:
+            return SessionQueryMaxDataSizeInRangingRsp.parse(fields.copy(), payload)
+        except Exception as exn:
+            pass
+        return SessionConfigPacket(**fields), span
+
+    def serialize(self, payload: bytes = None) -> bytes:
+        _span = bytearray()
+        _span.append((self.oid << 0))
+        _span.extend([0] * 2)
+        _span.extend(payload or self.payload or [])
+        return ControlPacket.serialize(self, payload = bytes(_span))
+
+    @property
+    def size(self) -> int:
+        return len(self.payload) + 3
+
+@dataclass
+class SessionControlPacket(ControlPacket):
+    oid: SessionControlOpcodeId = field(kw_only=True, default=SessionControlOpcodeId.START)
+
+    def __post_init__(self):
+        self.gid = GroupId.SESSION_CONTROL
+
+    @staticmethod
+    def parse(fields: dict, span: bytes) -> Tuple['SessionControlPacket', bytes]:
+        if fields['gid'] != GroupId.SESSION_CONTROL:
+            raise Exception("Invalid constraint field values")
+        if len(span) < 3:
+            raise Exception('Invalid packet size')
+        fields['oid'] = SessionControlOpcodeId.from_int((span[0] >> 0) & 0x3f)
+        value_ = int.from_bytes(span[1:3], byteorder='little')
+        span = span[3:]
+        payload = span
+        span = bytes([])
+        fields['payload'] = payload
+        try:
+            return SessionDataCreditNtf.parse(fields.copy(), payload)
+        except Exception as exn:
+            pass
+        try:
+            return SessionDataTransferStatusNtf.parse(fields.copy(), payload)
+        except Exception as exn:
+            pass
+        try:
+            return SessionStartCmd.parse(fields.copy(), payload)
         except Exception as exn:
             pass
         try:
@@ -1331,528 +1559,54 @@
         except Exception as exn:
             pass
         try:
-            return SessionStopRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionGetRangingCountRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return AndroidGetPowerStatsRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return AndroidSetCountryCodeRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        return UciResponse(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return ControlPacket.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class UciNotification(ControlPacket):
-    
-
-    def __post_init__(self):
-        self.mt = MessageType.NOTIFICATION
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['UciNotification', bytes]:
-        if fields['mt'] != MessageType.NOTIFICATION:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        try:
-            return DeviceStatusNtf.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return GenericError.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionStatusNtf.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionUpdateControllerMulticastListNtf.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return DataCreditNtf.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return DataTransferStatusNtf.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
             return SessionInfoNtf.parse(fields.copy(), payload)
         except Exception as exn:
             pass
         try:
-            return AndroidRangeDiagnosticsNtf.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        return UciNotification(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return ControlPacket.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class CoreCommand(UciCommand):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.CORE
-        self.mt = MessageType.COMMAND
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['CoreCommand', bytes]:
-        if fields['gid'] != GroupId.CORE or fields['mt'] != MessageType.COMMAND:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        try:
-            return DeviceResetCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return GetDeviceInfoCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return GetCapsInfoCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SetConfigCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return GetConfigCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return CoreQueryTimeStampCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        return CoreCommand(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciCommand.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class CoreResponse(UciResponse):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.CORE
-        self.mt = MessageType.RESPONSE
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['CoreResponse', bytes]:
-        if fields['gid'] != GroupId.CORE or fields['mt'] != MessageType.RESPONSE:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        try:
-            return DeviceResetRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return GetDeviceInfoRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return GetCapsInfoRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SetConfigRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return GetConfigRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return CoreQueryTimeStampRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        return CoreResponse(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciResponse.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class CoreNotification(UciNotification):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.CORE
-        self.mt = MessageType.NOTIFICATION
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['CoreNotification', bytes]:
-        if fields['gid'] != GroupId.CORE or fields['mt'] != MessageType.NOTIFICATION:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        try:
-            return DeviceStatusNtf.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return GenericError.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        return CoreNotification(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciNotification.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class SessionConfigCommand(UciCommand):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.SESSION_CONFIG
-        self.mt = MessageType.COMMAND
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['SessionConfigCommand', bytes]:
-        if fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.COMMAND:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        try:
-            return SessionInitCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionDeinitCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionSetAppConfigCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionGetAppConfigCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionGetCountCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionGetStateCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionUpdateDtTagRangingRoundsCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionUpdateControllerMulticastListCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionSetHybridConfigCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionQueryMaxDataSizeCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        return SessionConfigCommand(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciCommand.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class SessionConfigResponse(UciResponse):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.SESSION_CONFIG
-        self.mt = MessageType.RESPONSE
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['SessionConfigResponse', bytes]:
-        if fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.RESPONSE:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        try:
-            return SessionInitRsp_V2.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionInitRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionDeinitRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionSetAppConfigRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionGetAppConfigRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionGetCountRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionGetStateRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionUpdateDtTagRangingRoundsRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionSetHybridConfigRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionUpdateControllerMulticastListRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionQueryMaxDataSizeRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        return SessionConfigResponse(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciResponse.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class SessionConfigNotification(UciNotification):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.SESSION_CONFIG
-        self.mt = MessageType.NOTIFICATION
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['SessionConfigNotification', bytes]:
-        if fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.NOTIFICATION:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        try:
-            return SessionStatusNtf.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionUpdateControllerMulticastListNtf.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        return SessionConfigNotification(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciNotification.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class SessionControlCommand(UciCommand):
-    session_id: int = field(kw_only=True, default=0)
-
-    def __post_init__(self):
-        self.gid = GroupId.SESSION_CONTROL
-        self.mt = MessageType.COMMAND
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['SessionControlCommand', bytes]:
-        if fields['gid'] != GroupId.SESSION_CONTROL or fields['mt'] != MessageType.COMMAND:
-            raise Exception("Invalid constraint field values")
-        if len(span) < 4:
-            raise Exception('Invalid packet size')
-        value_ = int.from_bytes(span[0:4], byteorder='little')
-        fields['session_id'] = value_
-        span = span[4:]
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        try:
-            return SessionStartCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
             return SessionStopCmd.parse(fields.copy(), payload)
         except Exception as exn:
             pass
         try:
-            return SessionGetRangingCountCmd.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        return SessionControlCommand(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        if self.session_id > 4294967295:
-            print(f"Invalid value for field SessionControlCommand::session_id: {self.session_id} > 4294967295; the value will be truncated")
-            self.session_id &= 4294967295
-        _span.extend(int.to_bytes((self.session_id << 0), length=4, byteorder='little'))
-        _span.extend(payload or self.payload or [])
-        return UciCommand.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload) + 4
-
-@dataclass
-class SessionControlResponse(UciResponse):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.SESSION_CONTROL
-        self.mt = MessageType.RESPONSE
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['SessionControlResponse', bytes]:
-        if fields['gid'] != GroupId.SESSION_CONTROL or fields['mt'] != MessageType.RESPONSE:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        try:
-            return SessionStartRsp.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
             return SessionStopRsp.parse(fields.copy(), payload)
         except Exception as exn:
             pass
         try:
+            return SessionGetRangingCountCmd.parse(fields.copy(), payload)
+        except Exception as exn:
+            pass
+        try:
             return SessionGetRangingCountRsp.parse(fields.copy(), payload)
         except Exception as exn:
             pass
-        return SessionControlResponse(**fields), span
+        return SessionControlPacket(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
+        _span.append((self.oid << 0))
+        _span.extend([0] * 2)
         _span.extend(payload or self.payload or [])
-        return UciResponse.serialize(self, payload = bytes(_span))
+        return ControlPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
-        return len(self.payload)
+        return len(self.payload) + 3
 
 @dataclass
-class SessionControlNotification(UciNotification):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.SESSION_CONTROL
-        self.mt = MessageType.NOTIFICATION
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['SessionControlNotification', bytes]:
-        if fields['gid'] != GroupId.SESSION_CONTROL or fields['mt'] != MessageType.NOTIFICATION:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        try:
-            return DataCreditNtf.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return DataTransferStatusNtf.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        try:
-            return SessionInfoNtf.parse(fields.copy(), payload)
-        except Exception as exn:
-            pass
-        return SessionControlNotification(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciNotification.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class AndroidCommand(UciCommand):
-    
+class AndroidPacket(ControlPacket):
+    oid: AndroidOpcodeId = field(kw_only=True, default=AndroidOpcodeId.GET_POWER_STATS)
 
     def __post_init__(self):
         self.gid = GroupId.VENDOR_ANDROID
-        self.mt = MessageType.COMMAND
 
     @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['AndroidCommand', bytes]:
-        if fields['gid'] != GroupId.VENDOR_ANDROID or fields['mt'] != MessageType.COMMAND:
+    def parse(fields: dict, span: bytes) -> Tuple['AndroidPacket', bytes]:
+        if fields['gid'] != GroupId.VENDOR_ANDROID:
             raise Exception("Invalid constraint field values")
+        if len(span) < 3:
+            raise Exception('Invalid packet size')
+        fields['oid'] = AndroidOpcodeId.from_int((span[0] >> 0) & 0x3f)
+        value_ = int.from_bytes(span[1:3], byteorder='little')
+        span = span[3:]
         payload = span
         span = bytes([])
         fields['payload'] = payload
@@ -1861,194 +1615,144 @@
         except Exception as exn:
             pass
         try:
-            return AndroidSetCountryCodeCmd.parse(fields.copy(), payload)
+            return AndroidGetPowerStatsRsp.parse(fields.copy(), payload)
         except Exception as exn:
             pass
-        return AndroidCommand(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciCommand.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class AndroidResponse(UciResponse):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.VENDOR_ANDROID
-        self.mt = MessageType.RESPONSE
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['AndroidResponse', bytes]:
-        if fields['gid'] != GroupId.VENDOR_ANDROID or fields['mt'] != MessageType.RESPONSE:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
         try:
-            return AndroidGetPowerStatsRsp.parse(fields.copy(), payload)
+            return AndroidSetCountryCodeCmd.parse(fields.copy(), payload)
         except Exception as exn:
             pass
         try:
             return AndroidSetCountryCodeRsp.parse(fields.copy(), payload)
         except Exception as exn:
             pass
-        return AndroidResponse(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciResponse.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class AndroidNotification(UciNotification):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.VENDOR_ANDROID
-        self.mt = MessageType.NOTIFICATION
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['AndroidNotification', bytes]:
-        if fields['gid'] != GroupId.VENDOR_ANDROID or fields['mt'] != MessageType.NOTIFICATION:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
         try:
             return AndroidRangeDiagnosticsNtf.parse(fields.copy(), payload)
         except Exception as exn:
             pass
-        return AndroidNotification(**fields), span
+        return AndroidPacket(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
+        _span.append((self.oid << 0))
+        _span.extend([0] * 2)
         _span.extend(payload or self.payload or [])
-        return UciNotification.serialize(self, payload = bytes(_span))
+        return ControlPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
-        return len(self.payload)
+        return len(self.payload) + 3
 
 @dataclass
-class DeviceResetCmd(CoreCommand):
+class CoreDeviceResetCmd(CorePacket):
     reset_config: ResetConfig = field(kw_only=True, default=ResetConfig.UWBS_RESET)
 
     def __post_init__(self):
-        self.opcode = 0
-        self.gid = GroupId.CORE
         self.mt = MessageType.COMMAND
+        self.oid = CoreOpcodeId.DEVICE_RESET
+        self.gid = GroupId.CORE
 
     @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['DeviceResetCmd', bytes]:
-        if fields['opcode'] != 0x0 or fields['gid'] != GroupId.CORE or fields['mt'] != MessageType.COMMAND:
+    def parse(fields: dict, span: bytes) -> Tuple['CoreDeviceResetCmd', bytes]:
+        if fields['mt'] != MessageType.COMMAND or fields['oid'] != CoreOpcodeId.DEVICE_RESET or fields['gid'] != GroupId.CORE:
             raise Exception("Invalid constraint field values")
         if len(span) < 1:
             raise Exception('Invalid packet size')
         fields['reset_config'] = ResetConfig.from_int(span[0])
         span = span[1:]
-        return DeviceResetCmd(**fields), span
+        return CoreDeviceResetCmd(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
         _span.append((self.reset_config << 0))
-        return CoreCommand.serialize(self, payload = bytes(_span))
+        return CorePacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 1
 
 @dataclass
-class DeviceResetRsp(CoreResponse):
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+class CoreDeviceResetRsp(CorePacket):
+    status: Status = field(kw_only=True, default=Status.OK)
 
     def __post_init__(self):
-        self.opcode = 0
-        self.gid = GroupId.CORE
         self.mt = MessageType.RESPONSE
+        self.oid = CoreOpcodeId.DEVICE_RESET
+        self.gid = GroupId.CORE
 
     @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['DeviceResetRsp', bytes]:
-        if fields['opcode'] != 0x0 or fields['gid'] != GroupId.CORE or fields['mt'] != MessageType.RESPONSE:
+    def parse(fields: dict, span: bytes) -> Tuple['CoreDeviceResetRsp', bytes]:
+        if fields['mt'] != MessageType.RESPONSE or fields['oid'] != CoreOpcodeId.DEVICE_RESET or fields['gid'] != GroupId.CORE:
             raise Exception("Invalid constraint field values")
         if len(span) < 1:
             raise Exception('Invalid packet size')
-        fields['status'] = StatusCode.from_int(span[0])
+        fields['status'] = Status.from_int(span[0])
         span = span[1:]
-        return DeviceResetRsp(**fields), span
+        return CoreDeviceResetRsp(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
         _span.append((self.status << 0))
-        return CoreResponse.serialize(self, payload = bytes(_span))
+        return CorePacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 1
 
 @dataclass
-class DeviceStatusNtf(CoreNotification):
+class CoreDeviceStatusNtf(CorePacket):
     device_state: DeviceState = field(kw_only=True, default=DeviceState.DEVICE_STATE_READY)
 
     def __post_init__(self):
-        self.opcode = 1
-        self.gid = GroupId.CORE
         self.mt = MessageType.NOTIFICATION
+        self.oid = CoreOpcodeId.DEVICE_STATUS
+        self.gid = GroupId.CORE
 
     @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['DeviceStatusNtf', bytes]:
-        if fields['opcode'] != 0x1 or fields['gid'] != GroupId.CORE or fields['mt'] != MessageType.NOTIFICATION:
+    def parse(fields: dict, span: bytes) -> Tuple['CoreDeviceStatusNtf', bytes]:
+        if fields['mt'] != MessageType.NOTIFICATION or fields['oid'] != CoreOpcodeId.DEVICE_STATUS or fields['gid'] != GroupId.CORE:
             raise Exception("Invalid constraint field values")
         if len(span) < 1:
             raise Exception('Invalid packet size')
         fields['device_state'] = DeviceState.from_int(span[0])
         span = span[1:]
-        return DeviceStatusNtf(**fields), span
+        return CoreDeviceStatusNtf(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
         _span.append((self.device_state << 0))
-        return CoreNotification.serialize(self, payload = bytes(_span))
+        return CorePacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 1
 
 @dataclass
-class GetDeviceInfoCmd(CoreCommand):
+class CoreGetDeviceInfoCmd(CorePacket):
     
 
     def __post_init__(self):
-        self.opcode = 2
-        self.gid = GroupId.CORE
         self.mt = MessageType.COMMAND
+        self.oid = CoreOpcodeId.GET_DEVICE_INFO
+        self.gid = GroupId.CORE
 
     @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['GetDeviceInfoCmd', bytes]:
-        if fields['opcode'] != 0x2 or fields['gid'] != GroupId.CORE or fields['mt'] != MessageType.COMMAND:
+    def parse(fields: dict, span: bytes) -> Tuple['CoreGetDeviceInfoCmd', bytes]:
+        if fields['mt'] != MessageType.COMMAND or fields['oid'] != CoreOpcodeId.GET_DEVICE_INFO or fields['gid'] != GroupId.CORE:
             raise Exception("Invalid constraint field values")
-        return GetDeviceInfoCmd(**fields), span
+        return CoreGetDeviceInfoCmd(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
-        return CoreCommand.serialize(self, payload = bytes(_span))
+        return CorePacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 0
 
 @dataclass
-class GetDeviceInfoRsp(CoreResponse):
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+class CoreGetDeviceInfoRsp(CorePacket):
+    status: Status = field(kw_only=True, default=Status.OK)
     uci_version: int = field(kw_only=True, default=0)
     mac_version: int = field(kw_only=True, default=0)
     phy_version: int = field(kw_only=True, default=0)
@@ -2056,17 +1760,17 @@
     vendor_spec_info: bytearray = field(kw_only=True, default_factory=bytearray)
 
     def __post_init__(self):
-        self.opcode = 2
-        self.gid = GroupId.CORE
         self.mt = MessageType.RESPONSE
+        self.oid = CoreOpcodeId.GET_DEVICE_INFO
+        self.gid = GroupId.CORE
 
     @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['GetDeviceInfoRsp', bytes]:
-        if fields['opcode'] != 0x2 or fields['gid'] != GroupId.CORE or fields['mt'] != MessageType.RESPONSE:
+    def parse(fields: dict, span: bytes) -> Tuple['CoreGetDeviceInfoRsp', bytes]:
+        if fields['mt'] != MessageType.RESPONSE or fields['oid'] != CoreOpcodeId.GET_DEVICE_INFO or fields['gid'] != GroupId.CORE:
             raise Exception("Invalid constraint field values")
         if len(span) < 10:
             raise Exception('Invalid packet size')
-        fields['status'] = StatusCode.from_int(span[0])
+        fields['status'] = Status.from_int(span[0])
         value_ = int.from_bytes(span[1:3], byteorder='little')
         fields['uci_version'] = value_
         value_ = int.from_bytes(span[3:5], byteorder='little')
@@ -2081,56 +1785,56 @@
             raise Exception('Invalid packet size')
         fields['vendor_spec_info'] = list(span[:vendor_spec_info_count])
         span = span[vendor_spec_info_count:]
-        return GetDeviceInfoRsp(**fields), span
+        return CoreGetDeviceInfoRsp(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
         _span.append((self.status << 0))
         if self.uci_version > 65535:
-            print(f"Invalid value for field GetDeviceInfoRsp::uci_version: {self.uci_version} > 65535; the value will be truncated")
+            print(f"Invalid value for field CoreGetDeviceInfoRsp::uci_version: {self.uci_version} > 65535; the value will be truncated")
             self.uci_version &= 65535
         _span.extend(int.to_bytes((self.uci_version << 0), length=2, byteorder='little'))
         if self.mac_version > 65535:
-            print(f"Invalid value for field GetDeviceInfoRsp::mac_version: {self.mac_version} > 65535; the value will be truncated")
+            print(f"Invalid value for field CoreGetDeviceInfoRsp::mac_version: {self.mac_version} > 65535; the value will be truncated")
             self.mac_version &= 65535
         _span.extend(int.to_bytes((self.mac_version << 0), length=2, byteorder='little'))
         if self.phy_version > 65535:
-            print(f"Invalid value for field GetDeviceInfoRsp::phy_version: {self.phy_version} > 65535; the value will be truncated")
+            print(f"Invalid value for field CoreGetDeviceInfoRsp::phy_version: {self.phy_version} > 65535; the value will be truncated")
             self.phy_version &= 65535
         _span.extend(int.to_bytes((self.phy_version << 0), length=2, byteorder='little'))
         if self.uci_test_version > 65535:
-            print(f"Invalid value for field GetDeviceInfoRsp::uci_test_version: {self.uci_test_version} > 65535; the value will be truncated")
+            print(f"Invalid value for field CoreGetDeviceInfoRsp::uci_test_version: {self.uci_test_version} > 65535; the value will be truncated")
             self.uci_test_version &= 65535
         _span.extend(int.to_bytes((self.uci_test_version << 0), length=2, byteorder='little'))
         if len(self.vendor_spec_info) > 255:
-            print(f"Invalid length for field GetDeviceInfoRsp::vendor_spec_info:  {len(self.vendor_spec_info)} > 255; the array will be truncated")
+            print(f"Invalid length for field CoreGetDeviceInfoRsp::vendor_spec_info:  {len(self.vendor_spec_info)} > 255; the array will be truncated")
             del self.vendor_spec_info[255:]
         _span.append((len(self.vendor_spec_info) << 0))
         _span.extend(self.vendor_spec_info)
-        return CoreResponse.serialize(self, payload = bytes(_span))
+        return CorePacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return len(self.vendor_spec_info) * 1 + 10
 
 @dataclass
-class GetCapsInfoCmd(CoreCommand):
+class CoreGetCapsInfoCmd(CorePacket):
     
 
     def __post_init__(self):
-        self.opcode = 3
-        self.gid = GroupId.CORE
         self.mt = MessageType.COMMAND
+        self.oid = CoreOpcodeId.GET_CAPS_INFO
+        self.gid = GroupId.CORE
 
     @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['GetCapsInfoCmd', bytes]:
-        if fields['opcode'] != 0x3 or fields['gid'] != GroupId.CORE or fields['mt'] != MessageType.COMMAND:
+    def parse(fields: dict, span: bytes) -> Tuple['CoreGetCapsInfoCmd', bytes]:
+        if fields['mt'] != MessageType.COMMAND or fields['oid'] != CoreOpcodeId.GET_CAPS_INFO or fields['gid'] != GroupId.CORE:
             raise Exception("Invalid constraint field values")
-        return GetCapsInfoCmd(**fields), span
+        return CoreGetCapsInfoCmd(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
-        return CoreCommand.serialize(self, payload = bytes(_span))
+        return CorePacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
@@ -2173,22 +1877,22 @@
         return len(self.v) * 1 + 2
 
 @dataclass
-class GetCapsInfoRsp(CoreResponse):
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+class CoreGetCapsInfoRsp(CorePacket):
+    status: Status = field(kw_only=True, default=Status.OK)
     tlvs: List[CapTlv] = field(kw_only=True, default_factory=list)
 
     def __post_init__(self):
-        self.opcode = 3
-        self.gid = GroupId.CORE
         self.mt = MessageType.RESPONSE
+        self.oid = CoreOpcodeId.GET_CAPS_INFO
+        self.gid = GroupId.CORE
 
     @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['GetCapsInfoRsp', bytes]:
-        if fields['opcode'] != 0x3 or fields['gid'] != GroupId.CORE or fields['mt'] != MessageType.RESPONSE:
+    def parse(fields: dict, span: bytes) -> Tuple['CoreGetCapsInfoRsp', bytes]:
+        if fields['mt'] != MessageType.RESPONSE or fields['oid'] != CoreOpcodeId.GET_CAPS_INFO or fields['gid'] != GroupId.CORE:
             raise Exception("Invalid constraint field values")
         if len(span) < 2:
             raise Exception('Invalid packet size')
-        fields['status'] = StatusCode.from_int(span[0])
+        fields['status'] = Status.from_int(span[0])
         tlvs_count = span[1]
         span = span[2:]
         tlvs = []
@@ -2196,118 +1900,127 @@
             element, span = CapTlv.parse(span)
             tlvs.append(element)
         fields['tlvs'] = tlvs
-        return GetCapsInfoRsp(**fields), span
+        return CoreGetCapsInfoRsp(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
         _span.append((self.status << 0))
         if len(self.tlvs) > 255:
-            print(f"Invalid length for field GetCapsInfoRsp::tlvs:  {len(self.tlvs)} > 255; the array will be truncated")
+            print(f"Invalid length for field CoreGetCapsInfoRsp::tlvs:  {len(self.tlvs)} > 255; the array will be truncated")
             del self.tlvs[255:]
         _span.append((len(self.tlvs) << 0))
         for _elt in self.tlvs:
             _span.extend(_elt.serialize())
-        return CoreResponse.serialize(self, payload = bytes(_span))
+        return CorePacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return sum([elt.size for elt in self.tlvs]) + 2
 
+class ConfigParameterId(enum.IntEnum):
+    DEVICE_STATE = 0x0
+    LOW_POWER_MODE = 0x1
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'ConfigParameterId']:
+        try:
+            return ConfigParameterId(v)
+        except ValueError as exn:
+            return v
+
+
 @dataclass
-class DeviceConfigTlv(Packet):
-    cfg_id: DeviceConfigId = field(kw_only=True, default=DeviceConfigId.DEVICE_STATE)
-    v: bytearray = field(kw_only=True, default_factory=bytearray)
+class ConfigParameter(Packet):
+    id: ConfigParameterId = field(kw_only=True, default=ConfigParameterId.DEVICE_STATE)
+    value: bytearray = field(kw_only=True, default_factory=bytearray)
 
     def __post_init__(self):
         pass
 
     @staticmethod
-    def parse(span: bytes) -> Tuple['DeviceConfigTlv', bytes]:
+    def parse(span: bytes) -> Tuple['ConfigParameter', bytes]:
         fields = {'payload': None}
         if len(span) < 2:
             raise Exception('Invalid packet size')
-        fields['cfg_id'] = DeviceConfigId.from_int(span[0])
-        v_count = span[1]
+        fields['id'] = ConfigParameterId.from_int(span[0])
+        value_size = span[1]
         span = span[2:]
-        if len(span) < v_count:
+        if len(span) < value_size:
             raise Exception('Invalid packet size')
-        fields['v'] = list(span[:v_count])
-        span = span[v_count:]
-        return DeviceConfigTlv(**fields), span
+        fields['value'] = list(span[:value_size])
+        span = span[value_size:]
+        return ConfigParameter(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
-        _span.append((self.cfg_id << 0))
-        if len(self.v) > 255:
-            print(f"Invalid length for field DeviceConfigTlv::v:  {len(self.v)} > 255; the array will be truncated")
-            del self.v[255:]
-        _span.append((len(self.v) << 0))
-        _span.extend(self.v)
+        _span.append((self.id << 0))
+        _span.append(((len(self.value) * 1) << 0))
+        _span.extend(self.value)
         return bytes(_span)
 
     @property
     def size(self) -> int:
-        return len(self.v) * 1 + 2
+        return len(self.value) * 1 + 2
 
 @dataclass
-class SetConfigCmd(CoreCommand):
-    tlvs: List[DeviceConfigTlv] = field(kw_only=True, default_factory=list)
+class CoreSetConfigCmd(CorePacket):
+    parameters: List[ConfigParameter] = field(kw_only=True, default_factory=list)
 
     def __post_init__(self):
-        self.opcode = 4
-        self.gid = GroupId.CORE
         self.mt = MessageType.COMMAND
+        self.oid = CoreOpcodeId.SET_CONFIG
+        self.gid = GroupId.CORE
 
     @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['SetConfigCmd', bytes]:
-        if fields['opcode'] != 0x4 or fields['gid'] != GroupId.CORE or fields['mt'] != MessageType.COMMAND:
+    def parse(fields: dict, span: bytes) -> Tuple['CoreSetConfigCmd', bytes]:
+        if fields['mt'] != MessageType.COMMAND or fields['oid'] != CoreOpcodeId.SET_CONFIG or fields['gid'] != GroupId.CORE:
             raise Exception("Invalid constraint field values")
         if len(span) < 1:
             raise Exception('Invalid packet size')
-        tlvs_count = span[0]
+        parameters_count = span[0]
         span = span[1:]
-        tlvs = []
-        for n in range(tlvs_count):
-            element, span = DeviceConfigTlv.parse(span)
-            tlvs.append(element)
-        fields['tlvs'] = tlvs
-        return SetConfigCmd(**fields), span
+        parameters = []
+        for n in range(parameters_count):
+            element, span = ConfigParameter.parse(span)
+            parameters.append(element)
+        fields['parameters'] = parameters
+        return CoreSetConfigCmd(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
-        if len(self.tlvs) > 255:
-            print(f"Invalid length for field SetConfigCmd::tlvs:  {len(self.tlvs)} > 255; the array will be truncated")
-            del self.tlvs[255:]
-        _span.append((len(self.tlvs) << 0))
-        for _elt in self.tlvs:
+        if len(self.parameters) > 255:
+            print(f"Invalid length for field CoreSetConfigCmd::parameters:  {len(self.parameters)} > 255; the array will be truncated")
+            del self.parameters[255:]
+        _span.append((len(self.parameters) << 0))
+        for _elt in self.parameters:
             _span.extend(_elt.serialize())
-        return CoreCommand.serialize(self, payload = bytes(_span))
+        return CorePacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
-        return sum([elt.size for elt in self.tlvs]) + 1
+        return sum([elt.size for elt in self.parameters]) + 1
 
 @dataclass
-class DeviceConfigStatus(Packet):
-    cfg_id: DeviceConfigId = field(kw_only=True, default=DeviceConfigId.DEVICE_STATE)
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+class ConfigParameterStatus(Packet):
+    id: ConfigParameterId = field(kw_only=True, default=ConfigParameterId.DEVICE_STATE)
+    status: Status = field(kw_only=True, default=Status.OK)
 
     def __post_init__(self):
         pass
 
     @staticmethod
-    def parse(span: bytes) -> Tuple['DeviceConfigStatus', bytes]:
+    def parse(span: bytes) -> Tuple['ConfigParameterStatus', bytes]:
         fields = {'payload': None}
         if len(span) < 2:
             raise Exception('Invalid packet size')
-        fields['cfg_id'] = DeviceConfigId.from_int(span[0])
-        fields['status'] = StatusCode.from_int(span[1])
+        fields['id'] = ConfigParameterId.from_int(span[0])
+        fields['status'] = Status.from_int(span[1])
         span = span[2:]
-        return DeviceConfigStatus(**fields), span
+        return ConfigParameterStatus(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
-        _span.append((self.cfg_id << 0))
+        _span.append((self.id << 0))
         _span.append((self.status << 0))
         return bytes(_span)
 
@@ -2316,193 +2029,197 @@
         return 2
 
 @dataclass
-class SetConfigRsp(CoreResponse):
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
-    cfg_status: List[DeviceConfigStatus] = field(kw_only=True, default_factory=list)
+class CoreSetConfigRsp(CorePacket):
+    status: Status = field(kw_only=True, default=Status.OK)
+    parameters: List[ConfigParameterStatus] = field(kw_only=True, default_factory=list)
 
     def __post_init__(self):
-        self.opcode = 4
-        self.gid = GroupId.CORE
         self.mt = MessageType.RESPONSE
+        self.oid = CoreOpcodeId.SET_CONFIG
+        self.gid = GroupId.CORE
 
     @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['SetConfigRsp', bytes]:
-        if fields['opcode'] != 0x4 or fields['gid'] != GroupId.CORE or fields['mt'] != MessageType.RESPONSE:
+    def parse(fields: dict, span: bytes) -> Tuple['CoreSetConfigRsp', bytes]:
+        if fields['mt'] != MessageType.RESPONSE or fields['oid'] != CoreOpcodeId.SET_CONFIG or fields['gid'] != GroupId.CORE:
             raise Exception("Invalid constraint field values")
         if len(span) < 2:
             raise Exception('Invalid packet size')
-        fields['status'] = StatusCode.from_int(span[0])
-        cfg_status_count = span[1]
+        fields['status'] = Status.from_int(span[0])
+        parameters_count = span[1]
         span = span[2:]
-        if len(span) < cfg_status_count * 2:
+        if len(span) < parameters_count * 2:
             raise Exception('Invalid packet size')
-        cfg_status = []
-        for n in range(cfg_status_count):
-            cfg_status.append(DeviceConfigStatus.parse_all(span[n * 2:(n + 1) * 2]))
-        fields['cfg_status'] = cfg_status
-        span = span[cfg_status_count * 2:]
-        return SetConfigRsp(**fields), span
+        parameters = []
+        for n in range(parameters_count):
+            parameters.append(ConfigParameterStatus.parse_all(span[n * 2:(n + 1) * 2]))
+        fields['parameters'] = parameters
+        span = span[parameters_count * 2:]
+        return CoreSetConfigRsp(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
         _span.append((self.status << 0))
-        if len(self.cfg_status) > 255:
-            print(f"Invalid length for field SetConfigRsp::cfg_status:  {len(self.cfg_status)} > 255; the array will be truncated")
-            del self.cfg_status[255:]
-        _span.append((len(self.cfg_status) << 0))
-        for _elt in self.cfg_status:
+        if len(self.parameters) > 255:
+            print(f"Invalid length for field CoreSetConfigRsp::parameters:  {len(self.parameters)} > 255; the array will be truncated")
+            del self.parameters[255:]
+        _span.append((len(self.parameters) << 0))
+        for _elt in self.parameters:
             _span.extend(_elt.serialize())
-        return CoreResponse.serialize(self, payload = bytes(_span))
+        return CorePacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
-        return sum([elt.size for elt in self.cfg_status]) + 2
+        return sum([elt.size for elt in self.parameters]) + 2
 
 @dataclass
-class GetConfigCmd(CoreCommand):
-    cfg_id: bytearray = field(kw_only=True, default_factory=bytearray)
+class CoreGetConfigCmd(CorePacket):
+    parameter_ids: List[ConfigParameterId] = field(kw_only=True, default_factory=list)
 
     def __post_init__(self):
-        self.opcode = 5
-        self.gid = GroupId.CORE
         self.mt = MessageType.COMMAND
+        self.oid = CoreOpcodeId.GET_CONFIG
+        self.gid = GroupId.CORE
 
     @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['GetConfigCmd', bytes]:
-        if fields['opcode'] != 0x5 or fields['gid'] != GroupId.CORE or fields['mt'] != MessageType.COMMAND:
+    def parse(fields: dict, span: bytes) -> Tuple['CoreGetConfigCmd', bytes]:
+        if fields['mt'] != MessageType.COMMAND or fields['oid'] != CoreOpcodeId.GET_CONFIG or fields['gid'] != GroupId.CORE:
             raise Exception("Invalid constraint field values")
         if len(span) < 1:
             raise Exception('Invalid packet size')
-        cfg_id_count = span[0]
+        parameter_ids_count = span[0]
         span = span[1:]
-        if len(span) < cfg_id_count:
+        if len(span) < parameter_ids_count:
             raise Exception('Invalid packet size')
-        fields['cfg_id'] = list(span[:cfg_id_count])
-        span = span[cfg_id_count:]
-        return GetConfigCmd(**fields), span
+        parameter_ids = []
+        for n in range(parameter_ids_count):
+            parameter_ids.append(ConfigParameterId(int.from_bytes(span[n:n + 1], byteorder='little')))
+        fields['parameter_ids'] = parameter_ids
+        span = span[parameter_ids_count:]
+        return CoreGetConfigCmd(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
-        if len(self.cfg_id) > 255:
-            print(f"Invalid length for field GetConfigCmd::cfg_id:  {len(self.cfg_id)} > 255; the array will be truncated")
-            del self.cfg_id[255:]
-        _span.append((len(self.cfg_id) << 0))
-        _span.extend(self.cfg_id)
-        return CoreCommand.serialize(self, payload = bytes(_span))
+        if len(self.parameter_ids) > 255:
+            print(f"Invalid length for field CoreGetConfigCmd::parameter_ids:  {len(self.parameter_ids)} > 255; the array will be truncated")
+            del self.parameter_ids[255:]
+        _span.append((len(self.parameter_ids) << 0))
+        for _elt in self.parameter_ids:
+            _span.append(_elt)
+        return CorePacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
-        return len(self.cfg_id) * 1 + 1
+        return len(self.parameter_ids) * 8 + 1
 
 @dataclass
-class GetConfigRsp(CoreResponse):
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
-    tlvs: List[DeviceConfigTlv] = field(kw_only=True, default_factory=list)
+class CoreGetConfigRsp(CorePacket):
+    status: Status = field(kw_only=True, default=Status.OK)
+    parameters: List[ConfigParameter] = field(kw_only=True, default_factory=list)
 
     def __post_init__(self):
-        self.opcode = 5
-        self.gid = GroupId.CORE
         self.mt = MessageType.RESPONSE
+        self.oid = CoreOpcodeId.GET_CONFIG
+        self.gid = GroupId.CORE
 
     @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['GetConfigRsp', bytes]:
-        if fields['opcode'] != 0x5 or fields['gid'] != GroupId.CORE or fields['mt'] != MessageType.RESPONSE:
+    def parse(fields: dict, span: bytes) -> Tuple['CoreGetConfigRsp', bytes]:
+        if fields['mt'] != MessageType.RESPONSE or fields['oid'] != CoreOpcodeId.GET_CONFIG or fields['gid'] != GroupId.CORE:
             raise Exception("Invalid constraint field values")
         if len(span) < 2:
             raise Exception('Invalid packet size')
-        fields['status'] = StatusCode.from_int(span[0])
-        tlvs_count = span[1]
+        fields['status'] = Status.from_int(span[0])
+        parameters_count = span[1]
         span = span[2:]
-        tlvs = []
-        for n in range(tlvs_count):
-            element, span = DeviceConfigTlv.parse(span)
-            tlvs.append(element)
-        fields['tlvs'] = tlvs
-        return GetConfigRsp(**fields), span
+        parameters = []
+        for n in range(parameters_count):
+            element, span = ConfigParameter.parse(span)
+            parameters.append(element)
+        fields['parameters'] = parameters
+        return CoreGetConfigRsp(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
         _span.append((self.status << 0))
-        if len(self.tlvs) > 255:
-            print(f"Invalid length for field GetConfigRsp::tlvs:  {len(self.tlvs)} > 255; the array will be truncated")
-            del self.tlvs[255:]
-        _span.append((len(self.tlvs) << 0))
-        for _elt in self.tlvs:
+        if len(self.parameters) > 255:
+            print(f"Invalid length for field CoreGetConfigRsp::parameters:  {len(self.parameters)} > 255; the array will be truncated")
+            del self.parameters[255:]
+        _span.append((len(self.parameters) << 0))
+        for _elt in self.parameters:
             _span.extend(_elt.serialize())
-        return CoreResponse.serialize(self, payload = bytes(_span))
+        return CorePacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
-        return sum([elt.size for elt in self.tlvs]) + 2
+        return sum([elt.size for elt in self.parameters]) + 2
 
 @dataclass
-class GenericError(CoreNotification):
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+class CoreGenericErrorNtf(CorePacket):
+    status: Status = field(kw_only=True, default=Status.OK)
 
     def __post_init__(self):
-        self.opcode = 7
-        self.gid = GroupId.CORE
         self.mt = MessageType.NOTIFICATION
+        self.oid = CoreOpcodeId.GENERIC_ERROR
+        self.gid = GroupId.CORE
 
     @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['GenericError', bytes]:
-        if fields['opcode'] != 0x7 or fields['gid'] != GroupId.CORE or fields['mt'] != MessageType.NOTIFICATION:
+    def parse(fields: dict, span: bytes) -> Tuple['CoreGenericErrorNtf', bytes]:
+        if fields['mt'] != MessageType.NOTIFICATION or fields['oid'] != CoreOpcodeId.GENERIC_ERROR or fields['gid'] != GroupId.CORE:
             raise Exception("Invalid constraint field values")
         if len(span) < 1:
             raise Exception('Invalid packet size')
-        fields['status'] = StatusCode.from_int(span[0])
+        fields['status'] = Status.from_int(span[0])
         span = span[1:]
-        return GenericError(**fields), span
+        return CoreGenericErrorNtf(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
         _span.append((self.status << 0))
-        return CoreNotification.serialize(self, payload = bytes(_span))
+        return CorePacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 1
 
 @dataclass
-class CoreQueryTimeStampCmd(CoreCommand):
+class CoreQueryTimeStampCmd(CorePacket):
     
 
     def __post_init__(self):
-        self.opcode = 8
-        self.gid = GroupId.CORE
         self.mt = MessageType.COMMAND
+        self.oid = CoreOpcodeId.QUERY_UWBS_TIMESTAMP
+        self.gid = GroupId.CORE
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['CoreQueryTimeStampCmd', bytes]:
-        if fields['opcode'] != 0x8 or fields['gid'] != GroupId.CORE or fields['mt'] != MessageType.COMMAND:
+        if fields['mt'] != MessageType.COMMAND or fields['oid'] != CoreOpcodeId.QUERY_UWBS_TIMESTAMP or fields['gid'] != GroupId.CORE:
             raise Exception("Invalid constraint field values")
         return CoreQueryTimeStampCmd(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
-        return CoreCommand.serialize(self, payload = bytes(_span))
+        return CorePacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 0
 
 @dataclass
-class CoreQueryTimeStampRsp(CoreResponse):
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+class CoreQueryTimeStampRsp(CorePacket):
+    status: Status = field(kw_only=True, default=Status.OK)
     timeStamp: int = field(kw_only=True, default=0)
 
     def __post_init__(self):
-        self.opcode = 8
-        self.gid = GroupId.CORE
         self.mt = MessageType.RESPONSE
+        self.oid = CoreOpcodeId.QUERY_UWBS_TIMESTAMP
+        self.gid = GroupId.CORE
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['CoreQueryTimeStampRsp', bytes]:
-        if fields['opcode'] != 0x8 or fields['gid'] != GroupId.CORE or fields['mt'] != MessageType.RESPONSE:
+        if fields['mt'] != MessageType.RESPONSE or fields['oid'] != CoreOpcodeId.QUERY_UWBS_TIMESTAMP or fields['gid'] != GroupId.CORE:
             raise Exception("Invalid constraint field values")
         if len(span) < 9:
             raise Exception('Invalid packet size')
-        fields['status'] = StatusCode.from_int(span[0])
+        fields['status'] = Status.from_int(span[0])
         value_ = int.from_bytes(span[1:9], byteorder='little')
         fields['timeStamp'] = value_
         span = span[9:]
@@ -2515,25 +2232,25 @@
             print(f"Invalid value for field CoreQueryTimeStampRsp::timeStamp: {self.timeStamp} > 18446744073709551615; the value will be truncated")
             self.timeStamp &= 18446744073709551615
         _span.extend(int.to_bytes((self.timeStamp << 0), length=8, byteorder='little'))
-        return CoreResponse.serialize(self, payload = bytes(_span))
+        return CorePacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 9
 
 @dataclass
-class SessionInitCmd(SessionConfigCommand):
+class SessionInitCmd(SessionConfigPacket):
     session_id: int = field(kw_only=True, default=0)
     session_type: SessionType = field(kw_only=True, default=SessionType.FIRA_RANGING_SESSION)
 
     def __post_init__(self):
-        self.opcode = 0
-        self.gid = GroupId.SESSION_CONFIG
         self.mt = MessageType.COMMAND
+        self.oid = SessionConfigOpcodeId.INIT
+        self.gid = GroupId.SESSION_CONFIG
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionInitCmd', bytes]:
-        if fields['opcode'] != 0x0 or fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.COMMAND:
+        if fields['mt'] != MessageType.COMMAND or fields['oid'] != SessionConfigOpcodeId.INIT or fields['gid'] != GroupId.SESSION_CONFIG:
             raise Exception("Invalid constraint field values")
         if len(span) < 5:
             raise Exception('Invalid packet size')
@@ -2550,29 +2267,29 @@
             self.session_id &= 4294967295
         _span.extend(int.to_bytes((self.session_id << 0), length=4, byteorder='little'))
         _span.append((self.session_type << 0))
-        return SessionConfigCommand.serialize(self, payload = bytes(_span))
+        return SessionConfigPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 5
 
 @dataclass
-class SessionInitRsp_V2(SessionConfigResponse):
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+class SessionInitRsp_V2(SessionConfigPacket):
+    status: Status = field(kw_only=True, default=Status.OK)
     session_handle: int = field(kw_only=True, default=0)
 
     def __post_init__(self):
-        self.opcode = 0
-        self.gid = GroupId.SESSION_CONFIG
         self.mt = MessageType.RESPONSE
+        self.oid = SessionConfigOpcodeId.INIT
+        self.gid = GroupId.SESSION_CONFIG
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionInitRsp_V2', bytes]:
-        if fields['opcode'] != 0x0 or fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.RESPONSE:
+        if fields['mt'] != MessageType.RESPONSE or fields['oid'] != SessionConfigOpcodeId.INIT or fields['gid'] != GroupId.SESSION_CONFIG:
             raise Exception("Invalid constraint field values")
         if len(span) < 5:
             raise Exception('Invalid packet size')
-        fields['status'] = StatusCode.from_int(span[0])
+        fields['status'] = Status.from_int(span[0])
         value_ = int.from_bytes(span[1:5], byteorder='little')
         fields['session_handle'] = value_
         span = span[5:]
@@ -2585,52 +2302,52 @@
             print(f"Invalid value for field SessionInitRsp_V2::session_handle: {self.session_handle} > 4294967295; the value will be truncated")
             self.session_handle &= 4294967295
         _span.extend(int.to_bytes((self.session_handle << 0), length=4, byteorder='little'))
-        return SessionConfigResponse.serialize(self, payload = bytes(_span))
+        return SessionConfigPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 5
 
 @dataclass
-class SessionInitRsp(SessionConfigResponse):
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+class SessionInitRsp(SessionConfigPacket):
+    status: Status = field(kw_only=True, default=Status.OK)
 
     def __post_init__(self):
-        self.opcode = 0
-        self.gid = GroupId.SESSION_CONFIG
         self.mt = MessageType.RESPONSE
+        self.oid = SessionConfigOpcodeId.INIT
+        self.gid = GroupId.SESSION_CONFIG
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionInitRsp', bytes]:
-        if fields['opcode'] != 0x0 or fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.RESPONSE:
+        if fields['mt'] != MessageType.RESPONSE or fields['oid'] != SessionConfigOpcodeId.INIT or fields['gid'] != GroupId.SESSION_CONFIG:
             raise Exception("Invalid constraint field values")
         if len(span) < 1:
             raise Exception('Invalid packet size')
-        fields['status'] = StatusCode.from_int(span[0])
+        fields['status'] = Status.from_int(span[0])
         span = span[1:]
         return SessionInitRsp(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
         _span.append((self.status << 0))
-        return SessionConfigResponse.serialize(self, payload = bytes(_span))
+        return SessionConfigPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 1
 
 @dataclass
-class SessionDeinitCmd(SessionConfigCommand):
+class SessionDeinitCmd(SessionConfigPacket):
     session_token: int = field(kw_only=True, default=0)
 
     def __post_init__(self):
-        self.opcode = 1
-        self.gid = GroupId.SESSION_CONFIG
         self.mt = MessageType.COMMAND
+        self.oid = SessionConfigOpcodeId.DEINIT
+        self.gid = GroupId.SESSION_CONFIG
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionDeinitCmd', bytes]:
-        if fields['opcode'] != 0x1 or fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.COMMAND:
+        if fields['mt'] != MessageType.COMMAND or fields['oid'] != SessionConfigOpcodeId.DEINIT or fields['gid'] != GroupId.SESSION_CONFIG:
             raise Exception("Invalid constraint field values")
         if len(span) < 4:
             raise Exception('Invalid packet size')
@@ -2645,54 +2362,54 @@
             print(f"Invalid value for field SessionDeinitCmd::session_token: {self.session_token} > 4294967295; the value will be truncated")
             self.session_token &= 4294967295
         _span.extend(int.to_bytes((self.session_token << 0), length=4, byteorder='little'))
-        return SessionConfigCommand.serialize(self, payload = bytes(_span))
+        return SessionConfigPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 4
 
 @dataclass
-class SessionDeinitRsp(SessionConfigResponse):
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+class SessionDeinitRsp(SessionConfigPacket):
+    status: Status = field(kw_only=True, default=Status.OK)
 
     def __post_init__(self):
-        self.opcode = 1
-        self.gid = GroupId.SESSION_CONFIG
         self.mt = MessageType.RESPONSE
+        self.oid = SessionConfigOpcodeId.DEINIT
+        self.gid = GroupId.SESSION_CONFIG
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionDeinitRsp', bytes]:
-        if fields['opcode'] != 0x1 or fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.RESPONSE:
+        if fields['mt'] != MessageType.RESPONSE or fields['oid'] != SessionConfigOpcodeId.DEINIT or fields['gid'] != GroupId.SESSION_CONFIG:
             raise Exception("Invalid constraint field values")
         if len(span) < 1:
             raise Exception('Invalid packet size')
-        fields['status'] = StatusCode.from_int(span[0])
+        fields['status'] = Status.from_int(span[0])
         span = span[1:]
         return SessionDeinitRsp(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
         _span.append((self.status << 0))
-        return SessionConfigResponse.serialize(self, payload = bytes(_span))
+        return SessionConfigPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 1
 
 @dataclass
-class SessionStatusNtf(SessionConfigNotification):
+class SessionStatusNtf(SessionConfigPacket):
     session_token: int = field(kw_only=True, default=0)
     session_state: SessionState = field(kw_only=True, default=SessionState.SESSION_STATE_INIT)
     reason_code: int = field(kw_only=True, default=0)
 
     def __post_init__(self):
-        self.opcode = 2
-        self.gid = GroupId.SESSION_CONFIG
         self.mt = MessageType.NOTIFICATION
+        self.oid = SessionConfigOpcodeId.STATUS
+        self.gid = GroupId.SESSION_CONFIG
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionStatusNtf', bytes]:
-        if fields['opcode'] != 0x2 or fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.NOTIFICATION:
+        if fields['mt'] != MessageType.NOTIFICATION or fields['oid'] != SessionConfigOpcodeId.STATUS or fields['gid'] != GroupId.SESSION_CONFIG:
             raise Exception("Invalid constraint field values")
         if len(span) < 6:
             raise Exception('Invalid packet size')
@@ -2714,7 +2431,7 @@
             print(f"Invalid value for field SessionStatusNtf::reason_code: {self.reason_code} > 255; the value will be truncated")
             self.reason_code &= 255
         _span.append((self.reason_code << 0))
-        return SessionConfigNotification.serialize(self, payload = bytes(_span))
+        return SessionConfigPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
@@ -2757,18 +2474,18 @@
         return len(self.v) * 1 + 2
 
 @dataclass
-class SessionSetAppConfigCmd(SessionConfigCommand):
+class SessionSetAppConfigCmd(SessionConfigPacket):
     session_token: int = field(kw_only=True, default=0)
     tlvs: List[AppConfigTlv] = field(kw_only=True, default_factory=list)
 
     def __post_init__(self):
-        self.opcode = 3
-        self.gid = GroupId.SESSION_CONFIG
         self.mt = MessageType.COMMAND
+        self.oid = SessionConfigOpcodeId.SET_APP_CONFIG
+        self.gid = GroupId.SESSION_CONFIG
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionSetAppConfigCmd', bytes]:
-        if fields['opcode'] != 0x3 or fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.COMMAND:
+        if fields['mt'] != MessageType.COMMAND or fields['oid'] != SessionConfigOpcodeId.SET_APP_CONFIG or fields['gid'] != GroupId.SESSION_CONFIG:
             raise Exception("Invalid constraint field values")
         if len(span) < 5:
             raise Exception('Invalid packet size')
@@ -2795,7 +2512,7 @@
         _span.append((len(self.tlvs) << 0))
         for _elt in self.tlvs:
             _span.extend(_elt.serialize())
-        return SessionConfigCommand.serialize(self, payload = bytes(_span))
+        return SessionConfigPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
@@ -2804,7 +2521,7 @@
 @dataclass
 class AppConfigStatus(Packet):
     cfg_id: AppConfigTlvType = field(kw_only=True, default=AppConfigTlvType.DEVICE_TYPE)
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+    status: Status = field(kw_only=True, default=Status.OK)
 
     def __post_init__(self):
         pass
@@ -2815,7 +2532,7 @@
         if len(span) < 2:
             raise Exception('Invalid packet size')
         fields['cfg_id'] = AppConfigTlvType.from_int(span[0])
-        fields['status'] = StatusCode.from_int(span[1])
+        fields['status'] = Status.from_int(span[1])
         span = span[2:]
         return AppConfigStatus(**fields), span
 
@@ -2830,22 +2547,22 @@
         return 2
 
 @dataclass
-class SessionSetAppConfigRsp(SessionConfigResponse):
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+class SessionSetAppConfigRsp(SessionConfigPacket):
+    status: Status = field(kw_only=True, default=Status.OK)
     cfg_status: List[AppConfigStatus] = field(kw_only=True, default_factory=list)
 
     def __post_init__(self):
-        self.opcode = 3
-        self.gid = GroupId.SESSION_CONFIG
         self.mt = MessageType.RESPONSE
+        self.oid = SessionConfigOpcodeId.SET_APP_CONFIG
+        self.gid = GroupId.SESSION_CONFIG
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionSetAppConfigRsp', bytes]:
-        if fields['opcode'] != 0x3 or fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.RESPONSE:
+        if fields['mt'] != MessageType.RESPONSE or fields['oid'] != SessionConfigOpcodeId.SET_APP_CONFIG or fields['gid'] != GroupId.SESSION_CONFIG:
             raise Exception("Invalid constraint field values")
         if len(span) < 2:
             raise Exception('Invalid packet size')
-        fields['status'] = StatusCode.from_int(span[0])
+        fields['status'] = Status.from_int(span[0])
         cfg_status_count = span[1]
         span = span[2:]
         if len(span) < cfg_status_count * 2:
@@ -2866,25 +2583,25 @@
         _span.append((len(self.cfg_status) << 0))
         for _elt in self.cfg_status:
             _span.extend(_elt.serialize())
-        return SessionConfigResponse.serialize(self, payload = bytes(_span))
+        return SessionConfigPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return sum([elt.size for elt in self.cfg_status]) + 2
 
 @dataclass
-class SessionGetAppConfigCmd(SessionConfigCommand):
+class SessionGetAppConfigCmd(SessionConfigPacket):
     session_token: int = field(kw_only=True, default=0)
-    app_cfg: bytearray = field(kw_only=True, default_factory=bytearray)
+    app_cfg: List[AppConfigTlvType] = field(kw_only=True, default_factory=list)
 
     def __post_init__(self):
-        self.opcode = 4
-        self.gid = GroupId.SESSION_CONFIG
         self.mt = MessageType.COMMAND
+        self.oid = SessionConfigOpcodeId.GET_APP_CONFIG
+        self.gid = GroupId.SESSION_CONFIG
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionGetAppConfigCmd', bytes]:
-        if fields['opcode'] != 0x4 or fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.COMMAND:
+        if fields['mt'] != MessageType.COMMAND or fields['oid'] != SessionConfigOpcodeId.GET_APP_CONFIG or fields['gid'] != GroupId.SESSION_CONFIG:
             raise Exception("Invalid constraint field values")
         if len(span) < 5:
             raise Exception('Invalid packet size')
@@ -2894,7 +2611,10 @@
         span = span[5:]
         if len(span) < app_cfg_count:
             raise Exception('Invalid packet size')
-        fields['app_cfg'] = list(span[:app_cfg_count])
+        app_cfg = []
+        for n in range(app_cfg_count):
+            app_cfg.append(AppConfigTlvType(int.from_bytes(span[n:n + 1], byteorder='little')))
+        fields['app_cfg'] = app_cfg
         span = span[app_cfg_count:]
         return SessionGetAppConfigCmd(**fields), span
 
@@ -2908,30 +2628,31 @@
             print(f"Invalid length for field SessionGetAppConfigCmd::app_cfg:  {len(self.app_cfg)} > 255; the array will be truncated")
             del self.app_cfg[255:]
         _span.append((len(self.app_cfg) << 0))
-        _span.extend(self.app_cfg)
-        return SessionConfigCommand.serialize(self, payload = bytes(_span))
+        for _elt in self.app_cfg:
+            _span.append(_elt)
+        return SessionConfigPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
-        return len(self.app_cfg) * 1 + 5
+        return len(self.app_cfg) * 8 + 5
 
 @dataclass
-class SessionGetAppConfigRsp(SessionConfigResponse):
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+class SessionGetAppConfigRsp(SessionConfigPacket):
+    status: Status = field(kw_only=True, default=Status.OK)
     tlvs: List[AppConfigTlv] = field(kw_only=True, default_factory=list)
 
     def __post_init__(self):
-        self.opcode = 4
-        self.gid = GroupId.SESSION_CONFIG
         self.mt = MessageType.RESPONSE
+        self.oid = SessionConfigOpcodeId.GET_APP_CONFIG
+        self.gid = GroupId.SESSION_CONFIG
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionGetAppConfigRsp', bytes]:
-        if fields['opcode'] != 0x4 or fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.RESPONSE:
+        if fields['mt'] != MessageType.RESPONSE or fields['oid'] != SessionConfigOpcodeId.GET_APP_CONFIG or fields['gid'] != GroupId.SESSION_CONFIG:
             raise Exception("Invalid constraint field values")
         if len(span) < 2:
             raise Exception('Invalid packet size')
-        fields['status'] = StatusCode.from_int(span[0])
+        fields['status'] = Status.from_int(span[0])
         tlvs_count = span[1]
         span = span[2:]
         tlvs = []
@@ -2950,52 +2671,52 @@
         _span.append((len(self.tlvs) << 0))
         for _elt in self.tlvs:
             _span.extend(_elt.serialize())
-        return SessionConfigResponse.serialize(self, payload = bytes(_span))
+        return SessionConfigPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return sum([elt.size for elt in self.tlvs]) + 2
 
 @dataclass
-class SessionGetCountCmd(SessionConfigCommand):
+class SessionGetCountCmd(SessionConfigPacket):
     
 
     def __post_init__(self):
-        self.opcode = 5
-        self.gid = GroupId.SESSION_CONFIG
         self.mt = MessageType.COMMAND
+        self.oid = SessionConfigOpcodeId.GET_COUNT
+        self.gid = GroupId.SESSION_CONFIG
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionGetCountCmd', bytes]:
-        if fields['opcode'] != 0x5 or fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.COMMAND:
+        if fields['mt'] != MessageType.COMMAND or fields['oid'] != SessionConfigOpcodeId.GET_COUNT or fields['gid'] != GroupId.SESSION_CONFIG:
             raise Exception("Invalid constraint field values")
         return SessionGetCountCmd(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
-        return SessionConfigCommand.serialize(self, payload = bytes(_span))
+        return SessionConfigPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 0
 
 @dataclass
-class SessionGetCountRsp(SessionConfigResponse):
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+class SessionGetCountRsp(SessionConfigPacket):
+    status: Status = field(kw_only=True, default=Status.OK)
     session_count: int = field(kw_only=True, default=0)
 
     def __post_init__(self):
-        self.opcode = 5
-        self.gid = GroupId.SESSION_CONFIG
         self.mt = MessageType.RESPONSE
+        self.oid = SessionConfigOpcodeId.GET_COUNT
+        self.gid = GroupId.SESSION_CONFIG
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionGetCountRsp', bytes]:
-        if fields['opcode'] != 0x5 or fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.RESPONSE:
+        if fields['mt'] != MessageType.RESPONSE or fields['oid'] != SessionConfigOpcodeId.GET_COUNT or fields['gid'] != GroupId.SESSION_CONFIG:
             raise Exception("Invalid constraint field values")
         if len(span) < 2:
             raise Exception('Invalid packet size')
-        fields['status'] = StatusCode.from_int(span[0])
+        fields['status'] = Status.from_int(span[0])
         fields['session_count'] = span[1]
         span = span[2:]
         return SessionGetCountRsp(**fields), span
@@ -3007,24 +2728,24 @@
             print(f"Invalid value for field SessionGetCountRsp::session_count: {self.session_count} > 255; the value will be truncated")
             self.session_count &= 255
         _span.append((self.session_count << 0))
-        return SessionConfigResponse.serialize(self, payload = bytes(_span))
+        return SessionConfigPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 2
 
 @dataclass
-class SessionGetStateCmd(SessionConfigCommand):
+class SessionGetStateCmd(SessionConfigPacket):
     session_token: int = field(kw_only=True, default=0)
 
     def __post_init__(self):
-        self.opcode = 6
-        self.gid = GroupId.SESSION_CONFIG
         self.mt = MessageType.COMMAND
+        self.oid = SessionConfigOpcodeId.GET_STATE
+        self.gid = GroupId.SESSION_CONFIG
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionGetStateCmd', bytes]:
-        if fields['opcode'] != 0x6 or fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.COMMAND:
+        if fields['mt'] != MessageType.COMMAND or fields['oid'] != SessionConfigOpcodeId.GET_STATE or fields['gid'] != GroupId.SESSION_CONFIG:
             raise Exception("Invalid constraint field values")
         if len(span) < 4:
             raise Exception('Invalid packet size')
@@ -3039,29 +2760,29 @@
             print(f"Invalid value for field SessionGetStateCmd::session_token: {self.session_token} > 4294967295; the value will be truncated")
             self.session_token &= 4294967295
         _span.extend(int.to_bytes((self.session_token << 0), length=4, byteorder='little'))
-        return SessionConfigCommand.serialize(self, payload = bytes(_span))
+        return SessionConfigPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 4
 
 @dataclass
-class SessionGetStateRsp(SessionConfigResponse):
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+class SessionGetStateRsp(SessionConfigPacket):
+    status: Status = field(kw_only=True, default=Status.OK)
     session_state: SessionState = field(kw_only=True, default=SessionState.SESSION_STATE_INIT)
 
     def __post_init__(self):
-        self.opcode = 6
-        self.gid = GroupId.SESSION_CONFIG
         self.mt = MessageType.RESPONSE
+        self.oid = SessionConfigOpcodeId.GET_STATE
+        self.gid = GroupId.SESSION_CONFIG
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionGetStateRsp', bytes]:
-        if fields['opcode'] != 0x6 or fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.RESPONSE:
+        if fields['mt'] != MessageType.RESPONSE or fields['oid'] != SessionConfigOpcodeId.GET_STATE or fields['gid'] != GroupId.SESSION_CONFIG:
             raise Exception("Invalid constraint field values")
         if len(span) < 2:
             raise Exception('Invalid packet size')
-        fields['status'] = StatusCode.from_int(span[0])
+        fields['status'] = Status.from_int(span[0])
         fields['session_state'] = SessionState.from_int(span[1])
         span = span[2:]
         return SessionGetStateRsp(**fields), span
@@ -3070,25 +2791,71 @@
         _span = bytearray()
         _span.append((self.status << 0))
         _span.append((self.session_state << 0))
-        return SessionConfigResponse.serialize(self, payload = bytes(_span))
+        return SessionConfigPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 2
 
 @dataclass
-class SessionUpdateDtTagRangingRoundsCmd(SessionConfigCommand):
+class SessionUpdateDtAnchorRangingRoundsCmd(SessionConfigPacket):
+    
+
+    def __post_init__(self):
+        self.mt = MessageType.COMMAND
+        self.oid = SessionConfigOpcodeId.UPDATE_DT_ANCHOR_RANGING_ROUNDS
+        self.gid = GroupId.SESSION_CONFIG
+
+    @staticmethod
+    def parse(fields: dict, span: bytes) -> Tuple['SessionUpdateDtAnchorRangingRoundsCmd', bytes]:
+        if fields['mt'] != MessageType.COMMAND or fields['oid'] != SessionConfigOpcodeId.UPDATE_DT_ANCHOR_RANGING_ROUNDS or fields['gid'] != GroupId.SESSION_CONFIG:
+            raise Exception("Invalid constraint field values")
+        return SessionUpdateDtAnchorRangingRoundsCmd(**fields), span
+
+    def serialize(self, payload: bytes = None) -> bytes:
+        _span = bytearray()
+        return SessionConfigPacket.serialize(self, payload = bytes(_span))
+
+    @property
+    def size(self) -> int:
+        return 0
+
+@dataclass
+class SessionUpdateDtAnchorRangingRoundsRsp(SessionConfigPacket):
+    
+
+    def __post_init__(self):
+        self.mt = MessageType.RESPONSE
+        self.oid = SessionConfigOpcodeId.UPDATE_DT_ANCHOR_RANGING_ROUNDS
+        self.gid = GroupId.SESSION_CONFIG
+
+    @staticmethod
+    def parse(fields: dict, span: bytes) -> Tuple['SessionUpdateDtAnchorRangingRoundsRsp', bytes]:
+        if fields['mt'] != MessageType.RESPONSE or fields['oid'] != SessionConfigOpcodeId.UPDATE_DT_ANCHOR_RANGING_ROUNDS or fields['gid'] != GroupId.SESSION_CONFIG:
+            raise Exception("Invalid constraint field values")
+        return SessionUpdateDtAnchorRangingRoundsRsp(**fields), span
+
+    def serialize(self, payload: bytes = None) -> bytes:
+        _span = bytearray()
+        return SessionConfigPacket.serialize(self, payload = bytes(_span))
+
+    @property
+    def size(self) -> int:
+        return 0
+
+@dataclass
+class SessionUpdateDtTagRangingRoundsCmd(SessionConfigPacket):
     session_token: int = field(kw_only=True, default=0)
     ranging_round_indexes: bytearray = field(kw_only=True, default_factory=bytearray)
 
     def __post_init__(self):
-        self.opcode = 9
-        self.gid = GroupId.SESSION_CONFIG
         self.mt = MessageType.COMMAND
+        self.oid = SessionConfigOpcodeId.UPDATE_DT_TAG_RANGING_ROUNDS
+        self.gid = GroupId.SESSION_CONFIG
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionUpdateDtTagRangingRoundsCmd', bytes]:
-        if fields['opcode'] != 0x9 or fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.COMMAND:
+        if fields['mt'] != MessageType.COMMAND or fields['oid'] != SessionConfigOpcodeId.UPDATE_DT_TAG_RANGING_ROUNDS or fields['gid'] != GroupId.SESSION_CONFIG:
             raise Exception("Invalid constraint field values")
         if len(span) < 5:
             raise Exception('Invalid packet size')
@@ -3113,29 +2880,29 @@
             del self.ranging_round_indexes[255:]
         _span.append((len(self.ranging_round_indexes) << 0))
         _span.extend(self.ranging_round_indexes)
-        return SessionConfigCommand.serialize(self, payload = bytes(_span))
+        return SessionConfigPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return len(self.ranging_round_indexes) * 1 + 5
 
 @dataclass
-class SessionUpdateDtTagRangingRoundsRsp(SessionConfigResponse):
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+class SessionUpdateDtTagRangingRoundsRsp(SessionConfigPacket):
+    status: Status = field(kw_only=True, default=Status.OK)
     ranging_round_indexes: bytearray = field(kw_only=True, default_factory=bytearray)
 
     def __post_init__(self):
-        self.opcode = 9
-        self.gid = GroupId.SESSION_CONFIG
         self.mt = MessageType.RESPONSE
+        self.oid = SessionConfigOpcodeId.UPDATE_DT_TAG_RANGING_ROUNDS
+        self.gid = GroupId.SESSION_CONFIG
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionUpdateDtTagRangingRoundsRsp', bytes]:
-        if fields['opcode'] != 0x9 or fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.RESPONSE:
+        if fields['mt'] != MessageType.RESPONSE or fields['oid'] != SessionConfigOpcodeId.UPDATE_DT_TAG_RANGING_ROUNDS or fields['gid'] != GroupId.SESSION_CONFIG:
             raise Exception("Invalid constraint field values")
         if len(span) < 2:
             raise Exception('Invalid packet size')
-        fields['status'] = StatusCode.from_int(span[0])
+        fields['status'] = Status.from_int(span[0])
         ranging_round_indexes_count = span[1]
         span = span[2:]
         if len(span) < ranging_round_indexes_count:
@@ -3152,7 +2919,7 @@
             del self.ranging_round_indexes[255:]
         _span.append((len(self.ranging_round_indexes) << 0))
         _span.extend(self.ranging_round_indexes)
-        return SessionConfigResponse.serialize(self, payload = bytes(_span))
+        return SessionConfigPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
@@ -3279,7 +3046,7 @@
     ADD_CONTROLEE = 0x0
     REMOVE_CONTROLEE = 0x1
     ADD_CONTROLEE_WITH_SHORT_SUB_SESSION_KEY = 0x2
-    ADD_CONTROLEE_WITH_LONG_SUB_SESSION_KEY = 0x3
+    ADD_CONTROLEE_WITH_EXTENDED_SUB_SESSION_KEY = 0x3
 
     @staticmethod
     def from_int(v: int) -> Union[int, 'UpdateMulticastListAction']:
@@ -3290,18 +3057,18 @@
 
 
 @dataclass
-class SessionUpdateControllerMulticastListCmd(SessionConfigCommand):
+class SessionUpdateControllerMulticastListCmd(SessionConfigPacket):
     session_token: int = field(kw_only=True, default=0)
     action: UpdateMulticastListAction = field(kw_only=True, default=UpdateMulticastListAction.ADD_CONTROLEE)
 
     def __post_init__(self):
-        self.opcode = 7
-        self.gid = GroupId.SESSION_CONFIG
         self.mt = MessageType.COMMAND
+        self.oid = SessionConfigOpcodeId.UPDATE_CONTROLLER_MULTICAST_LIST
+        self.gid = GroupId.SESSION_CONFIG
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionUpdateControllerMulticastListCmd', bytes]:
-        if fields['opcode'] != 0x7 or fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.COMMAND:
+        if fields['mt'] != MessageType.COMMAND or fields['oid'] != SessionConfigOpcodeId.UPDATE_CONTROLLER_MULTICAST_LIST or fields['gid'] != GroupId.SESSION_CONFIG:
             raise Exception("Invalid constraint field values")
         if len(span) < 5:
             raise Exception('Invalid packet size')
@@ -3322,139 +3089,13 @@
         _span.extend(int.to_bytes((self.session_token << 0), length=4, byteorder='little'))
         _span.append((self.action << 0))
         _span.extend(payload or self.payload or [])
-        return SessionConfigCommand.serialize(self, payload = bytes(_span))
+        return SessionConfigPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return len(self.payload) + 5
 
 @dataclass
-class PhaseList(Packet):
-    session_token: int = field(kw_only=True, default=0)
-    start_slot_index: int = field(kw_only=True, default=0)
-    end_slot_index: int = field(kw_only=True, default=0)
-
-    def __post_init__(self):
-        pass
-
-    @staticmethod
-    def parse(span: bytes) -> Tuple['PhaseList', bytes]:
-        fields = {'payload': None}
-        if len(span) < 8:
-            raise Exception('Invalid packet size')
-        value_ = int.from_bytes(span[0:4], byteorder='little')
-        fields['session_token'] = value_
-        value_ = int.from_bytes(span[4:6], byteorder='little')
-        fields['start_slot_index'] = value_
-        value_ = int.from_bytes(span[6:8], byteorder='little')
-        fields['end_slot_index'] = value_
-        span = span[8:]
-        return PhaseList(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        if self.session_token > 4294967295:
-            print(f"Invalid value for field PhaseList::session_token: {self.session_token} > 4294967295; the value will be truncated")
-            self.session_token &= 4294967295
-        _span.extend(int.to_bytes((self.session_token << 0), length=4, byteorder='little'))
-        if self.start_slot_index > 65535:
-            print(f"Invalid value for field PhaseList::start_slot_index: {self.start_slot_index} > 65535; the value will be truncated")
-            self.start_slot_index &= 65535
-        _span.extend(int.to_bytes((self.start_slot_index << 0), length=2, byteorder='little'))
-        if self.end_slot_index > 65535:
-            print(f"Invalid value for field PhaseList::end_slot_index: {self.end_slot_index} > 65535; the value will be truncated")
-            self.end_slot_index &= 65535
-        _span.extend(int.to_bytes((self.end_slot_index << 0), length=2, byteorder='little'))
-        return bytes(_span)
-
-    @property
-    def size(self) -> int:
-        return 8
-
-@dataclass
-class SessionSetHybridConfigCmd(SessionConfigCommand):
-    session_token: int = field(kw_only=True, default=0)
-    number_of_phases: int = field(kw_only=True, default=0)
-    update_time: bytearray = field(kw_only=True, default_factory=bytearray)
-    phase_list: List[PhaseList] = field(kw_only=True, default_factory=list)
-
-    def __post_init__(self):
-        self.opcode = 12
-        self.gid = GroupId.SESSION_CONFIG
-        self.mt = MessageType.COMMAND
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['SessionSetHybridConfigCmd', bytes]:
-        if fields['opcode'] != 0xc or fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.COMMAND:
-            raise Exception("Invalid constraint field values")
-        if len(span) < 5:
-            raise Exception('Invalid packet size')
-        value_ = int.from_bytes(span[0:4], byteorder='little')
-        fields['session_token'] = value_
-        fields['number_of_phases'] = span[4]
-        span = span[5:]
-        if len(span) < 8:
-            raise Exception('Invalid packet size')
-        fields['update_time'] = list(span[:8])
-        span = span[8:]
-        if len(span) % 8 != 0:
-            raise Exception('Array size is not a multiple of the element size')
-        phase_list_count = int(len(span) / 8)
-        phase_list = []
-        for n in range(phase_list_count):
-            phase_list.append(PhaseList.parse_all(span[n * 8:(n + 1) * 8]))
-        fields['phase_list'] = phase_list
-        span = bytes()
-        return SessionSetHybridConfigCmd(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        if self.session_token > 4294967295:
-            print(f"Invalid value for field SessionSetHybridConfigCmd::session_token: {self.session_token} > 4294967295; the value will be truncated")
-            self.session_token &= 4294967295
-        _span.extend(int.to_bytes((self.session_token << 0), length=4, byteorder='little'))
-        if self.number_of_phases > 255:
-            print(f"Invalid value for field SessionSetHybridConfigCmd::number_of_phases: {self.number_of_phases} > 255; the value will be truncated")
-            self.number_of_phases &= 255
-        _span.append((self.number_of_phases << 0))
-        _span.extend(self.update_time)
-        for _elt in self.phase_list:
-            _span.extend(_elt.serialize())
-        return SessionConfigCommand.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return sum([elt.size for elt in self.phase_list]) + 13
-
-@dataclass
-class SessionSetHybridConfigRsp(SessionConfigResponse):
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
-
-    def __post_init__(self):
-        self.opcode = 12
-        self.gid = GroupId.SESSION_CONFIG
-        self.mt = MessageType.RESPONSE
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['SessionSetHybridConfigRsp', bytes]:
-        if fields['opcode'] != 0xc or fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.RESPONSE:
-            raise Exception("Invalid constraint field values")
-        if len(span) < 1:
-            raise Exception('Invalid packet size')
-        fields['status'] = StatusCode.from_int(span[0])
-        span = span[1:]
-        return SessionSetHybridConfigRsp(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.append((self.status << 0))
-        return SessionConfigResponse.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return 1
-
-@dataclass
 class SessionUpdateControllerMulticastListCmdPayload(Packet):
     controlees: List[Controlee] = field(kw_only=True, default_factory=list)
 
@@ -3566,28 +3207,28 @@
         return sum([elt.size for elt in self.controlees]) + 1
 
 @dataclass
-class SessionUpdateControllerMulticastListRsp(SessionConfigResponse):
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+class SessionUpdateControllerMulticastListRsp(SessionConfigPacket):
+    status: Status = field(kw_only=True, default=Status.OK)
 
     def __post_init__(self):
-        self.opcode = 7
-        self.gid = GroupId.SESSION_CONFIG
         self.mt = MessageType.RESPONSE
+        self.oid = SessionConfigOpcodeId.UPDATE_CONTROLLER_MULTICAST_LIST
+        self.gid = GroupId.SESSION_CONFIG
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionUpdateControllerMulticastListRsp', bytes]:
-        if fields['opcode'] != 0x7 or fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.RESPONSE:
+        if fields['mt'] != MessageType.RESPONSE or fields['oid'] != SessionConfigOpcodeId.UPDATE_CONTROLLER_MULTICAST_LIST or fields['gid'] != GroupId.SESSION_CONFIG:
             raise Exception("Invalid constraint field values")
         if len(span) < 1:
             raise Exception('Invalid packet size')
-        fields['status'] = StatusCode.from_int(span[0])
+        fields['status'] = Status.from_int(span[0])
         span = span[1:]
         return SessionUpdateControllerMulticastListRsp(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
         _span.append((self.status << 0))
-        return SessionConfigResponse.serialize(self, payload = bytes(_span))
+        return SessionConfigPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
@@ -3597,7 +3238,7 @@
 class ControleeStatus(Packet):
     mac_address: bytearray = field(kw_only=True, default_factory=bytearray)
     subsession_id: int = field(kw_only=True, default=0)
-    status: MulticastUpdateStatusCode = field(kw_only=True, default=MulticastUpdateStatusCode.STATUS_OK_MULTICAST_LIST_UPDATE)
+    status: MulticastUpdateStatus = field(kw_only=True, default=MulticastUpdateStatus.OK_MULTICAST_LIST_UPDATE)
 
     def __post_init__(self):
         pass
@@ -3613,7 +3254,7 @@
             raise Exception('Invalid packet size')
         value_ = int.from_bytes(span[0:4], byteorder='little')
         fields['subsession_id'] = value_
-        fields['status'] = MulticastUpdateStatusCode.from_int(span[4])
+        fields['status'] = MulticastUpdateStatus.from_int(span[4])
         span = span[5:]
         return ControleeStatus(**fields), span
 
@@ -3632,19 +3273,19 @@
         return 7
 
 @dataclass
-class SessionUpdateControllerMulticastListNtf(SessionConfigNotification):
+class SessionUpdateControllerMulticastListNtf(SessionConfigPacket):
     session_token: int = field(kw_only=True, default=0)
     remaining_multicast_list_size: int = field(kw_only=True, default=0)
     controlee_status: List[ControleeStatus] = field(kw_only=True, default_factory=list)
 
     def __post_init__(self):
-        self.opcode = 7
-        self.gid = GroupId.SESSION_CONFIG
         self.mt = MessageType.NOTIFICATION
+        self.oid = SessionConfigOpcodeId.UPDATE_CONTROLLER_MULTICAST_LIST
+        self.gid = GroupId.SESSION_CONFIG
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionUpdateControllerMulticastListNtf', bytes]:
-        if fields['opcode'] != 0x7 or fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.NOTIFICATION:
+        if fields['mt'] != MessageType.NOTIFICATION or fields['oid'] != SessionConfigOpcodeId.UPDATE_CONTROLLER_MULTICAST_LIST or fields['gid'] != GroupId.SESSION_CONFIG:
             raise Exception("Invalid constraint field values")
         if len(span) < 6:
             raise Exception('Invalid packet size')
@@ -3678,25 +3319,25 @@
         _span.append((len(self.controlee_status) << 0))
         for _elt in self.controlee_status:
             _span.extend(_elt.serialize())
-        return SessionConfigNotification.serialize(self, payload = bytes(_span))
+        return SessionConfigPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return sum([elt.size for elt in self.controlee_status]) + 6
 
 @dataclass
-class DataCreditNtf(SessionControlNotification):
+class SessionDataCreditNtf(SessionControlPacket):
     session_token: int = field(kw_only=True, default=0)
     credit_availability: CreditAvailability = field(kw_only=True, default=CreditAvailability.CREDIT_NOT_AVAILABLE)
 
     def __post_init__(self):
-        self.opcode = 4
-        self.gid = GroupId.SESSION_CONTROL
         self.mt = MessageType.NOTIFICATION
+        self.oid = SessionControlOpcodeId.DATA_CREDIT
+        self.gid = GroupId.SESSION_CONTROL
 
     @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['DataCreditNtf', bytes]:
-        if fields['opcode'] != 0x4 or fields['gid'] != GroupId.SESSION_CONTROL or fields['mt'] != MessageType.NOTIFICATION:
+    def parse(fields: dict, span: bytes) -> Tuple['SessionDataCreditNtf', bytes]:
+        if fields['mt'] != MessageType.NOTIFICATION or fields['oid'] != SessionControlOpcodeId.DATA_CREDIT or fields['gid'] != GroupId.SESSION_CONTROL:
             raise Exception("Invalid constraint field values")
         if len(span) < 5:
             raise Exception('Invalid packet size')
@@ -3704,36 +3345,36 @@
         fields['session_token'] = value_
         fields['credit_availability'] = CreditAvailability.from_int(span[4])
         span = span[5:]
-        return DataCreditNtf(**fields), span
+        return SessionDataCreditNtf(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
         if self.session_token > 4294967295:
-            print(f"Invalid value for field DataCreditNtf::session_token: {self.session_token} > 4294967295; the value will be truncated")
+            print(f"Invalid value for field SessionDataCreditNtf::session_token: {self.session_token} > 4294967295; the value will be truncated")
             self.session_token &= 4294967295
         _span.extend(int.to_bytes((self.session_token << 0), length=4, byteorder='little'))
         _span.append((self.credit_availability << 0))
-        return SessionControlNotification.serialize(self, payload = bytes(_span))
+        return SessionControlPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 5
 
 @dataclass
-class DataTransferStatusNtf(SessionControlNotification):
+class SessionDataTransferStatusNtf(SessionControlPacket):
     session_token: int = field(kw_only=True, default=0)
     uci_sequence_number: int = field(kw_only=True, default=0)
     status: DataTransferNtfStatusCode = field(kw_only=True, default=DataTransferNtfStatusCode.UCI_DATA_TRANSFER_STATUS_REPETITION_OK)
     tx_count: int = field(kw_only=True, default=0)
 
     def __post_init__(self):
-        self.opcode = 5
-        self.gid = GroupId.SESSION_CONTROL
         self.mt = MessageType.NOTIFICATION
+        self.oid = SessionControlOpcodeId.DATA_TRANSFER_STATUS
+        self.gid = GroupId.SESSION_CONTROL
 
     @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['DataTransferStatusNtf', bytes]:
-        if fields['opcode'] != 0x5 or fields['gid'] != GroupId.SESSION_CONTROL or fields['mt'] != MessageType.NOTIFICATION:
+    def parse(fields: dict, span: bytes) -> Tuple['SessionDataTransferStatusNtf', bytes]:
+        if fields['mt'] != MessageType.NOTIFICATION or fields['oid'] != SessionControlOpcodeId.DATA_TRANSFER_STATUS or fields['gid'] != GroupId.SESSION_CONTROL:
             raise Exception("Invalid constraint field values")
         if len(span) < 7:
             raise Exception('Invalid packet size')
@@ -3743,74 +3384,74 @@
         fields['status'] = DataTransferNtfStatusCode.from_int(span[5])
         fields['tx_count'] = span[6]
         span = span[7:]
-        return DataTransferStatusNtf(**fields), span
+        return SessionDataTransferStatusNtf(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
         if self.session_token > 4294967295:
-            print(f"Invalid value for field DataTransferStatusNtf::session_token: {self.session_token} > 4294967295; the value will be truncated")
+            print(f"Invalid value for field SessionDataTransferStatusNtf::session_token: {self.session_token} > 4294967295; the value will be truncated")
             self.session_token &= 4294967295
         _span.extend(int.to_bytes((self.session_token << 0), length=4, byteorder='little'))
         if self.uci_sequence_number > 255:
-            print(f"Invalid value for field DataTransferStatusNtf::uci_sequence_number: {self.uci_sequence_number} > 255; the value will be truncated")
+            print(f"Invalid value for field SessionDataTransferStatusNtf::uci_sequence_number: {self.uci_sequence_number} > 255; the value will be truncated")
             self.uci_sequence_number &= 255
         _span.append((self.uci_sequence_number << 0))
         _span.append((self.status << 0))
         if self.tx_count > 255:
-            print(f"Invalid value for field DataTransferStatusNtf::tx_count: {self.tx_count} > 255; the value will be truncated")
+            print(f"Invalid value for field SessionDataTransferStatusNtf::tx_count: {self.tx_count} > 255; the value will be truncated")
             self.tx_count &= 255
         _span.append((self.tx_count << 0))
-        return SessionControlNotification.serialize(self, payload = bytes(_span))
+        return SessionControlPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 7
 
 @dataclass
-class SessionQueryMaxDataSizeCmd(SessionConfigCommand):
+class SessionQueryMaxDataSizeInRangingCmd(SessionConfigPacket):
     session_token: int = field(kw_only=True, default=0)
 
     def __post_init__(self):
-        self.opcode = 11
-        self.gid = GroupId.SESSION_CONFIG
         self.mt = MessageType.COMMAND
+        self.oid = SessionConfigOpcodeId.QUERY_DATA_SIZE_IN_RANGING
+        self.gid = GroupId.SESSION_CONFIG
 
     @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['SessionQueryMaxDataSizeCmd', bytes]:
-        if fields['opcode'] != 0xb or fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.COMMAND:
+    def parse(fields: dict, span: bytes) -> Tuple['SessionQueryMaxDataSizeInRangingCmd', bytes]:
+        if fields['mt'] != MessageType.COMMAND or fields['oid'] != SessionConfigOpcodeId.QUERY_DATA_SIZE_IN_RANGING or fields['gid'] != GroupId.SESSION_CONFIG:
             raise Exception("Invalid constraint field values")
         if len(span) < 4:
             raise Exception('Invalid packet size')
         value_ = int.from_bytes(span[0:4], byteorder='little')
         fields['session_token'] = value_
         span = span[4:]
-        return SessionQueryMaxDataSizeCmd(**fields), span
+        return SessionQueryMaxDataSizeInRangingCmd(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
         if self.session_token > 4294967295:
-            print(f"Invalid value for field SessionQueryMaxDataSizeCmd::session_token: {self.session_token} > 4294967295; the value will be truncated")
+            print(f"Invalid value for field SessionQueryMaxDataSizeInRangingCmd::session_token: {self.session_token} > 4294967295; the value will be truncated")
             self.session_token &= 4294967295
         _span.extend(int.to_bytes((self.session_token << 0), length=4, byteorder='little'))
-        return SessionConfigCommand.serialize(self, payload = bytes(_span))
+        return SessionConfigPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 4
 
 @dataclass
-class SessionQueryMaxDataSizeRsp(SessionConfigResponse):
+class SessionQueryMaxDataSizeInRangingRsp(SessionConfigPacket):
     session_token: int = field(kw_only=True, default=0)
     max_data_size: int = field(kw_only=True, default=0)
 
     def __post_init__(self):
-        self.opcode = 11
-        self.gid = GroupId.SESSION_CONFIG
         self.mt = MessageType.RESPONSE
+        self.oid = SessionConfigOpcodeId.QUERY_DATA_SIZE_IN_RANGING
+        self.gid = GroupId.SESSION_CONFIG
 
     @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['SessionQueryMaxDataSizeRsp', bytes]:
-        if fields['opcode'] != 0xb or fields['gid'] != GroupId.SESSION_CONFIG or fields['mt'] != MessageType.RESPONSE:
+    def parse(fields: dict, span: bytes) -> Tuple['SessionQueryMaxDataSizeInRangingRsp', bytes]:
+        if fields['mt'] != MessageType.RESPONSE or fields['oid'] != SessionConfigOpcodeId.QUERY_DATA_SIZE_IN_RANGING or fields['gid'] != GroupId.SESSION_CONFIG:
             raise Exception("Invalid constraint field values")
         if len(span) < 6:
             raise Exception('Invalid packet size')
@@ -3819,70 +3460,79 @@
         value_ = int.from_bytes(span[4:6], byteorder='little')
         fields['max_data_size'] = value_
         span = span[6:]
-        return SessionQueryMaxDataSizeRsp(**fields), span
+        return SessionQueryMaxDataSizeInRangingRsp(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
         if self.session_token > 4294967295:
-            print(f"Invalid value for field SessionQueryMaxDataSizeRsp::session_token: {self.session_token} > 4294967295; the value will be truncated")
+            print(f"Invalid value for field SessionQueryMaxDataSizeInRangingRsp::session_token: {self.session_token} > 4294967295; the value will be truncated")
             self.session_token &= 4294967295
         _span.extend(int.to_bytes((self.session_token << 0), length=4, byteorder='little'))
         if self.max_data_size > 65535:
-            print(f"Invalid value for field SessionQueryMaxDataSizeRsp::max_data_size: {self.max_data_size} > 65535; the value will be truncated")
+            print(f"Invalid value for field SessionQueryMaxDataSizeInRangingRsp::max_data_size: {self.max_data_size} > 65535; the value will be truncated")
             self.max_data_size &= 65535
         _span.extend(int.to_bytes((self.max_data_size << 0), length=2, byteorder='little'))
-        return SessionConfigResponse.serialize(self, payload = bytes(_span))
+        return SessionConfigPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 6
 
 @dataclass
-class SessionStartCmd(SessionControlCommand):
-    
+class SessionStartCmd(SessionControlPacket):
+    session_id: int = field(kw_only=True, default=0)
 
     def __post_init__(self):
-        self.opcode = 0
-        self.gid = GroupId.SESSION_CONTROL
         self.mt = MessageType.COMMAND
+        self.oid = SessionControlOpcodeId.START
+        self.gid = GroupId.SESSION_CONTROL
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionStartCmd', bytes]:
-        if fields['opcode'] != 0x0 or fields['gid'] != GroupId.SESSION_CONTROL or fields['mt'] != MessageType.COMMAND:
+        if fields['mt'] != MessageType.COMMAND or fields['oid'] != SessionControlOpcodeId.START or fields['gid'] != GroupId.SESSION_CONTROL:
             raise Exception("Invalid constraint field values")
+        if len(span) < 4:
+            raise Exception('Invalid packet size')
+        value_ = int.from_bytes(span[0:4], byteorder='little')
+        fields['session_id'] = value_
+        span = span[4:]
         return SessionStartCmd(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
-        return SessionControlCommand.serialize(self, payload = bytes(_span))
+        if self.session_id > 4294967295:
+            print(f"Invalid value for field SessionStartCmd::session_id: {self.session_id} > 4294967295; the value will be truncated")
+            self.session_id &= 4294967295
+        _span.extend(int.to_bytes((self.session_id << 0), length=4, byteorder='little'))
+        return SessionControlPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
-        return 0
+        return 4
 
 @dataclass
-class SessionStartRsp(SessionControlResponse):
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+class SessionStartRsp(SessionControlPacket):
+    status: Status = field(kw_only=True, default=Status.OK)
 
     def __post_init__(self):
-        self.opcode = 0
-        self.gid = GroupId.SESSION_CONTROL
         self.mt = MessageType.RESPONSE
+        self.oid = SessionControlOpcodeId.START
+        self.gid = GroupId.SESSION_CONTROL
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionStartRsp', bytes]:
-        if fields['opcode'] != 0x0 or fields['gid'] != GroupId.SESSION_CONTROL or fields['mt'] != MessageType.RESPONSE:
+        if fields['mt'] != MessageType.RESPONSE or fields['oid'] != SessionControlOpcodeId.START or fields['gid'] != GroupId.SESSION_CONTROL:
             raise Exception("Invalid constraint field values")
         if len(span) < 1:
             raise Exception('Invalid packet size')
-        fields['status'] = StatusCode.from_int(span[0])
+        fields['status'] = Status.from_int(span[0])
         span = span[1:]
         return SessionStartRsp(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
         _span.append((self.status << 0))
-        return SessionControlResponse.serialize(self, payload = bytes(_span))
+        return SessionControlPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
@@ -3891,7 +3541,7 @@
 @dataclass
 class ShortAddressTwoWayRangingMeasurement(Packet):
     mac_address: int = field(kw_only=True, default=0)
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+    status: Status = field(kw_only=True, default=Status.OK)
     nlos: int = field(kw_only=True, default=0)
     distance: int = field(kw_only=True, default=0)
     aoa_azimuth: int = field(kw_only=True, default=0)
@@ -3915,7 +3565,7 @@
             raise Exception('Invalid packet size')
         value_ = int.from_bytes(span[0:2], byteorder='little')
         fields['mac_address'] = value_
-        fields['status'] = StatusCode.from_int(span[2])
+        fields['status'] = Status.from_int(span[2])
         fields['nlos'] = span[3]
         value_ = int.from_bytes(span[4:6], byteorder='little')
         fields['distance'] = value_
@@ -4004,7 +3654,7 @@
 @dataclass
 class ExtendedAddressTwoWayRangingMeasurement(Packet):
     mac_address: int = field(kw_only=True, default=0)
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+    status: Status = field(kw_only=True, default=Status.OK)
     nlos: int = field(kw_only=True, default=0)
     distance: int = field(kw_only=True, default=0)
     aoa_azimuth: int = field(kw_only=True, default=0)
@@ -4028,7 +3678,7 @@
             raise Exception('Invalid packet size')
         value_ = int.from_bytes(span[0:8], byteorder='little')
         fields['mac_address'] = value_
-        fields['status'] = StatusCode.from_int(span[8])
+        fields['status'] = Status.from_int(span[8])
         fields['nlos'] = span[9]
         value_ = int.from_bytes(span[10:12], byteorder='little')
         fields['distance'] = value_
@@ -4115,7 +3765,7 @@
 @dataclass
 class ShortAddressOwrAoaRangingMeasurement(Packet):
     mac_address: int = field(kw_only=True, default=0)
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+    status: Status = field(kw_only=True, default=Status.OK)
     nlos: int = field(kw_only=True, default=0)
     frame_sequence_number: int = field(kw_only=True, default=0)
     block_index: int = field(kw_only=True, default=0)
@@ -4134,7 +3784,7 @@
             raise Exception('Invalid packet size')
         value_ = int.from_bytes(span[0:2], byteorder='little')
         fields['mac_address'] = value_
-        fields['status'] = StatusCode.from_int(span[2])
+        fields['status'] = Status.from_int(span[2])
         fields['nlos'] = span[3]
         fields['frame_sequence_number'] = span[4]
         value_ = int.from_bytes(span[5:7], byteorder='little')
@@ -4192,7 +3842,7 @@
 @dataclass
 class ExtendedAddressOwrAoaRangingMeasurement(Packet):
     mac_address: int = field(kw_only=True, default=0)
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+    status: Status = field(kw_only=True, default=Status.OK)
     nlos: int = field(kw_only=True, default=0)
     frame_sequence_number: int = field(kw_only=True, default=0)
     block_index: int = field(kw_only=True, default=0)
@@ -4211,7 +3861,7 @@
             raise Exception('Invalid packet size')
         value_ = int.from_bytes(span[0:8], byteorder='little')
         fields['mac_address'] = value_
-        fields['status'] = StatusCode.from_int(span[8])
+        fields['status'] = Status.from_int(span[8])
         fields['nlos'] = span[9]
         fields['frame_sequence_number'] = span[10]
         value_ = int.from_bytes(span[11:13], byteorder='little')
@@ -4281,7 +3931,7 @@
 
 
 @dataclass
-class SessionInfoNtf(SessionControlNotification):
+class SessionInfoNtf(SessionControlPacket):
     sequence_number: int = field(kw_only=True, default=0)
     session_token: int = field(kw_only=True, default=0)
     rcr_indicator: int = field(kw_only=True, default=0)
@@ -4290,13 +3940,13 @@
     mac_address_indicator: MacAddressIndicator = field(kw_only=True, default=MacAddressIndicator.SHORT_ADDRESS)
 
     def __post_init__(self):
-        self.opcode = 0
-        self.gid = GroupId.SESSION_CONTROL
         self.mt = MessageType.NOTIFICATION
+        self.oid = SessionControlOpcodeId.START
+        self.gid = GroupId.SESSION_CONTROL
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionInfoNtf', bytes]:
-        if fields['opcode'] != 0x0 or fields['gid'] != GroupId.SESSION_CONTROL or fields['mt'] != MessageType.NOTIFICATION:
+        if fields['mt'] != MessageType.NOTIFICATION or fields['oid'] != SessionControlOpcodeId.START or fields['gid'] != GroupId.SESSION_CONTROL:
             raise Exception("Invalid constraint field values")
         if len(span) < 24:
             raise Exception('Invalid packet size')
@@ -4363,7 +4013,7 @@
         _span.append((self.mac_address_indicator << 0))
         _span.extend([0] * 8)
         _span.extend(payload or self.payload or [])
-        return SessionControlNotification.serialize(self, payload = bytes(_span))
+        return SessionControlPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
@@ -4377,13 +4027,13 @@
     def __post_init__(self):
         self.ranging_measurement_type = RangingMeasurementType.TWO_WAY
         self.mac_address_indicator = MacAddressIndicator.SHORT_ADDRESS
-        self.opcode = 0
-        self.gid = GroupId.SESSION_CONTROL
         self.mt = MessageType.NOTIFICATION
+        self.oid = SessionControlOpcodeId.START
+        self.gid = GroupId.SESSION_CONTROL
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['ShortMacTwoWaySessionInfoNtf', bytes]:
-        if fields['ranging_measurement_type'] != RangingMeasurementType.TWO_WAY or fields['mac_address_indicator'] != MacAddressIndicator.SHORT_ADDRESS or fields['opcode'] != 0x0 or fields['gid'] != GroupId.SESSION_CONTROL or fields['mt'] != MessageType.NOTIFICATION:
+        if fields['ranging_measurement_type'] != RangingMeasurementType.TWO_WAY or fields['mac_address_indicator'] != MacAddressIndicator.SHORT_ADDRESS or fields['mt'] != MessageType.NOTIFICATION or fields['oid'] != SessionControlOpcodeId.START or fields['gid'] != GroupId.SESSION_CONTROL:
             raise Exception("Invalid constraint field values")
         if len(span) < 1:
             raise Exception('Invalid packet size')
@@ -4426,13 +4076,13 @@
     def __post_init__(self):
         self.ranging_measurement_type = RangingMeasurementType.TWO_WAY
         self.mac_address_indicator = MacAddressIndicator.EXTENDED_ADDRESS
-        self.opcode = 0
-        self.gid = GroupId.SESSION_CONTROL
         self.mt = MessageType.NOTIFICATION
+        self.oid = SessionControlOpcodeId.START
+        self.gid = GroupId.SESSION_CONTROL
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['ExtendedMacTwoWaySessionInfoNtf', bytes]:
-        if fields['ranging_measurement_type'] != RangingMeasurementType.TWO_WAY or fields['mac_address_indicator'] != MacAddressIndicator.EXTENDED_ADDRESS or fields['opcode'] != 0x0 or fields['gid'] != GroupId.SESSION_CONTROL or fields['mt'] != MessageType.NOTIFICATION:
+        if fields['ranging_measurement_type'] != RangingMeasurementType.TWO_WAY or fields['mac_address_indicator'] != MacAddressIndicator.EXTENDED_ADDRESS or fields['mt'] != MessageType.NOTIFICATION or fields['oid'] != SessionControlOpcodeId.START or fields['gid'] != GroupId.SESSION_CONTROL:
             raise Exception("Invalid constraint field values")
         if len(span) < 1:
             raise Exception('Invalid packet size')
@@ -4475,13 +4125,13 @@
     def __post_init__(self):
         self.ranging_measurement_type = RangingMeasurementType.DL_TDOA
         self.mac_address_indicator = MacAddressIndicator.SHORT_ADDRESS
-        self.opcode = 0
-        self.gid = GroupId.SESSION_CONTROL
         self.mt = MessageType.NOTIFICATION
+        self.oid = SessionControlOpcodeId.START
+        self.gid = GroupId.SESSION_CONTROL
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['ShortMacDlTDoASessionInfoNtf', bytes]:
-        if fields['ranging_measurement_type'] != RangingMeasurementType.DL_TDOA or fields['mac_address_indicator'] != MacAddressIndicator.SHORT_ADDRESS or fields['opcode'] != 0x0 or fields['gid'] != GroupId.SESSION_CONTROL or fields['mt'] != MessageType.NOTIFICATION:
+        if fields['ranging_measurement_type'] != RangingMeasurementType.DL_TDOA or fields['mac_address_indicator'] != MacAddressIndicator.SHORT_ADDRESS or fields['mt'] != MessageType.NOTIFICATION or fields['oid'] != SessionControlOpcodeId.START or fields['gid'] != GroupId.SESSION_CONTROL:
             raise Exception("Invalid constraint field values")
         if len(span) < 1:
             raise Exception('Invalid packet size')
@@ -4512,13 +4162,13 @@
     def __post_init__(self):
         self.ranging_measurement_type = RangingMeasurementType.DL_TDOA
         self.mac_address_indicator = MacAddressIndicator.EXTENDED_ADDRESS
-        self.opcode = 0
-        self.gid = GroupId.SESSION_CONTROL
         self.mt = MessageType.NOTIFICATION
+        self.oid = SessionControlOpcodeId.START
+        self.gid = GroupId.SESSION_CONTROL
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['ExtendedMacDlTDoASessionInfoNtf', bytes]:
-        if fields['ranging_measurement_type'] != RangingMeasurementType.DL_TDOA or fields['mac_address_indicator'] != MacAddressIndicator.EXTENDED_ADDRESS or fields['opcode'] != 0x0 or fields['gid'] != GroupId.SESSION_CONTROL or fields['mt'] != MessageType.NOTIFICATION:
+        if fields['ranging_measurement_type'] != RangingMeasurementType.DL_TDOA or fields['mac_address_indicator'] != MacAddressIndicator.EXTENDED_ADDRESS or fields['mt'] != MessageType.NOTIFICATION or fields['oid'] != SessionControlOpcodeId.START or fields['gid'] != GroupId.SESSION_CONTROL:
             raise Exception("Invalid constraint field values")
         if len(span) < 1:
             raise Exception('Invalid packet size')
@@ -4549,13 +4199,13 @@
     def __post_init__(self):
         self.ranging_measurement_type = RangingMeasurementType.OWR_AOA
         self.mac_address_indicator = MacAddressIndicator.SHORT_ADDRESS
-        self.opcode = 0
-        self.gid = GroupId.SESSION_CONTROL
         self.mt = MessageType.NOTIFICATION
+        self.oid = SessionControlOpcodeId.START
+        self.gid = GroupId.SESSION_CONTROL
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['ShortMacOwrAoaSessionInfoNtf', bytes]:
-        if fields['ranging_measurement_type'] != RangingMeasurementType.OWR_AOA or fields['mac_address_indicator'] != MacAddressIndicator.SHORT_ADDRESS or fields['opcode'] != 0x0 or fields['gid'] != GroupId.SESSION_CONTROL or fields['mt'] != MessageType.NOTIFICATION:
+        if fields['ranging_measurement_type'] != RangingMeasurementType.OWR_AOA or fields['mac_address_indicator'] != MacAddressIndicator.SHORT_ADDRESS or fields['mt'] != MessageType.NOTIFICATION or fields['oid'] != SessionControlOpcodeId.START or fields['gid'] != GroupId.SESSION_CONTROL:
             raise Exception("Invalid constraint field values")
         if len(span) < 1:
             raise Exception('Invalid packet size')
@@ -4598,13 +4248,13 @@
     def __post_init__(self):
         self.ranging_measurement_type = RangingMeasurementType.OWR_AOA
         self.mac_address_indicator = MacAddressIndicator.EXTENDED_ADDRESS
-        self.opcode = 0
-        self.gid = GroupId.SESSION_CONTROL
         self.mt = MessageType.NOTIFICATION
+        self.oid = SessionControlOpcodeId.START
+        self.gid = GroupId.SESSION_CONTROL
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['ExtendedMacOwrAoaSessionInfoNtf', bytes]:
-        if fields['ranging_measurement_type'] != RangingMeasurementType.OWR_AOA or fields['mac_address_indicator'] != MacAddressIndicator.EXTENDED_ADDRESS or fields['opcode'] != 0x0 or fields['gid'] != GroupId.SESSION_CONTROL or fields['mt'] != MessageType.NOTIFICATION:
+        if fields['ranging_measurement_type'] != RangingMeasurementType.OWR_AOA or fields['mac_address_indicator'] != MacAddressIndicator.EXTENDED_ADDRESS or fields['mt'] != MessageType.NOTIFICATION or fields['oid'] != SessionControlOpcodeId.START or fields['gid'] != GroupId.SESSION_CONTROL:
             raise Exception("Invalid constraint field values")
         if len(span) < 1:
             raise Exception('Invalid packet size')
@@ -4640,96 +4290,114 @@
         )
 
 @dataclass
-class SessionStopCmd(SessionControlCommand):
-    
+class SessionStopCmd(SessionControlPacket):
+    session_id: int = field(kw_only=True, default=0)
 
     def __post_init__(self):
-        self.opcode = 1
-        self.gid = GroupId.SESSION_CONTROL
         self.mt = MessageType.COMMAND
+        self.oid = SessionControlOpcodeId.STOP
+        self.gid = GroupId.SESSION_CONTROL
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionStopCmd', bytes]:
-        if fields['opcode'] != 0x1 or fields['gid'] != GroupId.SESSION_CONTROL or fields['mt'] != MessageType.COMMAND:
+        if fields['mt'] != MessageType.COMMAND or fields['oid'] != SessionControlOpcodeId.STOP or fields['gid'] != GroupId.SESSION_CONTROL:
             raise Exception("Invalid constraint field values")
+        if len(span) < 4:
+            raise Exception('Invalid packet size')
+        value_ = int.from_bytes(span[0:4], byteorder='little')
+        fields['session_id'] = value_
+        span = span[4:]
         return SessionStopCmd(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
-        return SessionControlCommand.serialize(self, payload = bytes(_span))
+        if self.session_id > 4294967295:
+            print(f"Invalid value for field SessionStopCmd::session_id: {self.session_id} > 4294967295; the value will be truncated")
+            self.session_id &= 4294967295
+        _span.extend(int.to_bytes((self.session_id << 0), length=4, byteorder='little'))
+        return SessionControlPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
-        return 0
+        return 4
 
 @dataclass
-class SessionStopRsp(SessionControlResponse):
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+class SessionStopRsp(SessionControlPacket):
+    status: Status = field(kw_only=True, default=Status.OK)
 
     def __post_init__(self):
-        self.opcode = 1
-        self.gid = GroupId.SESSION_CONTROL
         self.mt = MessageType.RESPONSE
+        self.oid = SessionControlOpcodeId.STOP
+        self.gid = GroupId.SESSION_CONTROL
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionStopRsp', bytes]:
-        if fields['opcode'] != 0x1 or fields['gid'] != GroupId.SESSION_CONTROL or fields['mt'] != MessageType.RESPONSE:
+        if fields['mt'] != MessageType.RESPONSE or fields['oid'] != SessionControlOpcodeId.STOP or fields['gid'] != GroupId.SESSION_CONTROL:
             raise Exception("Invalid constraint field values")
         if len(span) < 1:
             raise Exception('Invalid packet size')
-        fields['status'] = StatusCode.from_int(span[0])
+        fields['status'] = Status.from_int(span[0])
         span = span[1:]
         return SessionStopRsp(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
         _span.append((self.status << 0))
-        return SessionControlResponse.serialize(self, payload = bytes(_span))
+        return SessionControlPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 1
 
 @dataclass
-class SessionGetRangingCountCmd(SessionControlCommand):
-    
+class SessionGetRangingCountCmd(SessionControlPacket):
+    session_id: int = field(kw_only=True, default=0)
 
     def __post_init__(self):
-        self.opcode = 3
-        self.gid = GroupId.SESSION_CONTROL
         self.mt = MessageType.COMMAND
+        self.oid = SessionControlOpcodeId.GET_RANGING_COUNT
+        self.gid = GroupId.SESSION_CONTROL
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionGetRangingCountCmd', bytes]:
-        if fields['opcode'] != 0x3 or fields['gid'] != GroupId.SESSION_CONTROL or fields['mt'] != MessageType.COMMAND:
+        if fields['mt'] != MessageType.COMMAND or fields['oid'] != SessionControlOpcodeId.GET_RANGING_COUNT or fields['gid'] != GroupId.SESSION_CONTROL:
             raise Exception("Invalid constraint field values")
+        if len(span) < 4:
+            raise Exception('Invalid packet size')
+        value_ = int.from_bytes(span[0:4], byteorder='little')
+        fields['session_id'] = value_
+        span = span[4:]
         return SessionGetRangingCountCmd(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
-        return SessionControlCommand.serialize(self, payload = bytes(_span))
+        if self.session_id > 4294967295:
+            print(f"Invalid value for field SessionGetRangingCountCmd::session_id: {self.session_id} > 4294967295; the value will be truncated")
+            self.session_id &= 4294967295
+        _span.extend(int.to_bytes((self.session_id << 0), length=4, byteorder='little'))
+        return SessionControlPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
-        return 0
+        return 4
 
 @dataclass
-class SessionGetRangingCountRsp(SessionControlResponse):
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+class SessionGetRangingCountRsp(SessionControlPacket):
+    status: Status = field(kw_only=True, default=Status.OK)
     count: int = field(kw_only=True, default=0)
 
     def __post_init__(self):
-        self.opcode = 3
-        self.gid = GroupId.SESSION_CONTROL
         self.mt = MessageType.RESPONSE
+        self.oid = SessionControlOpcodeId.GET_RANGING_COUNT
+        self.gid = GroupId.SESSION_CONTROL
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['SessionGetRangingCountRsp', bytes]:
-        if fields['opcode'] != 0x3 or fields['gid'] != GroupId.SESSION_CONTROL or fields['mt'] != MessageType.RESPONSE:
+        if fields['mt'] != MessageType.RESPONSE or fields['oid'] != SessionControlOpcodeId.GET_RANGING_COUNT or fields['gid'] != GroupId.SESSION_CONTROL:
             raise Exception("Invalid constraint field values")
         if len(span) < 5:
             raise Exception('Invalid packet size')
-        fields['status'] = StatusCode.from_int(span[0])
+        fields['status'] = Status.from_int(span[0])
         value_ = int.from_bytes(span[1:5], byteorder='little')
         fields['count'] = value_
         span = span[5:]
@@ -4742,30 +4410,30 @@
             print(f"Invalid value for field SessionGetRangingCountRsp::count: {self.count} > 4294967295; the value will be truncated")
             self.count &= 4294967295
         _span.extend(int.to_bytes((self.count << 0), length=4, byteorder='little'))
-        return SessionControlResponse.serialize(self, payload = bytes(_span))
+        return SessionControlPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 5
 
 @dataclass
-class AndroidGetPowerStatsCmd(AndroidCommand):
+class AndroidGetPowerStatsCmd(AndroidPacket):
     
 
     def __post_init__(self):
-        self.opcode = 0
-        self.gid = GroupId.VENDOR_ANDROID
         self.mt = MessageType.COMMAND
+        self.oid = AndroidOpcodeId.GET_POWER_STATS
+        self.gid = GroupId.VENDOR_ANDROID
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['AndroidGetPowerStatsCmd', bytes]:
-        if fields['opcode'] != 0x0 or fields['gid'] != GroupId.VENDOR_ANDROID or fields['mt'] != MessageType.COMMAND:
+        if fields['mt'] != MessageType.COMMAND or fields['oid'] != AndroidOpcodeId.GET_POWER_STATS or fields['gid'] != GroupId.VENDOR_ANDROID:
             raise Exception("Invalid constraint field values")
         return AndroidGetPowerStatsCmd(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
-        return AndroidCommand.serialize(self, payload = bytes(_span))
+        return AndroidPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
@@ -4773,7 +4441,7 @@
 
 @dataclass
 class PowerStats(Packet):
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+    status: Status = field(kw_only=True, default=Status.OK)
     idle_time_ms: int = field(kw_only=True, default=0)
     tx_time_ms: int = field(kw_only=True, default=0)
     rx_time_ms: int = field(kw_only=True, default=0)
@@ -4787,7 +4455,7 @@
         fields = {'payload': None}
         if len(span) < 17:
             raise Exception('Invalid packet size')
-        fields['status'] = StatusCode.from_int(span[0])
+        fields['status'] = Status.from_int(span[0])
         value_ = int.from_bytes(span[1:5], byteorder='little')
         fields['idle_time_ms'] = value_
         value_ = int.from_bytes(span[5:9], byteorder='little')
@@ -4825,17 +4493,17 @@
         return 17
 
 @dataclass
-class AndroidGetPowerStatsRsp(AndroidResponse):
+class AndroidGetPowerStatsRsp(AndroidPacket):
     stats: PowerStats = field(kw_only=True, default_factory=PowerStats)
 
     def __post_init__(self):
-        self.opcode = 0
-        self.gid = GroupId.VENDOR_ANDROID
         self.mt = MessageType.RESPONSE
+        self.oid = AndroidOpcodeId.GET_POWER_STATS
+        self.gid = GroupId.VENDOR_ANDROID
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['AndroidGetPowerStatsRsp', bytes]:
-        if fields['opcode'] != 0x0 or fields['gid'] != GroupId.VENDOR_ANDROID or fields['mt'] != MessageType.RESPONSE:
+        if fields['mt'] != MessageType.RESPONSE or fields['oid'] != AndroidOpcodeId.GET_POWER_STATS or fields['gid'] != GroupId.VENDOR_ANDROID:
             raise Exception("Invalid constraint field values")
         if len(span) < 17:
             raise Exception('Invalid packet size')
@@ -4846,24 +4514,24 @@
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
         _span.extend(self.stats.serialize())
-        return AndroidResponse.serialize(self, payload = bytes(_span))
+        return AndroidPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 17
 
 @dataclass
-class AndroidSetCountryCodeCmd(AndroidCommand):
+class AndroidSetCountryCodeCmd(AndroidPacket):
     country_code: bytearray = field(kw_only=True, default_factory=bytearray)
 
     def __post_init__(self):
-        self.opcode = 1
-        self.gid = GroupId.VENDOR_ANDROID
         self.mt = MessageType.COMMAND
+        self.oid = AndroidOpcodeId.SET_COUNTRY_CODE
+        self.gid = GroupId.VENDOR_ANDROID
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['AndroidSetCountryCodeCmd', bytes]:
-        if fields['opcode'] != 0x1 or fields['gid'] != GroupId.VENDOR_ANDROID or fields['mt'] != MessageType.COMMAND:
+        if fields['mt'] != MessageType.COMMAND or fields['oid'] != AndroidOpcodeId.SET_COUNTRY_CODE or fields['gid'] != GroupId.VENDOR_ANDROID:
             raise Exception("Invalid constraint field values")
         if len(span) < 2:
             raise Exception('Invalid packet size')
@@ -4874,40 +4542,53 @@
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
         _span.extend(self.country_code)
-        return AndroidCommand.serialize(self, payload = bytes(_span))
+        return AndroidPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 2
 
 @dataclass
-class AndroidSetCountryCodeRsp(AndroidResponse):
-    status: StatusCode = field(kw_only=True, default=StatusCode.UCI_STATUS_OK)
+class AndroidSetCountryCodeRsp(AndroidPacket):
+    status: Status = field(kw_only=True, default=Status.OK)
 
     def __post_init__(self):
-        self.opcode = 1
-        self.gid = GroupId.VENDOR_ANDROID
         self.mt = MessageType.RESPONSE
+        self.oid = AndroidOpcodeId.SET_COUNTRY_CODE
+        self.gid = GroupId.VENDOR_ANDROID
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['AndroidSetCountryCodeRsp', bytes]:
-        if fields['opcode'] != 0x1 or fields['gid'] != GroupId.VENDOR_ANDROID or fields['mt'] != MessageType.RESPONSE:
+        if fields['mt'] != MessageType.RESPONSE or fields['oid'] != AndroidOpcodeId.SET_COUNTRY_CODE or fields['gid'] != GroupId.VENDOR_ANDROID:
             raise Exception("Invalid constraint field values")
         if len(span) < 1:
             raise Exception('Invalid packet size')
-        fields['status'] = StatusCode.from_int(span[0])
+        fields['status'] = Status.from_int(span[0])
         span = span[1:]
         return AndroidSetCountryCodeRsp(**fields), span
 
     def serialize(self, payload: bytes = None) -> bytes:
         _span = bytearray()
         _span.append((self.status << 0))
-        return AndroidResponse.serialize(self, payload = bytes(_span))
+        return AndroidPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return 1
 
+class FrameReportTlvType(enum.IntEnum):
+    RSSI = 0x0
+    AOA = 0x1
+    CIR = 0x2
+
+    @staticmethod
+    def from_int(v: int) -> Union[int, 'FrameReportTlvType']:
+        try:
+            return FrameReportTlvType(v)
+        except ValueError as exn:
+            raise exn
+
+
 @dataclass
 class FrameReportTlv(Packet):
     t: FrameReportTlvType = field(kw_only=True, default=FrameReportTlvType.RSSI)
@@ -5277,19 +4958,19 @@
         return sum([elt.size for elt in self.frame_report_tlvs]) + 4
 
 @dataclass
-class AndroidRangeDiagnosticsNtf(AndroidNotification):
+class AndroidRangeDiagnosticsNtf(AndroidPacket):
     session_token: int = field(kw_only=True, default=0)
     sequence_number: int = field(kw_only=True, default=0)
     frame_reports: List[FrameReport] = field(kw_only=True, default_factory=list)
 
     def __post_init__(self):
-        self.opcode = 2
-        self.gid = GroupId.VENDOR_ANDROID
         self.mt = MessageType.NOTIFICATION
+        self.oid = AndroidOpcodeId.FIRA_RANGE_DIAGNOSTICS
+        self.gid = GroupId.VENDOR_ANDROID
 
     @staticmethod
     def parse(fields: dict, span: bytes) -> Tuple['AndroidRangeDiagnosticsNtf', bytes]:
-        if fields['opcode'] != 0x2 or fields['gid'] != GroupId.VENDOR_ANDROID or fields['mt'] != MessageType.NOTIFICATION:
+        if fields['mt'] != MessageType.NOTIFICATION or fields['oid'] != AndroidOpcodeId.FIRA_RANGE_DIAGNOSTICS or fields['gid'] != GroupId.VENDOR_ANDROID:
             raise Exception("Invalid constraint field values")
         if len(span) < 9:
             raise Exception('Invalid packet size')
@@ -5322,424 +5003,8 @@
         _span.append((len(self.frame_reports) << 0))
         for _elt in self.frame_reports:
             _span.extend(_elt.serialize())
-        return AndroidNotification.serialize(self, payload = bytes(_span))
+        return AndroidPacket.serialize(self, payload = bytes(_span))
 
     @property
     def size(self) -> int:
         return sum([elt.size for elt in self.frame_reports]) + 9
-
-@dataclass
-class UciVendor_9_Command(UciCommand):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.VENDOR_RESERVED_9
-        self.mt = MessageType.COMMAND
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['UciVendor_9_Command', bytes]:
-        if fields['gid'] != GroupId.VENDOR_RESERVED_9 or fields['mt'] != MessageType.COMMAND:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        return UciVendor_9_Command(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciCommand.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class UciVendor_A_Command(UciCommand):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.VENDOR_RESERVED_A
-        self.mt = MessageType.COMMAND
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['UciVendor_A_Command', bytes]:
-        if fields['gid'] != GroupId.VENDOR_RESERVED_A or fields['mt'] != MessageType.COMMAND:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        return UciVendor_A_Command(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciCommand.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class UciVendor_B_Command(UciCommand):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.VENDOR_RESERVED_B
-        self.mt = MessageType.COMMAND
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['UciVendor_B_Command', bytes]:
-        if fields['gid'] != GroupId.VENDOR_RESERVED_B or fields['mt'] != MessageType.COMMAND:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        return UciVendor_B_Command(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciCommand.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class UciVendor_E_Command(UciCommand):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.VENDOR_RESERVED_E
-        self.mt = MessageType.COMMAND
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['UciVendor_E_Command', bytes]:
-        if fields['gid'] != GroupId.VENDOR_RESERVED_E or fields['mt'] != MessageType.COMMAND:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        return UciVendor_E_Command(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciCommand.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class UciVendor_F_Command(UciCommand):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.VENDOR_RESERVED_F
-        self.mt = MessageType.COMMAND
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['UciVendor_F_Command', bytes]:
-        if fields['gid'] != GroupId.VENDOR_RESERVED_F or fields['mt'] != MessageType.COMMAND:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        return UciVendor_F_Command(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciCommand.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class UciVendor_9_Response(UciResponse):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.VENDOR_RESERVED_9
-        self.mt = MessageType.RESPONSE
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['UciVendor_9_Response', bytes]:
-        if fields['gid'] != GroupId.VENDOR_RESERVED_9 or fields['mt'] != MessageType.RESPONSE:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        return UciVendor_9_Response(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciResponse.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class UciVendor_A_Response(UciResponse):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.VENDOR_RESERVED_A
-        self.mt = MessageType.RESPONSE
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['UciVendor_A_Response', bytes]:
-        if fields['gid'] != GroupId.VENDOR_RESERVED_A or fields['mt'] != MessageType.RESPONSE:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        return UciVendor_A_Response(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciResponse.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class UciVendor_B_Response(UciResponse):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.VENDOR_RESERVED_B
-        self.mt = MessageType.RESPONSE
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['UciVendor_B_Response', bytes]:
-        if fields['gid'] != GroupId.VENDOR_RESERVED_B or fields['mt'] != MessageType.RESPONSE:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        return UciVendor_B_Response(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciResponse.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class UciVendor_E_Response(UciResponse):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.VENDOR_RESERVED_E
-        self.mt = MessageType.RESPONSE
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['UciVendor_E_Response', bytes]:
-        if fields['gid'] != GroupId.VENDOR_RESERVED_E or fields['mt'] != MessageType.RESPONSE:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        return UciVendor_E_Response(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciResponse.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class UciVendor_F_Response(UciResponse):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.VENDOR_RESERVED_F
-        self.mt = MessageType.RESPONSE
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['UciVendor_F_Response', bytes]:
-        if fields['gid'] != GroupId.VENDOR_RESERVED_F or fields['mt'] != MessageType.RESPONSE:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        return UciVendor_F_Response(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciResponse.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class UciVendor_9_Notification(UciNotification):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.VENDOR_RESERVED_9
-        self.mt = MessageType.NOTIFICATION
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['UciVendor_9_Notification', bytes]:
-        if fields['gid'] != GroupId.VENDOR_RESERVED_9 or fields['mt'] != MessageType.NOTIFICATION:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        return UciVendor_9_Notification(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciNotification.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class UciVendor_A_Notification(UciNotification):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.VENDOR_RESERVED_A
-        self.mt = MessageType.NOTIFICATION
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['UciVendor_A_Notification', bytes]:
-        if fields['gid'] != GroupId.VENDOR_RESERVED_A or fields['mt'] != MessageType.NOTIFICATION:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        return UciVendor_A_Notification(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciNotification.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class UciVendor_B_Notification(UciNotification):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.VENDOR_RESERVED_B
-        self.mt = MessageType.NOTIFICATION
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['UciVendor_B_Notification', bytes]:
-        if fields['gid'] != GroupId.VENDOR_RESERVED_B or fields['mt'] != MessageType.NOTIFICATION:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        return UciVendor_B_Notification(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciNotification.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class UciVendor_E_Notification(UciNotification):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.VENDOR_RESERVED_E
-        self.mt = MessageType.NOTIFICATION
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['UciVendor_E_Notification', bytes]:
-        if fields['gid'] != GroupId.VENDOR_RESERVED_E or fields['mt'] != MessageType.NOTIFICATION:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        return UciVendor_E_Notification(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciNotification.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class UciVendor_F_Notification(UciNotification):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.VENDOR_RESERVED_F
-        self.mt = MessageType.NOTIFICATION
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['UciVendor_F_Notification', bytes]:
-        if fields['gid'] != GroupId.VENDOR_RESERVED_F or fields['mt'] != MessageType.NOTIFICATION:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        return UciVendor_F_Notification(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciNotification.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
-
-@dataclass
-class TestNotification(UciNotification):
-    
-
-    def __post_init__(self):
-        self.gid = GroupId.TEST
-        self.mt = MessageType.NOTIFICATION
-
-    @staticmethod
-    def parse(fields: dict, span: bytes) -> Tuple['TestNotification', bytes]:
-        if fields['gid'] != GroupId.TEST or fields['mt'] != MessageType.NOTIFICATION:
-            raise Exception("Invalid constraint field values")
-        payload = span
-        span = bytes([])
-        fields['payload'] = payload
-        return TestNotification(**fields), span
-
-    def serialize(self, payload: bytes = None) -> bytes:
-        _span = bytearray()
-        _span.extend(payload or self.payload or [])
-        return UciNotification.serialize(self, payload = bytes(_span))
-
-    @property
-    def size(self) -> int:
-        return len(self.payload)
diff --git a/src/app_config.rs b/src/app_config.rs
new file mode 100644
index 0000000..40ac595
--- /dev/null
+++ b/src/app_config.rs
@@ -0,0 +1,517 @@
+use crate::packets::uci;
+use crate::MacAddress;
+
+/// [UCI] 8.3 Application Configuration Parameters.
+/// Sub-session Key provided for Provisioned STS for Responder specific Key mode
+/// (STS_CONFIG equal to 0x04).
+#[derive(Clone, PartialEq, Eq)]
+pub enum SubSessionKey {
+    None,
+    Short([u8; 16]),
+    Extended([u8; 32]),
+}
+
+/// [UCI] 8.3 Application Configuration Parameters.
+/// The configuration is initially filled with default values from the
+/// specification.
+/// See [UCI] Table 45: APP Configuration Parameters IDs
+/// for the format of each parameter and the default value.
+/// Mandatory APP configuration parameters are declared as optional,
+/// and must be set before moving the session from SESSION_STATE_INIT to
+/// SESSION_STATE_IDLE.
+#[derive(Clone, PartialEq, Eq)]
+pub struct AppConfig {
+    pub device_type: Option<uci::DeviceType>,
+    pub ranging_round_usage: Option<uci::RangingRoundUsage>,
+    pub sts_config: uci::StsConfig,
+    pub multi_node_mode: Option<uci::MultiNodeMode>,
+    channel_number: uci::ChannelNumber,
+    /// Number of Controlees(N) 1<=N<=8 (Default is 1)
+    pub number_of_controlees: u8,
+    /// MAC Address of the UWBS itself participating in UWB session.
+    /// The short address (2 bytes) or extended MAC address (8 bytes)
+    /// shall be indicated via MAC_ADDRESS_MODE config.
+    pub device_mac_address: Option<MacAddress>,
+    /// MAC Address list(N) for NUMBER_OF_CONTROLEES
+    /// devices participating in UWB Session.
+    ///
+    /// The size of this list shall be:
+    /// - equal to 1 when MULTI_NODE_MODE is set 0x00 (O2O).
+    /// - ranging from 1 to 8 when MULTI_NODE_MODE is set to 0x01 (O2M).
+    pub dst_mac_address: Vec<MacAddress>,
+    slot_duration: u16,
+    pub ranging_duration: u32,
+    sts_index: u32,
+    mac_fcs_type: uci::MacFcsType,
+    ranging_round_control: u8,
+    aoa_result_req: uci::AoaResultReq,
+    pub session_info_ntf_config: uci::SessionInfoNtfConfig,
+    near_proximity_config: u16,
+    far_proximity_config: u16,
+    pub device_role: Option<uci::DeviceRole>,
+    rframe_config: uci::RframeConfig,
+    rssi_reporting: uci::RssiReporting,
+    preamble_code_index: u8,
+    sfd_id: u8,
+    psdu_data_rate: uci::PsduDataRate,
+    preamble_duration: uci::PreambleDuration,
+    link_layer_mode: uci::LinkLayerMode,
+    data_repetition_count: u8,
+    ranging_time_struct: uci::RangingTimeStruct,
+    slots_per_rr: u8,
+    aoa_bound_config: [u16; 4],
+    prf_mode: uci::PrfMode,
+    cap_size_range: [u8; 2],
+    tx_jitter_window_size: u8,
+    pub schedule_mode: Option<uci::ScheduleMode>,
+    key_rotation: uci::KeyRotation,
+    key_rotation_rate: u8,
+    session_priority: u8,
+    pub mac_address_mode: uci::MacAddressMode,
+    vendor_id: u16,
+    static_sts_iv: [u8; 6],
+    number_of_sts_segments: u8,
+    max_rr_retry: u16,
+    uwb_initiation_time: u64,
+    hopping_mode: uci::HoppingMode,
+    block_stride_length: u8,
+    result_report_config: u8,
+    pub in_band_termination_attempt_count: u8,
+    sub_session_id: u32,
+    bprf_phr_data_rate: uci::BprfPhrDataRate,
+    max_number_of_measurements: u16,
+    sts_length: uci::StsLength,
+    min_frames_per_rr: u8,
+    mtu_size: u16,
+    inter_frame_interval: u8,
+    session_key: Vec<u8>,
+    sub_session_key: SubSessionKey,
+    pub session_data_transfer_status_ntf_config: uci::SessionDataTransferStatusNtfConfig,
+    session_time_base: [u8; 9],
+    application_data_endpoint: u8,
+}
+
+impl Default for AppConfig {
+    fn default() -> Self {
+        AppConfig {
+            device_type: None,
+            ranging_round_usage: None,
+            sts_config: uci::StsConfig::Static,
+            multi_node_mode: None,
+            channel_number: uci::ChannelNumber::ChannelNumber9,
+            number_of_controlees: 1,
+            device_mac_address: None,
+            dst_mac_address: vec![],
+            slot_duration: 2400,
+            ranging_duration: 200,
+            sts_index: 0,
+            mac_fcs_type: uci::MacFcsType::Crc16,
+            // The default is 0x03 when Time Scheduled Ranging is used,
+            // 0x06 when Contention-based Ranging is used.
+            ranging_round_control: 0x06,
+            aoa_result_req: uci::AoaResultReq::AoaEnabled,
+            session_info_ntf_config: uci::SessionInfoNtfConfig::Enable,
+            near_proximity_config: 0,
+            far_proximity_config: 20000,
+            device_role: None,
+            rframe_config: uci::RframeConfig::Sp3,
+            rssi_reporting: uci::RssiReporting::Disable,
+            preamble_code_index: 10,
+            sfd_id: 2,
+            psdu_data_rate: uci::PsduDataRate::DataRate6m81,
+            preamble_duration: uci::PreambleDuration::Duration64Symbols,
+            link_layer_mode: uci::LinkLayerMode::BypassMode,
+            data_repetition_count: 0,
+            ranging_time_struct: uci::RangingTimeStruct::BlockBasedScheduling,
+            slots_per_rr: 25,
+            aoa_bound_config: [0; 4],
+            prf_mode: uci::PrfMode::BprfMode,
+            // Default for Octet[0] is SLOTS_PER_RR - 1
+            cap_size_range: [24, 5],
+            tx_jitter_window_size: 0,
+            schedule_mode: None,
+            key_rotation: uci::KeyRotation::Disable,
+            key_rotation_rate: 0,
+            session_priority: 50,
+            mac_address_mode: uci::MacAddressMode::Mode0,
+            vendor_id: 0,
+            static_sts_iv: [0; 6],
+            number_of_sts_segments: 1,
+            max_rr_retry: 0,
+            uwb_initiation_time: 0,
+            hopping_mode: uci::HoppingMode::Disable,
+            block_stride_length: 0,
+            result_report_config: 0x01,
+            in_band_termination_attempt_count: 1,
+            sub_session_id: 0, // XX
+            bprf_phr_data_rate: uci::BprfPhrDataRate::DataRate850k,
+            max_number_of_measurements: 0,
+            sts_length: uci::StsLength::Length64Symbols,
+            min_frames_per_rr: 4,
+            mtu_size: 0, // XX
+            inter_frame_interval: 1,
+            session_key: vec![],
+            sub_session_key: SubSessionKey::None,
+            session_data_transfer_status_ntf_config:
+                uci::SessionDataTransferStatusNtfConfig::Disable,
+            session_time_base: [0; 9],
+            application_data_endpoint: 0,
+        }
+    }
+}
+
+impl AppConfig {
+    /// Set the APP configuration value with the selected identifier
+    /// and value. Returns `Ok` if the identifier is known and the value
+    /// well formatted, `Err` otherwise.
+    pub fn set(&mut self, id: uci::AppConfigTlvType, value: &[u8]) -> anyhow::Result<()> {
+        fn try_parse<T: TryFrom<u8, Error = u8>>(value: &[u8]) -> anyhow::Result<T> {
+            T::try_from(u8::from_le_bytes(value.try_into()?)).map_err(anyhow::Error::msg)
+        }
+
+        fn try_parse_u8(value: &[u8]) -> anyhow::Result<u8> {
+            Ok(u8::from_le_bytes(value.try_into()?))
+        }
+
+        fn try_parse_u16(value: &[u8]) -> anyhow::Result<u16> {
+            Ok(u16::from_le_bytes(value.try_into()?))
+        }
+
+        fn try_parse_u32(value: &[u8]) -> anyhow::Result<u32> {
+            Ok(u32::from_le_bytes(value.try_into()?))
+        }
+
+        fn try_parse_u64(value: &[u8]) -> anyhow::Result<u64> {
+            Ok(u64::from_le_bytes(value.try_into()?))
+        }
+
+        match id {
+            uci::AppConfigTlvType::DeviceType => self.device_type = Some(try_parse(value)?),
+            uci::AppConfigTlvType::RangingRoundUsage => {
+                self.ranging_round_usage = Some(try_parse(value)?)
+            }
+            uci::AppConfigTlvType::StsConfig => self.sts_config = try_parse(value)?,
+            uci::AppConfigTlvType::MultiNodeMode => self.multi_node_mode = Some(try_parse(value)?),
+            uci::AppConfigTlvType::ChannelNumber => self.channel_number = try_parse(value)?,
+            uci::AppConfigTlvType::NumberOfControlees => {
+                self.number_of_controlees = try_parse_u8(value)?
+            }
+            uci::AppConfigTlvType::DeviceMacAddress => {
+                self.device_mac_address = Some(match self.mac_address_mode {
+                    uci::MacAddressMode::Mode0 => MacAddress::Short(value.try_into()?),
+                    uci::MacAddressMode::Mode1 => unimplemented!(),
+                    uci::MacAddressMode::Mode2 => MacAddress::Extended(value.try_into()?),
+                })
+            }
+            uci::AppConfigTlvType::DstMacAddress => {
+                let mac_address_size = match self.mac_address_mode {
+                    uci::MacAddressMode::Mode0 => 2,
+                    uci::MacAddressMode::Mode1 => unimplemented!(),
+                    uci::MacAddressMode::Mode2 => 8,
+                };
+                if value.len() != self.number_of_controlees as usize * mac_address_size {
+                    log::error!(
+                        "invalid dst_mac_address len: expected {}x{}, got {}",
+                        self.number_of_controlees,
+                        mac_address_size,
+                        value.len()
+                    );
+                    anyhow::bail!("invalid dst_mac_address len")
+                }
+                self.dst_mac_address = value
+                    .chunks(mac_address_size)
+                    .map(|value| match self.mac_address_mode {
+                        uci::MacAddressMode::Mode0 => MacAddress::Short(value.try_into().unwrap()),
+                        uci::MacAddressMode::Mode1 => unimplemented!(),
+                        uci::MacAddressMode::Mode2 => {
+                            MacAddress::Extended(value.try_into().unwrap())
+                        }
+                    })
+                    .collect();
+            }
+            uci::AppConfigTlvType::SlotDuration => self.slot_duration = try_parse_u16(value)?,
+            uci::AppConfigTlvType::RangingDuration => self.ranging_duration = try_parse_u32(value)?,
+            uci::AppConfigTlvType::StsIndex => self.sts_index = try_parse_u32(value)?,
+            uci::AppConfigTlvType::MacFcsType => self.mac_fcs_type = try_parse(value)?,
+            uci::AppConfigTlvType::RangingRoundControl => {
+                self.ranging_round_control = try_parse_u8(value)?
+            }
+            uci::AppConfigTlvType::AoaResultReq => self.aoa_result_req = try_parse(value)?,
+            uci::AppConfigTlvType::SessionInfoNtfConfig => {
+                self.session_info_ntf_config = try_parse(value)?
+            }
+            uci::AppConfigTlvType::NearProximityConfig => {
+                self.near_proximity_config = try_parse_u16(value)?
+            }
+            uci::AppConfigTlvType::FarProximityConfig => {
+                self.far_proximity_config = try_parse_u16(value)?
+            }
+            uci::AppConfigTlvType::DeviceRole => self.device_role = Some(try_parse(value)?),
+            uci::AppConfigTlvType::RframeConfig => self.rframe_config = try_parse(value)?,
+            uci::AppConfigTlvType::RssiReporting => self.rssi_reporting = try_parse(value)?,
+            uci::AppConfigTlvType::PreambleCodeIndex => {
+                self.preamble_code_index = try_parse_u8(value)?
+            }
+            uci::AppConfigTlvType::SfdId => self.sfd_id = try_parse_u8(value)?,
+            uci::AppConfigTlvType::PsduDataRate => self.psdu_data_rate = try_parse(value)?,
+            uci::AppConfigTlvType::PreambleDuration => self.preamble_duration = try_parse(value)?,
+            uci::AppConfigTlvType::LinkLayerMode => self.link_layer_mode = try_parse(value)?,
+            uci::AppConfigTlvType::DataRepetitionCount => {
+                self.data_repetition_count = try_parse_u8(value)?
+            }
+            uci::AppConfigTlvType::RangingTimeStruct => {
+                self.ranging_time_struct = try_parse(value)?
+            }
+            uci::AppConfigTlvType::SlotsPerRr => self.slots_per_rr = try_parse_u8(value)?,
+            uci::AppConfigTlvType::AoaBoundConfig => {
+                if value.len() != 8 {
+                    log::error!(
+                        "invalid aoa_bound_config len: expected 8, got {}",
+                        value.len()
+                    );
+                    anyhow::bail!("invalid aoa_bound_config len")
+                }
+                self.aoa_bound_config = [
+                    u16::from_le_bytes([value[0], value[1]]),
+                    u16::from_le_bytes([value[2], value[3]]),
+                    u16::from_le_bytes([value[4], value[5]]),
+                    u16::from_le_bytes([value[6], value[7]]),
+                ]
+            }
+            uci::AppConfigTlvType::PrfMode => self.prf_mode = try_parse(value)?,
+            uci::AppConfigTlvType::CapSizeRange => self.cap_size_range = value.try_into()?,
+            uci::AppConfigTlvType::TxJitterWindowSize => {
+                self.tx_jitter_window_size = try_parse_u8(value)?
+            }
+            uci::AppConfigTlvType::ScheduleMode => self.schedule_mode = Some(try_parse(value)?),
+            uci::AppConfigTlvType::KeyRotation => self.key_rotation = try_parse(value)?,
+            uci::AppConfigTlvType::KeyRotationRate => self.key_rotation_rate = try_parse_u8(value)?,
+            uci::AppConfigTlvType::SessionPriority => self.session_priority = try_parse_u8(value)?,
+            uci::AppConfigTlvType::MacAddressMode => self.mac_address_mode = try_parse(value)?,
+            uci::AppConfigTlvType::VendorId => self.vendor_id = try_parse_u16(value)?,
+            uci::AppConfigTlvType::StaticStsIv => self.static_sts_iv = value.try_into()?,
+            uci::AppConfigTlvType::NumberOfStsSegments => {
+                self.number_of_sts_segments = try_parse_u8(value)?
+            }
+            uci::AppConfigTlvType::MaxRrRetry => self.max_rr_retry = try_parse_u16(value)?,
+            uci::AppConfigTlvType::UwbInitiationTime => {
+                // Implement backward compatiblity for UCI 1.0
+                // where the value is 4 bytes instead of 8.
+                self.uwb_initiation_time = match value.len() {
+                    4 => try_parse_u32(value)? as u64,
+                    _ => try_parse_u64(value)?,
+                }
+            }
+            uci::AppConfigTlvType::HoppingMode => self.hopping_mode = try_parse(value)?,
+            uci::AppConfigTlvType::BlockStrideLength => {
+                self.block_stride_length = try_parse_u8(value)?
+            }
+            uci::AppConfigTlvType::ResultReportConfig => {
+                self.result_report_config = try_parse_u8(value)?
+            }
+            uci::AppConfigTlvType::InBandTerminationAttemptCount => {
+                self.in_band_termination_attempt_count = try_parse_u8(value)?
+            }
+            uci::AppConfigTlvType::SubSessionId => self.sub_session_id = try_parse_u32(value)?,
+            uci::AppConfigTlvType::BprfPhrDataRate => self.bprf_phr_data_rate = try_parse(value)?,
+            uci::AppConfigTlvType::MaxNumberOfMeasurements => {
+                self.max_number_of_measurements = try_parse_u16(value)?
+            }
+            uci::AppConfigTlvType::StsLength => self.sts_length = try_parse(value)?,
+            uci::AppConfigTlvType::MinFramesPerRr => self.min_frames_per_rr = try_parse_u8(value)?,
+            uci::AppConfigTlvType::MtuSize => self.mtu_size = try_parse_u16(value)?,
+            uci::AppConfigTlvType::InterFrameInterval => {
+                self.inter_frame_interval = try_parse_u8(value)?
+            }
+            uci::AppConfigTlvType::SessionKey => self.session_key = value.to_vec(),
+            uci::AppConfigTlvType::SubSessionKey => {
+                self.sub_session_key = match value.len() {
+                    16 => SubSessionKey::Short(value.try_into().unwrap()),
+                    32 => SubSessionKey::Extended(value.try_into().unwrap()),
+                    _ => anyhow::bail!("invalid sub-session key size {}", value.len()),
+                }
+            }
+            uci::AppConfigTlvType::SessionDataTransferStatusNtfConfig => {
+                self.session_data_transfer_status_ntf_config = try_parse(value)?
+            }
+            uci::AppConfigTlvType::SessionTimeBase => self.session_time_base = value.try_into()?,
+            uci::AppConfigTlvType::ApplicationDataEndpoint => {
+                self.application_data_endpoint = try_parse_u8(value)?
+            }
+
+            uci::AppConfigTlvType::CccHopModeKey
+            | uci::AppConfigTlvType::CccUwbTime0
+            | uci::AppConfigTlvType::CccRangingProtocolVer
+            | uci::AppConfigTlvType::CccUwbConfigId
+            | uci::AppConfigTlvType::CccPulseshapeCombo
+            | uci::AppConfigTlvType::CccUrskTtl
+            | uci::AppConfigTlvType::CccLastIndexUsed
+            | uci::AppConfigTlvType::NbOfRangeMeasurements
+            | uci::AppConfigTlvType::NbOfAzimuthMeasurements
+            | uci::AppConfigTlvType::NbOfElevationMeasurements
+            | uci::AppConfigTlvType::EnableDiagnostics
+            | uci::AppConfigTlvType::DiagramsFrameReportsFields => {
+                log::error!("unsupported vendor config type {:?}", id);
+                anyhow::bail!("unsupported vendor config type {:?}", id)
+            }
+            _ => {
+                log::error!("unsupported app config type {:?}", id);
+                anyhow::bail!("unsupported app config type {:?}", id)
+            }
+        }
+        Ok(())
+    }
+
+    /// Retrieve the APP configuration value with the selected identifier
+    /// Returns `Ok` if the identifier is known, `Err` otherwise.
+    pub fn get(&self, id: uci::AppConfigTlvType) -> anyhow::Result<Vec<u8>> {
+        match id {
+            uci::AppConfigTlvType::DeviceType => Ok(vec![self
+                .device_type
+                .ok_or(anyhow::anyhow!("optional app config not set"))?
+                .into()]),
+            uci::AppConfigTlvType::RangingRoundUsage => Ok(vec![self
+                .ranging_round_usage
+                .ok_or(anyhow::anyhow!("optional app config not set"))?
+                .into()]),
+            uci::AppConfigTlvType::StsConfig => Ok(vec![self.sts_config.into()]),
+            uci::AppConfigTlvType::MultiNodeMode => Ok(vec![self
+                .multi_node_mode
+                .ok_or(anyhow::anyhow!("optional app config not set"))?
+                .into()]),
+            uci::AppConfigTlvType::ChannelNumber => Ok(vec![self.channel_number.into()]),
+            uci::AppConfigTlvType::NumberOfControlees => Ok(vec![self.number_of_controlees]),
+            uci::AppConfigTlvType::DeviceMacAddress => Ok(self
+                .device_mac_address
+                .ok_or(anyhow::anyhow!("optional app config not set"))?
+                .into()),
+            uci::AppConfigTlvType::DstMacAddress => Ok(self
+                .dst_mac_address
+                .iter()
+                .flat_map(Vec::<u8>::from)
+                .collect()),
+            uci::AppConfigTlvType::SlotDuration => Ok(self.slot_duration.to_le_bytes().to_vec()),
+            uci::AppConfigTlvType::RangingDuration => {
+                Ok(self.ranging_duration.to_le_bytes().to_vec())
+            }
+            uci::AppConfigTlvType::StsIndex => Ok(self.sts_index.to_le_bytes().to_vec()),
+            uci::AppConfigTlvType::MacFcsType => Ok(vec![self.mac_fcs_type.into()]),
+            uci::AppConfigTlvType::RangingRoundControl => Ok(vec![self.ranging_round_control]),
+            uci::AppConfigTlvType::AoaResultReq => Ok(vec![self.aoa_result_req.into()]),
+            uci::AppConfigTlvType::SessionInfoNtfConfig => {
+                Ok(vec![self.session_info_ntf_config.into()])
+            }
+            uci::AppConfigTlvType::NearProximityConfig => {
+                Ok(self.near_proximity_config.to_le_bytes().to_vec())
+            }
+            uci::AppConfigTlvType::FarProximityConfig => {
+                Ok(self.far_proximity_config.to_le_bytes().to_vec())
+            }
+            uci::AppConfigTlvType::DeviceRole => Ok(vec![self
+                .device_role
+                .ok_or(anyhow::anyhow!("optional app config not set"))?
+                .into()]),
+            uci::AppConfigTlvType::RframeConfig => Ok(vec![self.rframe_config.into()]),
+            uci::AppConfigTlvType::RssiReporting => Ok(vec![self.rssi_reporting.into()]),
+            uci::AppConfigTlvType::PreambleCodeIndex => Ok(vec![self.preamble_code_index]),
+            uci::AppConfigTlvType::SfdId => Ok(vec![self.sfd_id]),
+            uci::AppConfigTlvType::PsduDataRate => Ok(vec![self.psdu_data_rate.into()]),
+            uci::AppConfigTlvType::PreambleDuration => Ok(vec![self.preamble_duration.into()]),
+            uci::AppConfigTlvType::LinkLayerMode => Ok(vec![self.link_layer_mode.into()]),
+            uci::AppConfigTlvType::DataRepetitionCount => Ok(vec![self.data_repetition_count]),
+            uci::AppConfigTlvType::RangingTimeStruct => Ok(vec![self.ranging_time_struct.into()]),
+            uci::AppConfigTlvType::SlotsPerRr => Ok(vec![self.slots_per_rr]),
+            uci::AppConfigTlvType::AoaBoundConfig => Ok(self
+                .aoa_bound_config
+                .iter()
+                .copied()
+                .flat_map(u16::to_le_bytes)
+                .collect()),
+            uci::AppConfigTlvType::PrfMode => Ok(vec![self.prf_mode.into()]),
+            uci::AppConfigTlvType::CapSizeRange => Ok(self.cap_size_range.to_vec()),
+            uci::AppConfigTlvType::TxJitterWindowSize => Ok(vec![self.tx_jitter_window_size]),
+            uci::AppConfigTlvType::ScheduleMode => Ok(vec![self
+                .schedule_mode
+                .ok_or(anyhow::anyhow!("optional app config not set"))?
+                .into()]),
+            uci::AppConfigTlvType::KeyRotation => Ok(vec![self.key_rotation.into()]),
+            uci::AppConfigTlvType::KeyRotationRate => Ok(vec![self.key_rotation_rate]),
+            uci::AppConfigTlvType::SessionPriority => Ok(vec![self.session_priority]),
+            uci::AppConfigTlvType::MacAddressMode => Ok(vec![self.mac_address_mode.into()]),
+            uci::AppConfigTlvType::VendorId => Ok(self.vendor_id.to_le_bytes().to_vec()),
+            uci::AppConfigTlvType::StaticStsIv => Ok(self.static_sts_iv.to_vec()),
+            uci::AppConfigTlvType::NumberOfStsSegments => Ok(vec![self.number_of_sts_segments]),
+            uci::AppConfigTlvType::MaxRrRetry => Ok(self.max_rr_retry.to_le_bytes().to_vec()),
+            uci::AppConfigTlvType::UwbInitiationTime => {
+                Ok(self.uwb_initiation_time.to_le_bytes().to_vec())
+            }
+            uci::AppConfigTlvType::HoppingMode => Ok(vec![self.hopping_mode.into()]),
+            uci::AppConfigTlvType::BlockStrideLength => Ok(vec![self.block_stride_length]),
+            uci::AppConfigTlvType::ResultReportConfig => Ok(vec![self.result_report_config]),
+            uci::AppConfigTlvType::InBandTerminationAttemptCount => {
+                Ok(vec![self.in_band_termination_attempt_count])
+            }
+            uci::AppConfigTlvType::SubSessionId => Ok(self.sub_session_id.to_le_bytes().to_vec()),
+            uci::AppConfigTlvType::BprfPhrDataRate => Ok(vec![self.bprf_phr_data_rate.into()]),
+            uci::AppConfigTlvType::MaxNumberOfMeasurements => {
+                Ok(self.max_number_of_measurements.to_le_bytes().to_vec())
+            }
+            uci::AppConfigTlvType::StsLength => Ok(vec![self.sts_length.into()]),
+            uci::AppConfigTlvType::MinFramesPerRr => Ok(vec![self.min_frames_per_rr]),
+            uci::AppConfigTlvType::MtuSize => Ok(self.mtu_size.to_le_bytes().to_vec()),
+            uci::AppConfigTlvType::InterFrameInterval => Ok(vec![self.inter_frame_interval]),
+            uci::AppConfigTlvType::SessionKey => Ok(self.session_key.clone()),
+            uci::AppConfigTlvType::SubSessionKey => Ok(match self.sub_session_key {
+                SubSessionKey::None => vec![],
+                SubSessionKey::Short(key) => key.to_vec(),
+                SubSessionKey::Extended(key) => key.to_vec(),
+            }),
+            uci::AppConfigTlvType::SessionDataTransferStatusNtfConfig => {
+                Ok(vec![self.session_data_transfer_status_ntf_config.into()])
+            }
+            uci::AppConfigTlvType::SessionTimeBase => Ok(self.session_time_base.to_vec()),
+            uci::AppConfigTlvType::ApplicationDataEndpoint => {
+                Ok(vec![self.application_data_endpoint])
+            }
+
+            uci::AppConfigTlvType::CccHopModeKey
+            | uci::AppConfigTlvType::CccUwbTime0
+            | uci::AppConfigTlvType::CccRangingProtocolVer
+            | uci::AppConfigTlvType::CccUwbConfigId
+            | uci::AppConfigTlvType::CccPulseshapeCombo
+            | uci::AppConfigTlvType::CccUrskTtl
+            | uci::AppConfigTlvType::CccLastIndexUsed
+            | uci::AppConfigTlvType::NbOfRangeMeasurements
+            | uci::AppConfigTlvType::NbOfAzimuthMeasurements
+            | uci::AppConfigTlvType::NbOfElevationMeasurements
+            | uci::AppConfigTlvType::EnableDiagnostics
+            | uci::AppConfigTlvType::DiagramsFrameReportsFields => {
+                log::error!("unsupported vendor config type {:?}", id);
+                anyhow::bail!("unsupported vendor config type {:?}", id)
+            }
+            _ => {
+                log::error!("unsupported app config type {:?}", id);
+                anyhow::bail!("unsupported app config type {:?}", id)
+            }
+        }
+    }
+
+    pub fn is_compatible_for_ranging(&self, peer_config: &Self) -> bool {
+        self.device_role != peer_config.device_role
+            && self.device_type != peer_config.device_type
+            && peer_config
+                .dst_mac_address
+                .contains(&self.device_mac_address.unwrap())
+            && self
+                .dst_mac_address
+                .contains(&peer_config.device_mac_address.unwrap())
+    }
+
+    pub fn can_start_data_transfer(&self) -> bool {
+        self.device_role == Some(uci::DeviceRole::Initiator)
+    }
+
+    pub fn can_receive_data_transfer(&self) -> bool {
+        self.device_role == Some(uci::DeviceRole::Responder)
+    }
+}
diff --git a/src/device.rs b/src/device.rs
index 48d2bd2..eec1c7f 100644
--- a/src/device.rs
+++ b/src/device.rs
@@ -12,27 +12,31 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-use crate::packets::uci::*;
+use crate::packets::uci::{self, *};
 use crate::MacAddress;
 use crate::PicaCommand;
 
 use std::collections::HashMap;
-use std::iter::Extend;
 use std::time::Duration;
 
 use tokio::sync::mpsc;
 use tokio::time;
 
-use super::session::{Session, MAX_SESSION};
+use super::app_config::SubSessionKey;
+use super::session::Session;
 use super::UciPacket;
 
 pub const MAX_DEVICE: usize = 4;
+pub const MAX_SESSION: usize = 255;
 
 const UCI_VERSION: u16 = 0x0002; // Version 2.0
 const MAC_VERSION: u16 = 0x3001; // Version 1.3.0
 const PHY_VERSION: u16 = 0x3001; // Version 1.3.0
 const TEST_VERSION: u16 = 0x1001; // Version 1.1
 
+/// cf. [UCI] 8.3 Table 29
+pub const MAX_NUMBER_OF_CONTROLEES: usize = 8;
+
 // Capabilities are vendor defined
 // Android compliant: FIRA-287 UCI_Generic_Specification controlee capabilities_r4
 // Android parses capabilities, according to these definitions:
@@ -72,15 +76,36 @@
     ),
 ];
 
+/// [UCI] 8.2 Device Configuration Parameters
+pub struct DeviceConfig {
+    device_state: DeviceState,
+    // This config is used to enable/disable the low power mode.
+    //   0x00 = Disable low power mode
+    //   0x01 = Enable low power mode (default)
+    low_power_mode: bool,
+}
+
+// [UCI] 6.3.1 Setting the Configuration
+// All device configuration parameters within the UWBS are set to
+// default values at Table 44 [..].
+impl Default for DeviceConfig {
+    fn default() -> Self {
+        DeviceConfig {
+            device_state: DeviceState::DeviceStateError,
+            low_power_mode: true,
+        }
+    }
+}
+
 pub struct Device {
     pub handle: usize,
     pub mac_address: MacAddress,
+    config: DeviceConfig,
     /// [UCI] 5. UWBS Device State Machine
     state: DeviceState,
     sessions: HashMap<u32, Session>,
     pub tx: mpsc::UnboundedSender<UciPacket>,
     pica_tx: mpsc::Sender<PicaCommand>,
-    config: HashMap<DeviceConfigId, Vec<u8>>,
     country_code: [u8; 2],
 
     pub n_active_sessions: usize,
@@ -96,11 +121,11 @@
         Device {
             handle,
             mac_address,
+            config: Default::default(),
             state: DeviceState::DeviceStateError, // Will be overwitten
             sessions: Default::default(),
             tx,
             pica_tx,
-            config: HashMap::new(),
             country_code: Default::default(),
             n_active_sessions: 0,
         }
@@ -117,7 +142,7 @@
         let tx = self.tx.clone();
         tokio::spawn(async move {
             time::sleep(Duration::from_millis(5)).await;
-            tx.send(DeviceStatusNtfBuilder { device_state }.build().into())
+            tx.send(CoreDeviceStatusNtfBuilder { device_state }.build().into())
                 .unwrap()
         });
     }
@@ -175,13 +200,13 @@
 
     // The fira norm specify to send a response, then reset, then
     // send a notification once the reset is done
-    fn command_device_reset(&mut self, cmd: DeviceResetCmd) -> DeviceResetRsp {
+    fn core_device_reset(&mut self, cmd: CoreDeviceResetCmd) -> CoreDeviceResetRsp {
         let reset_config = cmd.get_reset_config();
         log::debug!("[{}] DeviceReset", self.handle);
         log::debug!("  reset_config={:?}", reset_config);
 
         let status = match reset_config {
-            ResetConfig::UwbsReset => StatusCode::UciStatusOk,
+            ResetConfig::UwbsReset => uci::Status::Ok,
         };
         *self = Device::new(
             self.handle,
@@ -191,15 +216,15 @@
         );
         self.init();
 
-        DeviceResetRspBuilder { status }.build()
+        CoreDeviceResetRspBuilder { status }.build()
     }
 
-    fn command_get_device_info(&self, _cmd: GetDeviceInfoCmd) -> GetDeviceInfoRsp {
+    fn core_get_device_info(&self, _cmd: CoreGetDeviceInfoCmd) -> CoreGetDeviceInfoRsp {
         // TODO: Implement a fancy build time state machine instead of crash at runtime
         log::debug!("[{}] GetDeviceInfo", self.handle);
         assert_eq!(self.state, DeviceState::DeviceStateReady);
-        GetDeviceInfoRspBuilder {
-            status: StatusCode::UciStatusOk,
+        CoreGetDeviceInfoRspBuilder {
+            status: uci::Status::Ok,
             uci_version: UCI_VERSION,
             mac_version: MAC_VERSION,
             phy_version: PHY_VERSION,
@@ -209,7 +234,7 @@
         .build()
     }
 
-    pub fn command_get_caps_info(&self, _cmd: GetCapsInfoCmd) -> GetCapsInfoRsp {
+    pub fn core_get_caps_info(&self, _cmd: CoreGetCapsInfoCmd) -> CoreGetCapsInfoRsp {
         log::debug!("[{}] GetCapsInfo", self.handle);
 
         let caps = DEFAULT_CAPS_INFO
@@ -220,86 +245,101 @@
             })
             .collect();
 
-        GetCapsInfoRspBuilder {
-            status: StatusCode::UciStatusOk,
+        CoreGetCapsInfoRspBuilder {
+            status: uci::Status::Ok,
             tlvs: caps,
         }
         .build()
     }
 
-    pub fn command_set_config(&mut self, cmd: SetConfigCmd) -> SetConfigRsp {
+    pub fn core_set_config(&mut self, cmd: CoreSetConfigCmd) -> CoreSetConfigRsp {
         log::debug!("[{}] SetConfig", self.handle);
         assert_eq!(self.state, DeviceState::DeviceStateReady); // UCI 6.3
 
-        let (valid_parameters, invalid_config_status) = cmd.get_tlvs().iter().fold(
-            (HashMap::new(), Vec::new()),
-            |(mut valid_parameters, invalid_config_status), param| {
-                // TODO: DeviceState is a read only parameter
-                valid_parameters.insert(param.cfg_id, param.v.clone());
+        // [UCI] 6.3.1 Setting the Configuration
+        // The UWBS shall respond with CORE_SET_CONFIG_RSP setting the Status
+        // field of STATUS_INVALID_PARAM and including one or more invalid
+        // Parameter ID(s) If the Host tries to set a parameter that is not
+        // available in the UWBS. All other configuration parameters should
+        // have been set to the new values within the UWBS.
+        let mut invalid_parameters = vec![];
+        for parameter in cmd.get_parameters() {
+            match parameter.id {
+                uci::ConfigParameterId::DeviceState => {
+                    invalid_parameters.push(uci::ConfigParameterStatus {
+                        id: parameter.id,
+                        status: uci::Status::ReadOnly,
+                    })
+                }
+                uci::ConfigParameterId::LowPowerMode => {
+                    self.config.low_power_mode = parameter.value.first().copied().unwrap_or(1) != 0;
+                }
+                uci::ConfigParameterId::Rfu(id) => {
+                    log::warn!("unknown config parameter id 0x{:02x}", *id);
+                    invalid_parameters.push(uci::ConfigParameterStatus {
+                        id: parameter.id,
+                        status: uci::Status::InvalidParam,
+                    })
+                }
+            }
+        }
 
-                (valid_parameters, invalid_config_status)
+        CoreSetConfigRspBuilder {
+            status: if invalid_parameters.is_empty() {
+                uci::Status::Ok
+            } else {
+                uci::Status::InvalidParam
             },
-        );
-
-        let (status, parameters) = if invalid_config_status.is_empty() {
-            self.config.extend(valid_parameters);
-            (StatusCode::UciStatusOk, Vec::new())
-        } else {
-            (StatusCode::UciStatusInvalidParam, invalid_config_status)
-        };
-
-        SetConfigRspBuilder {
-            cfg_status: parameters,
-            status,
+            parameters: invalid_parameters,
         }
         .build()
     }
 
-    pub fn command_get_config(&self, cmd: GetConfigCmd) -> GetConfigRsp {
+    pub fn core_get_config(&self, cmd: CoreGetConfigCmd) -> CoreGetConfigRsp {
         log::debug!("[{}] GetConfig", self.handle);
 
-        // TODO: do this config shall be set on device reset
-        let ids = cmd.get_cfg_id();
-        let (valid_parameters, invalid_parameters) = ids.iter().fold(
-            (Vec::new(), Vec::new()),
-            |(mut valid_parameters, mut invalid_parameters), id| {
-                // UCI Core Section 6.3.2 Table 8
-                // UCI Core Section 6.3.2 - Return the Configuration
-                // If the status code is ok, return the params
-                // If there is at least one invalid param, return the list of invalid params
-                // If the ID is not present in our config, return the Type with length = 0
-                match DeviceConfigId::try_from(*id) {
-                    Ok(cfg_id) => match self.config.get(&cfg_id) {
-                        Some(value) => valid_parameters.push(DeviceConfigTlv {
-                            cfg_id,
-                            v: value.clone(),
-                        }),
-                        None => invalid_parameters.push(DeviceConfigTlv {
-                            cfg_id,
-                            v: Vec::new(),
-                        }),
-                    },
-                    Err(_) => log::error!("Failed to parse config id: {:?}", id),
-                }
-
-                (valid_parameters, invalid_parameters)
-            },
-        );
-
-        let (status, parameters) = if invalid_parameters.is_empty() {
-            (StatusCode::UciStatusOk, valid_parameters)
-        } else {
-            (StatusCode::UciStatusInvalidParam, invalid_parameters)
-        };
-
-        GetConfigRspBuilder {
-            status,
-            tlvs: parameters,
+        // [UCI] 6.3.2 Retrieve the Configuration
+        // If the Host tries to retrieve any Parameter(s) that are not available
+        // in the UWBS, the UWBS shall respond with a CORE_GET_CONFIG_RSP with
+        // a Status field of STATUS_INVALID_PARAM, containing each unavailable
+        // Device Configuration Parameter Type with Length field is zero. In
+        // this case, the CORE_GET_CONFIG_RSP shall not include any parameter(s)
+        // that are available in the UWBS.
+        let mut valid_parameters = vec![];
+        let mut invalid_parameters = vec![];
+        for id in cmd.get_parameter_ids() {
+            match id {
+                ConfigParameterId::DeviceState => valid_parameters.push(ConfigParameter {
+                    id: *id,
+                    value: vec![self.config.device_state.into()],
+                }),
+                ConfigParameterId::LowPowerMode => valid_parameters.push(ConfigParameter {
+                    id: *id,
+                    value: vec![self.config.low_power_mode.into()],
+                }),
+                ConfigParameterId::Rfu(_) => invalid_parameters.push(ConfigParameter {
+                    id: *id,
+                    value: vec![],
+                }),
+            }
         }
-        .build()
+
+        if invalid_parameters.is_empty() {
+            CoreGetConfigRspBuilder {
+                status: uci::Status::Ok,
+                parameters: valid_parameters,
+            }
+            .build()
+        } else {
+            CoreGetConfigRspBuilder {
+                status: uci::Status::InvalidParam,
+                parameters: invalid_parameters,
+            }
+            .build()
+        }
     }
 
-    fn command_session_init(&mut self, cmd: SessionInitCmd) -> SessionInitRsp {
+    fn session_init(&mut self, cmd: SessionInitCmd) -> SessionInitRsp {
         let session_id = cmd.get_session_id();
         let session_type = cmd.get_session_type();
 
@@ -308,23 +348,17 @@
         log::debug!("  session_type={:?}", session_type);
 
         let status = if self.sessions.len() >= MAX_SESSION {
-            StatusCode::UciStatusMaxSessionsExceeded
+            uci::Status::ErrorMaxSessionsExceeded
         } else {
             match self.sessions.insert(
                 session_id,
-                Session::new(
-                    session_id,
-                    session_type,
-                    self.handle,
-                    self.tx.clone(),
-                    self.pica_tx.clone(),
-                ),
+                Session::new(session_id, session_type, self.handle, self.tx.clone()),
             ) {
-                Some(_) => StatusCode::UciStatusSessionDuplicate,
+                Some(_) => uci::Status::ErrorSessionDuplicate,
                 None => {
                     // Should not fail
                     self.session_mut(session_id).unwrap().init();
-                    StatusCode::UciStatusOk
+                    uci::Status::Ok
                 }
             }
         };
@@ -332,7 +366,7 @@
         SessionInitRspBuilder { status }.build()
     }
 
-    fn command_session_deinit(&mut self, cmd: SessionDeinitCmd) -> SessionDeinitRsp {
+    fn session_deinit(&mut self, cmd: SessionDeinitCmd) -> SessionDeinitRsp {
         let session_id = cmd.get_session_token();
         log::debug!("[{}] Session deinit", self.handle);
         log::debug!("  session_id=0x{:x}", session_id);
@@ -346,24 +380,499 @@
                     }
                 }
                 self.sessions.remove(&session_id);
-                StatusCode::UciStatusOk
+                uci::Status::Ok
             }
-            None => StatusCode::UciStatusSessionNotExist,
+            None => uci::Status::ErrorSessionNotExist,
         };
         SessionDeinitRspBuilder { status }.build()
     }
 
-    fn command_session_get_count(&self, _cmd: SessionGetCountCmd) -> SessionGetCountRsp {
+    fn session_get_count(&self, _cmd: SessionGetCountCmd) -> SessionGetCountRsp {
         log::debug!("[{}] Session get count", self.handle);
 
         SessionGetCountRspBuilder {
-            status: StatusCode::UciStatusOk,
+            status: uci::Status::Ok,
             session_count: self.sessions.len() as u8,
         }
         .build()
     }
 
-    fn command_set_country_code(
+    fn session_set_app_config(&mut self, cmd: SessionSetAppConfigCmd) -> SessionSetAppConfigRsp {
+        let session_handle = cmd.get_session_token();
+
+        log::debug!(
+            "[{}:0x{:x}] Session Set App Config",
+            self.handle,
+            session_handle
+        );
+
+        let Some(session) = self.sessions.get_mut(&session_handle) else {
+            return SessionSetAppConfigRspBuilder {
+                cfg_status: Vec::new(),
+                status: uci::Status::ErrorSessionNotExist,
+            }
+            .build();
+        };
+
+        assert!(
+            session.session_type == SessionType::FiraRangingSession
+                || session.session_type == SessionType::FiraRangingAndInBandDataSession
+        );
+
+        if session.state == SessionState::SessionStateActive {
+            const IMMUTABLE_PARAMETERS: &[AppConfigTlvType] = &[AppConfigTlvType::AoaResultReq];
+            if cmd
+                .get_tlvs()
+                .iter()
+                .any(|cfg| IMMUTABLE_PARAMETERS.contains(&cfg.cfg_id))
+            {
+                return SessionSetAppConfigRspBuilder {
+                    status: uci::Status::ErrorSessionActive,
+                    cfg_status: vec![],
+                }
+                .build();
+            }
+        }
+
+        let (status, invalid_parameters) = if session.state != SessionState::SessionStateInit
+            && session.state != SessionState::SessionStateActive
+        {
+            (uci::Status::Rejected, Vec::new())
+        } else {
+            let mut app_config = session.app_config.clone();
+            let mut invalid_parameters = vec![];
+            for cfg in cmd.get_tlvs() {
+                match app_config.set(cfg.cfg_id, &cfg.v) {
+                    Ok(_) => (),
+                    Err(_) => invalid_parameters.push(AppConfigStatus {
+                        cfg_id: cfg.cfg_id,
+                        status: uci::Status::InvalidParam,
+                    }),
+                }
+            }
+
+            // [UCI] 7.5.1 Configuration of a Session
+            // This section defines the mandatory APP Configuration Parameters to be applied
+            // by the Host for FiRa defined UWB Session types. The Host shall apply these
+            // mandatory configurations to move the Session State from SESSION_STATE_INIT
+            // to SESSION_STATE_IDLE.
+            //
+            // - DEVICE_ROLE
+            // - MULTI_NODE_MODE
+            // - RANGING_ROUND_USAGE
+            // - DEVICE_MAC_ADDRESS
+            // - DEVICE_TYPE (see Note1)
+            // - SCHEDULE_MODE
+            if app_config.device_role.is_none()
+                || app_config.multi_node_mode.is_none()
+                || app_config.ranging_round_usage.is_none()
+                || app_config.device_mac_address.is_none()
+                || app_config.schedule_mode.is_none()
+            {
+                log::error!(
+                    "[{}:0x{:x}] missing mandatory APP config parameters",
+                    self.handle,
+                    session_handle
+                );
+                return SessionSetAppConfigRspBuilder {
+                    status: uci::Status::Rejected,
+                    cfg_status: vec![],
+                }
+                .build();
+            }
+
+            if invalid_parameters.is_empty() {
+                session.app_config = app_config;
+                if session.state == SessionState::SessionStateInit {
+                    session.set_state(
+                        SessionState::SessionStateIdle,
+                        ReasonCode::StateChangeWithSessionManagementCommands,
+                    );
+                }
+                (uci::Status::Ok, invalid_parameters)
+            } else {
+                (uci::Status::InvalidParam, invalid_parameters)
+            }
+        };
+
+        SessionSetAppConfigRspBuilder {
+            status,
+            cfg_status: invalid_parameters,
+        }
+        .build()
+    }
+
+    fn session_get_app_config(&self, cmd: SessionGetAppConfigCmd) -> SessionGetAppConfigRsp {
+        let session_handle = cmd.get_session_token();
+
+        log::debug!(
+            "[{}:0x{:x}] Session Get App Config",
+            self.handle,
+            session_handle
+        );
+
+        let Some(session) = self.sessions.get(&session_handle) else {
+            return SessionGetAppConfigRspBuilder {
+                tlvs: vec![],
+                status: uci::Status::ErrorSessionNotExist,
+            }
+            .build();
+        };
+
+        let (status, valid_parameters) = {
+            let mut valid_parameters = vec![];
+            let mut invalid_parameters = vec![];
+            for id in cmd.get_app_cfg() {
+                match session.app_config.get(*id) {
+                    Ok(value) => valid_parameters.push(AppConfigTlv {
+                        cfg_id: *id,
+                        v: value,
+                    }),
+                    Err(_) => invalid_parameters.push(AppConfigTlv {
+                        cfg_id: *id,
+                        v: vec![],
+                    }),
+                }
+            }
+
+            if invalid_parameters.is_empty() {
+                (uci::Status::Ok, valid_parameters)
+            } else {
+                (uci::Status::Failed, Vec::new())
+            }
+        };
+
+        SessionGetAppConfigRspBuilder {
+            status,
+            tlvs: valid_parameters,
+        }
+        .build()
+    }
+
+    fn session_get_state(&self, cmd: SessionGetStateCmd) -> SessionGetStateRsp {
+        let session_handle = cmd.get_session_token();
+
+        log::debug!("[{}:0x{:x}] Session Get State", self.handle, session_handle);
+
+        let Some(session) = self.sessions.get(&session_handle) else {
+            return SessionGetStateRspBuilder {
+                session_state: SessionState::SessionStateInit,
+                status: uci::Status::ErrorSessionNotExist,
+            }
+            .build();
+        };
+
+        SessionGetStateRspBuilder {
+            status: uci::Status::Ok,
+            session_state: session.state,
+        }
+        .build()
+    }
+
+    fn session_update_controller_multicast_list(
+        &mut self,
+        cmd: SessionUpdateControllerMulticastListCmd,
+    ) -> SessionUpdateControllerMulticastListRsp {
+        let session_handle = cmd.get_session_token();
+
+        log::debug!(
+            "[{}:0x{:x}] Session Update Controller Multicast List",
+            self.handle,
+            session_handle
+        );
+
+        let Some(session) = self.sessions.get_mut(&session_handle) else {
+            return SessionUpdateControllerMulticastListRspBuilder {
+                status: uci::Status::ErrorSessionNotExist,
+            }
+            .build();
+        };
+
+        if (session.state != SessionState::SessionStateActive
+            && session.state != SessionState::SessionStateIdle)
+            || session.app_config.device_type != Some(DeviceType::Controller)
+            || session.app_config.multi_node_mode != Some(MultiNodeMode::OneToMany)
+        {
+            return SessionUpdateControllerMulticastListRspBuilder {
+                status: uci::Status::Rejected,
+            }
+            .build();
+        }
+        let action = cmd.get_action();
+        let mut dst_addresses = session.app_config.dst_mac_address.clone();
+        let new_controlees: Vec<Controlee> = match action {
+            UpdateMulticastListAction::AddControlee
+            | UpdateMulticastListAction::RemoveControlee => {
+                if let Ok(packet) =
+                    SessionUpdateControllerMulticastListCmdPayload::parse(cmd.get_payload())
+                {
+                    packet
+                        .controlees
+                        .iter()
+                        .map(|controlee| controlee.into())
+                        .collect()
+                } else {
+                    return SessionUpdateControllerMulticastListRspBuilder {
+                        status: uci::Status::SyntaxError,
+                    }
+                    .build();
+                }
+            }
+            UpdateMulticastListAction::AddControleeWithShortSubSessionKey => {
+                if let Ok(packet) =
+                    SessionUpdateControllerMulticastListCmd_2_0_16_Byte_Payload::parse(
+                        cmd.get_payload(),
+                    )
+                {
+                    packet
+                        .controlees
+                        .iter()
+                        .map(|controlee| controlee.into())
+                        .collect()
+                } else {
+                    return SessionUpdateControllerMulticastListRspBuilder {
+                        status: uci::Status::SyntaxError,
+                    }
+                    .build();
+                }
+            }
+            UpdateMulticastListAction::AddControleeWithExtendedSubSessionKey => {
+                if let Ok(packet) =
+                    SessionUpdateControllerMulticastListCmd_2_0_32_Byte_Payload::parse(
+                        cmd.get_payload(),
+                    )
+                {
+                    packet
+                        .controlees
+                        .iter()
+                        .map(|controlee| controlee.into())
+                        .collect()
+                } else {
+                    return SessionUpdateControllerMulticastListRspBuilder {
+                        status: uci::Status::SyntaxError,
+                    }
+                    .build();
+                }
+            }
+        };
+        let mut controlee_status = Vec::new();
+        let mut status = uci::Status::Ok;
+
+        match action {
+            UpdateMulticastListAction::AddControlee
+            | UpdateMulticastListAction::AddControleeWithShortSubSessionKey
+            | UpdateMulticastListAction::AddControleeWithExtendedSubSessionKey => {
+                new_controlees.iter().for_each(|controlee| {
+                    let mut update_status = MulticastUpdateStatus::OkMulticastListUpdate;
+                    if !dst_addresses.contains(&controlee.short_address) {
+                        if dst_addresses.len() == MAX_NUMBER_OF_CONTROLEES {
+                            status = uci::Status::ErrorMulticastListFull;
+                            update_status = MulticastUpdateStatus::ErrorMulticastListFull;
+                        } else if (action
+                            == UpdateMulticastListAction::AddControleeWithShortSubSessionKey
+                            || action
+                                == UpdateMulticastListAction::AddControleeWithExtendedSubSessionKey)
+                            && session.app_config.sts_config
+                                != uci::StsConfig::ProvisionedForResponderSubSessionKey
+                        {
+                            // If Action is 0x02 or 0x03 for STS_CONFIG values other than
+                            // 0x04, the UWBS shall return SESSION_UPDATE_CONTROLLER_MULTICAST_LIST_NTF
+                            // with Status set to STATUS_ERROR_SUB_SESSION_KEY_NOT_APPLICABLE for each
+                            // Controlee in the Controlee List.
+                            status = uci::Status::Failed;
+                            update_status = MulticastUpdateStatus::ErrorSubSessionKeyNotApplicable;
+                        } else {
+                            dst_addresses.push(controlee.short_address);
+                        };
+                    }
+                    controlee_status.push(ControleeStatus {
+                        mac_address: match controlee.short_address {
+                            MacAddress::Short(address) => address,
+                            MacAddress::Extended(_) => panic!("Extended address is not supported!"),
+                        },
+                        status: update_status,
+                    });
+                });
+            }
+            UpdateMulticastListAction::RemoveControlee => {
+                new_controlees.iter().for_each(|controlee: &Controlee| {
+                    let pica_tx = self.pica_tx.clone();
+                    let address = controlee.short_address;
+                    let attempt_count = session.app_config.in_band_termination_attempt_count;
+                    let mut update_status = MulticastUpdateStatus::OkMulticastListUpdate;
+                    if !dst_addresses.contains(&address) {
+                        status = uci::Status::Failed;
+                        update_status = MulticastUpdateStatus::ErrorKeyFetchFail;
+                    } else {
+                        dst_addresses.retain(|value| *value != address);
+                        // If IN_BAND_TERMINATION_ATTEMPT_COUNT is not equal to 0x00, then the
+                        // UWBS shall transmit the RCM with the “Stop Ranging” bit set to ‘1’
+                        // for IN_BAND_TERMINATION_ATTEMPT_COUNT times to the corresponding
+                        // Controlee.
+                        if attempt_count != 0 {
+                            tokio::spawn(async move {
+                                for _ in 0..attempt_count {
+                                    pica_tx
+                                        .send(PicaCommand::StopRanging(address, session_handle))
+                                        .await
+                                        .unwrap()
+                                }
+                            });
+                        }
+                    }
+                    controlee_status.push(ControleeStatus {
+                        mac_address: match address {
+                            MacAddress::Short(addr) => addr,
+                            MacAddress::Extended(_) => panic!("Extended address is not supported!"),
+                        },
+                        status: update_status,
+                    });
+                });
+            }
+        }
+        session.app_config.number_of_controlees = dst_addresses.len() as u8;
+        session.app_config.dst_mac_address = dst_addresses.clone();
+        // If the multicast list becomes empty, the UWBS shall move the session to
+        // SESSION_STATE_IDLE by sending the SESSION_STATUS_NTF with Reason Code
+        // set to ERROR_INVALID_NUM_OF_CONTROLEES.
+        if session.app_config.dst_mac_address.is_empty() {
+            session.set_state(
+                SessionState::SessionStateIdle,
+                ReasonCode::ErrorInvalidNumOfControlees,
+            )
+        }
+        let tx = self.tx.clone();
+        tokio::spawn(async move {
+            // Sleep for 5ms to make sure the notification is not being
+            // sent before the response.
+            // TODO(#84) remove the sleep.
+            time::sleep(Duration::from_millis(5)).await;
+            tx.send(
+                SessionUpdateControllerMulticastListNtfBuilder {
+                    controlee_status,
+                    session_token: session_handle,
+                }
+                .build()
+                .into(),
+            )
+            .unwrap()
+        });
+        SessionUpdateControllerMulticastListRspBuilder { status }.build()
+    }
+
+    fn session_start(&mut self, cmd: SessionStartCmd) -> SessionStartRsp {
+        let session_id = cmd.get_session_id();
+
+        log::debug!("[{}:0x{:x}] Session Start", self.handle, session_id);
+
+        let Some(session) = self.sessions.get_mut(&session_id) else {
+            return SessionStartRspBuilder {
+                status: uci::Status::ErrorSessionNotExist,
+            }
+            .build();
+        };
+
+        if session.state != SessionState::SessionStateIdle {
+            return SessionStartRspBuilder {
+                status: uci::Status::ErrorSessionNotConfigured,
+            }
+            .build();
+        }
+
+        assert!(session.ranging_task.is_none());
+
+        let ranging_interval =
+            time::Duration::from_millis(session.app_config.ranging_duration as u64);
+
+        let tx = self.pica_tx.clone();
+        let handle = self.handle;
+        session.ranging_task = Some(tokio::spawn(async move {
+            loop {
+                time::sleep(ranging_interval).await;
+                tx.send(PicaCommand::Ranging(handle, session_id))
+                    .await
+                    .unwrap();
+            }
+        }));
+
+        session.set_state(
+            SessionState::SessionStateActive,
+            ReasonCode::StateChangeWithSessionManagementCommands,
+        );
+
+        self.n_active_sessions += 1;
+        self.set_state(DeviceState::DeviceStateActive);
+
+        SessionStartRspBuilder {
+            status: uci::Status::Ok,
+        }
+        .build()
+    }
+
+    fn session_stop(&mut self, cmd: SessionStopCmd) -> SessionStopRsp {
+        let session_id = cmd.get_session_id();
+
+        log::debug!("[{}:0x{:x}] Session Stop", self.handle, session_id);
+
+        let Some(session) = self.sessions.get_mut(&session_id) else {
+            return SessionStopRspBuilder {
+                status: uci::Status::ErrorSessionNotExist,
+            }
+            .build();
+        };
+
+        if session.state != SessionState::SessionStateActive {
+            return SessionStopRspBuilder {
+                status: uci::Status::ErrorSessionActive,
+            }
+            .build();
+        }
+
+        session.stop_ranging_task();
+        session.set_state(
+            SessionState::SessionStateIdle,
+            ReasonCode::StateChangeWithSessionManagementCommands,
+        );
+
+        self.n_active_sessions -= 1;
+        if self.n_active_sessions == 0 {
+            self.set_state(DeviceState::DeviceStateReady);
+        }
+
+        SessionStopRspBuilder {
+            status: uci::Status::Ok,
+        }
+        .build()
+    }
+
+    fn session_get_ranging_count(
+        &self,
+        cmd: SessionGetRangingCountCmd,
+    ) -> SessionGetRangingCountRsp {
+        let session_id = cmd.get_session_id();
+
+        log::debug!(
+            "[{}:0x{:x}] Session Get Ranging Count",
+            self.handle,
+            session_id
+        );
+
+        let Some(session) = self.sessions.get(&session_id) else {
+            return SessionGetRangingCountRspBuilder {
+                status: uci::Status::ErrorSessionNotExist,
+                count: 0,
+            }
+            .build();
+        };
+
+        SessionGetRangingCountRspBuilder {
+            status: uci::Status::Ok,
+            count: session.sequence_number,
+        }
+        .build()
+    }
+
+    fn android_set_country_code(
         &mut self,
         cmd: AndroidSetCountryCodeCmd,
     ) -> AndroidSetCountryCodeRsp {
@@ -373,12 +882,12 @@
 
         self.country_code = country_code;
         AndroidSetCountryCodeRspBuilder {
-            status: StatusCode::UciStatusOk,
+            status: uci::Status::Ok,
         }
         .build()
     }
 
-    fn command_get_power_stats(
+    fn android_get_power_stats(
         &mut self,
         _cmd: AndroidGetPowerStatsCmd,
     ) -> AndroidGetPowerStatsRsp {
@@ -387,7 +896,7 @@
         // TODO
         AndroidGetPowerStatsRspBuilder {
             stats: PowerStats {
-                status: StatusCode::UciStatusOk,
+                status: uci::Status::Ok,
                 idle_time_ms: 0,
                 tx_time_ms: 0,
                 rx_time_ms: 0,
@@ -397,7 +906,7 @@
         .build()
     }
 
-    pub fn data_message_snd(&mut self, data: DataPacket) -> SessionControlNotification {
+    pub fn data_message_snd(&mut self, data: DataPacket) -> ControlPacket {
         log::debug!("[{}] data_message_send", self.handle);
         match data.specialize() {
             DataPacketChild::DataMessageSnd(data_msg_snd) => {
@@ -405,7 +914,7 @@
                 if let Some(session) = self.session_mut(session_token) {
                     session.data_message_snd(data_msg_snd)
                 } else {
-                    DataTransferStatusNtfBuilder {
+                    SessionDataTransferStatusNtfBuilder {
                         session_token,
                         status: DataTransferNtfStatusCode::UciDataTransferStatusErrorRejected,
                         tx_count: 1, // TODO: support for retries?
@@ -418,7 +927,7 @@
             DataPacketChild::DataMessageRcv(data_msg_rcv) => {
                 // This function should not be passed anything besides DataMessageSnd
                 let session_token = data_msg_rcv.get_session_handle();
-                DataTransferStatusNtfBuilder {
+                SessionDataTransferStatusNtfBuilder {
                     session_token,
                     status: DataTransferNtfStatusCode::UciDataTransferStatusInvalidFormat,
                     tx_count: 1, // TODO: support for retries?
@@ -433,187 +942,73 @@
         }
     }
 
-    fn receive_command(&mut self, cmd: UciCommand) -> UciResponse {
+    fn receive_command(&mut self, cmd: ControlPacket) -> ControlPacket {
+        use AndroidPacketChild::*;
+        use ControlPacketChild::*;
+        use CorePacketChild::*;
+        use SessionConfigPacketChild::*;
+        use SessionControlPacketChild::*;
+
         match cmd.specialize() {
-            // Handle commands for this device
-            UciCommandChild::CoreCommand(core_command) => match core_command.specialize() {
-                CoreCommandChild::DeviceResetCmd(cmd) => self.command_device_reset(cmd).into(),
-                CoreCommandChild::GetDeviceInfoCmd(cmd) => self.command_get_device_info(cmd).into(),
-                CoreCommandChild::GetCapsInfoCmd(cmd) => self.command_get_caps_info(cmd).into(),
-                CoreCommandChild::SetConfigCmd(cmd) => self.command_set_config(cmd).into(),
-                CoreCommandChild::GetConfigCmd(cmd) => self.command_get_config(cmd).into(),
-                _ => panic!("Unsupported core command"),
+            CorePacket(cmd) => match cmd.specialize() {
+                CoreDeviceResetCmd(cmd) => self.core_device_reset(cmd).into(),
+                CoreGetDeviceInfoCmd(cmd) => self.core_get_device_info(cmd).into(),
+                CoreGetCapsInfoCmd(cmd) => self.core_get_caps_info(cmd).into(),
+                CoreSetConfigCmd(cmd) => self.core_set_config(cmd).into(),
+                CoreGetConfigCmd(cmd) => self.core_get_config(cmd).into(),
+                _ => unimplemented!("Unsupported Core oid {:?}", cmd.get_oid()),
             },
-            // Handle commands for session management
-            UciCommandChild::SessionConfigCommand(session_command) => {
-                match session_command.specialize() {
-                    SessionConfigCommandChild::SessionInitCmd(cmd) => {
-                        return self.command_session_init(cmd).into();
-                    }
-                    SessionConfigCommandChild::SessionDeinitCmd(cmd) => {
-                        return self.command_session_deinit(cmd).into();
-                    }
-                    SessionConfigCommandChild::SessionGetCountCmd(cmd) => {
-                        return self.command_session_get_count(cmd).into();
-                    }
-                    _ => {}
+            SessionConfigPacket(cmd) => match cmd.specialize() {
+                SessionInitCmd(cmd) => self.session_init(cmd).into(),
+                SessionDeinitCmd(cmd) => self.session_deinit(cmd).into(),
+                SessionGetCountCmd(cmd) => self.session_get_count(cmd).into(),
+                SessionSetAppConfigCmd(cmd) => self.session_set_app_config(cmd).into(),
+                SessionGetAppConfigCmd(cmd) => self.session_get_app_config(cmd).into(),
+                SessionGetStateCmd(cmd) => self.session_get_state(cmd).into(),
+                SessionUpdateControllerMulticastListCmd(cmd) => {
+                    self.session_update_controller_multicast_list(cmd).into()
                 }
-
-                // Common code for retrieving the session_id in the command
-                let session_id = match session_command.specialize() {
-                    SessionConfigCommandChild::SessionSetAppConfigCmd(cmd) => {
-                        cmd.get_session_token()
-                    }
-                    SessionConfigCommandChild::SessionGetAppConfigCmd(cmd) => {
-                        cmd.get_session_token()
-                    }
-                    SessionConfigCommandChild::SessionGetStateCmd(cmd) => cmd.get_session_token(),
-                    SessionConfigCommandChild::SessionUpdateControllerMulticastListCmd(cmd) => {
-                        cmd.get_session_token()
-                    }
-                    _ => panic!("Unsupported session command type"),
-                };
-
-                if let Some(session) = self.session_mut(session_id) {
-                    // There is a session matching the session_id in the command
-                    // Pass the command through
-                    match session_command.specialize() {
-                        SessionConfigCommandChild::SessionSetAppConfigCmd(_)
-                        | SessionConfigCommandChild::SessionGetAppConfigCmd(_)
-                        | SessionConfigCommandChild::SessionGetStateCmd(_)
-                        | SessionConfigCommandChild::SessionUpdateControllerMulticastListCmd(_) => {
-                            session.session_command(session_command).into()
-                        }
-                        _ => panic!("Unsupported session command"),
-                    }
-                } else {
-                    // There is no session matching the session_id in the command
-                    let status = StatusCode::UciStatusSessionNotExist;
-                    match session_command.specialize() {
-                        SessionConfigCommandChild::SessionSetAppConfigCmd(_) => {
-                            SessionSetAppConfigRspBuilder {
-                                cfg_status: Vec::new(),
-                                status,
-                            }
-                            .build()
-                            .into()
-                        }
-                        SessionConfigCommandChild::SessionGetAppConfigCmd(_) => {
-                            SessionGetAppConfigRspBuilder {
-                                status,
-                                tlvs: Vec::new(),
-                            }
-                            .build()
-                            .into()
-                        }
-                        SessionConfigCommandChild::SessionGetStateCmd(_) => {
-                            SessionGetStateRspBuilder {
-                                status,
-                                session_state: SessionState::SessionStateDeinit,
-                            }
-                            .build()
-                            .into()
-                        }
-                        SessionConfigCommandChild::SessionUpdateControllerMulticastListCmd(_) => {
-                            SessionUpdateControllerMulticastListRspBuilder { status }
-                                .build()
-                                .into()
-                        }
-                        _ => panic!("Unsupported session command"),
-                    }
+                _ => unimplemented!("Unsupported Session Config oid {:?}", cmd.get_oid()),
+            },
+            SessionControlPacket(cmd) => match cmd.specialize() {
+                SessionStartCmd(cmd) => self.session_start(cmd).into(),
+                SessionStopCmd(cmd) => self.session_stop(cmd).into(),
+                SessionGetRangingCountCmd(cmd) => self.session_get_ranging_count(cmd).into(),
+                _ => unimplemented!("Unsupported Session Control oid {:?}", cmd.get_oid()),
+            },
+            AndroidPacket(cmd) => match cmd.specialize() {
+                AndroidSetCountryCodeCmd(cmd) => self.android_set_country_code(cmd).into(),
+                AndroidGetPowerStatsCmd(cmd) => self.android_get_power_stats(cmd).into(),
+                _ => unimplemented!("Unsupported Android oid {:?}", cmd.get_oid()),
+            },
+            ControlPacketChild::Payload(_)
+                if matches!(
+                    cmd.get_mt(),
+                    uci::MessageType::Response | uci::MessageType::Notification
+                ) =>
+            {
+                unreachable!("Unhandled control messsage with type {:?}", cmd.get_mt());
+            }
+            ControlPacketChild::Payload(payload) => {
+                // [UCI] 4.3.2 Exception Handling for Control Messages
+                // The UWBS shall respond to an unknown Command (unknown GID
+                // or OID) with a Response having the same GID and OID field
+                // values as the Command, followed by a Status field with the
+                // value of STATUS_UNKNOWN_GID/STATUS_UNKNOWN_OID respectively
+                // and no additional fields.
+                log::error!("Unsupported gid {:?}", cmd.get_gid());
+                ControlPacketBuilder {
+                    mt: uci::MessageType::Response,
+                    gid: cmd.get_gid(),
+                    payload: Some(
+                        vec![payload[0], payload[1], 0x1, uci::Status::UnknownGid.into()].into(),
+                    ),
                 }
+                .build()
             }
-            UciCommandChild::SessionControlCommand(ranging_command) => {
-                let session_id = ranging_command.get_session_id();
-                if let Some(session) = self.session_mut(session_id) {
-                    // Forward to the proper session
-                    let response = session.ranging_command(ranging_command);
-                    match response.specialize() {
-                        SessionControlResponseChild::SessionStartRsp(rsp)
-                            if rsp.get_status() == StatusCode::UciStatusOk =>
-                        {
-                            self.n_active_sessions += 1;
-                            self.set_state(DeviceState::DeviceStateActive);
-                        }
-                        SessionControlResponseChild::SessionStopRsp(rsp)
-                            if rsp.get_status() == StatusCode::UciStatusOk =>
-                        {
-                            assert!(self.n_active_sessions > 0);
-                            self.n_active_sessions -= 1;
-                            if self.n_active_sessions == 0 {
-                                self.set_state(DeviceState::DeviceStateReady);
-                            }
-                        }
-                        _ => {}
-                    }
-                    response.into()
-                } else {
-                    let status = StatusCode::UciStatusSessionNotExist;
-                    match ranging_command.specialize() {
-                        SessionControlCommandChild::SessionStartCmd(_) => {
-                            SessionStartRspBuilder { status }.build().into()
-                        }
-                        SessionControlCommandChild::SessionStopCmd(_) => {
-                            SessionStopRspBuilder { status }.build().into()
-                        }
-                        SessionControlCommandChild::SessionGetRangingCountCmd(_) => {
-                            SessionGetRangingCountRspBuilder { status, count: 0 }
-                                .build()
-                                .into()
-                        }
-                        _ => panic!("Unsupported ranging command"),
-                    }
-                }
+            ControlPacketChild::None => {
+                unreachable!()
             }
-
-            UciCommandChild::AndroidCommand(android_command) => {
-                match android_command.specialize() {
-                    AndroidCommandChild::AndroidSetCountryCodeCmd(cmd) => {
-                        self.command_set_country_code(cmd).into()
-                    }
-                    AndroidCommandChild::AndroidGetPowerStatsCmd(cmd) => {
-                        self.command_get_power_stats(cmd).into()
-                    }
-                    _ => panic!("Unsupported Android command"),
-                }
-            }
-            UciCommandChild::UciVendor_9_Command(vendor_command) => UciVendor_9_ResponseBuilder {
-                opcode: vendor_command.get_opcode(),
-                payload: Some(vec![u8::from(StatusCode::UciStatusRejected)].into()),
-            }
-            .build()
-            .into(),
-            UciCommandChild::UciVendor_A_Command(vendor_command) => UciVendor_A_ResponseBuilder {
-                opcode: vendor_command.get_opcode(),
-                payload: Some(vec![u8::from(StatusCode::UciStatusRejected)].into()),
-            }
-            .build()
-            .into(),
-            UciCommandChild::UciVendor_B_Command(vendor_command) => UciVendor_B_ResponseBuilder {
-                opcode: vendor_command.get_opcode(),
-                payload: Some(vec![u8::from(StatusCode::UciStatusRejected)].into()),
-            }
-            .build()
-            .into(),
-            UciCommandChild::UciVendor_E_Command(vendor_command) => UciVendor_E_ResponseBuilder {
-                opcode: vendor_command.get_opcode(),
-                payload: Some(vec![u8::from(StatusCode::UciStatusRejected)].into()),
-            }
-            .build()
-            .into(),
-            UciCommandChild::UciVendor_F_Command(vendor_command) => UciVendor_F_ResponseBuilder {
-                opcode: vendor_command.get_opcode(),
-                payload: Some(vec![u8::from(StatusCode::UciStatusRejected)].into()),
-            }
-            .build()
-            .into(),
-            // TODO: Handle properly without panic
-            _ => UciResponseBuilder {
-                gid: GroupId::Core,
-                opcode: 0,
-                payload: None,
-            }
-            .build(),
         }
     }
 
@@ -642,9 +1037,9 @@
                         let opcode_id = packet[1] & 0x3f;
 
                         let status = if GroupId::try_from(group_id).is_ok() {
-                            StatusCode::UciStatusUnknownOid
+                            uci::Status::UnknownOid
                         } else {
-                            StatusCode::UciStatusUnknownGid
+                            uci::Status::UnknownGid
                         };
                         // The PDL generated code cannot be used to generate
                         // responses with invalid group identifiers.
@@ -660,7 +1055,7 @@
 
                     // Parsing success, ignore non command packets.
                     Ok(cmd) => {
-                        let response = self.receive_command(cmd.try_into().unwrap());
+                        let response = self.receive_command(cmd);
                         self.send_control(response)
                     }
                 }
@@ -672,3 +1067,41 @@
         }
     }
 }
+
+struct Controlee {
+    short_address: MacAddress,
+    #[allow(dead_code)]
+    sub_session_id: u32,
+    #[allow(dead_code)]
+    session_key: SubSessionKey,
+}
+
+impl From<&uci::Controlee> for Controlee {
+    fn from(value: &uci::Controlee) -> Self {
+        Controlee {
+            short_address: MacAddress::Short(value.short_address),
+            sub_session_id: value.subsession_id,
+            session_key: SubSessionKey::None,
+        }
+    }
+}
+
+impl From<&uci::Controlee_V2_0_16_Byte_Version> for Controlee {
+    fn from(value: &uci::Controlee_V2_0_16_Byte_Version) -> Self {
+        Controlee {
+            short_address: MacAddress::Short(value.short_address),
+            sub_session_id: value.subsession_id,
+            session_key: SubSessionKey::Short(value.subsession_key),
+        }
+    }
+}
+
+impl From<&uci::Controlee_V2_0_32_Byte_Version> for Controlee {
+    fn from(value: &uci::Controlee_V2_0_32_Byte_Version) -> Self {
+        Controlee {
+            short_address: MacAddress::Short(value.short_address),
+            sub_session_id: value.subsession_id,
+            session_key: SubSessionKey::Extended(value.subsession_key),
+        }
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 2927d95..17ad1c2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -24,19 +24,18 @@
 pub mod packets;
 mod pcapng;
 
-use packets::uci::StatusCode as UciStatusCode;
-use packets::uci::*;
+use packets::uci::{self, *};
 
 mod device;
-use device::{Device, MAX_DEVICE};
+use device::{Device, MAX_DEVICE, MAX_SESSION};
 
 mod session;
-use session::MAX_SESSION;
 
 mod mac_address;
 pub use mac_address::MacAddress;
 
-use crate::session::RangeDataNtfConfig;
+mod app_config;
+pub use app_config::AppConfig;
 
 pub type UciPacket = Vec<u8>;
 pub type UciStream = Pin<Box<dyn futures::stream::Stream<Item = Vec<u8>> + Send>>;
@@ -162,7 +161,7 @@
     if let MacAddress::Short(address) = mac_address {
         ShortAddressTwoWayRangingMeasurement {
             mac_address: u16::from_le_bytes(*address),
-            status: UciStatusCode::UciStatusOk,
+            status: uci::Status::Ok,
             nlos: 0, // in Line Of Sight
             distance: local.range,
             aoa_azimuth: local.azimuth as u16,
@@ -412,7 +411,7 @@
         let mut measurements = Vec::new();
 
         // Look for compatible anchors.
-        for mac_address in session.get_dst_mac_addresses() {
+        for mac_address in session.get_dst_mac_address() {
             if let Some(other) = self.anchors.get(mac_address) {
                 let local = self
                     .ranging_estimator
@@ -437,7 +436,8 @@
                     .session(session_id)
                     .unwrap()
                     .app_config
-                    .device_mac_address;
+                    .device_mac_address
+                    .unwrap();
                 let local = self
                     .ranging_estimator
                     .estimate(&device.handle, &peer_device.handle)
@@ -467,15 +467,15 @@
                         data_sequence_number: 0x01,
                         pbf: PacketBoundaryFlag::Complete,
                         session_handle: session_id,
-                        source_address: device.mac_address.into(),
-                        status: UciStatusCode::UciStatusOk,
+                        source_address: session.app_config.device_mac_address.unwrap().into(),
+                        status: uci::Status::Ok,
                     }
                     .build()
                     .into(),
                 )
                 .unwrap();
         }
-        if session.is_ranging_data_ntf_enabled() != RangeDataNtfConfig::Disable {
+        if session.is_session_info_ntf_enabled() {
             device
                 .tx
                 .send(
@@ -554,7 +554,7 @@
                 continue;
             };
 
-            if &session.app_config.device_mac_address != mac_address {
+            if session.app_config.device_mac_address != Some(*mac_address) {
                 continue;
             }
 
diff --git a/src/mac_address.rs b/src/mac_address.rs
index 79cfe94..6c93981 100644
--- a/src/mac_address.rs
+++ b/src/mac_address.rs
@@ -43,15 +43,36 @@
     }
 }
 
+impl From<&MacAddress> for u64 {
+    fn from(mac_address: &MacAddress) -> Self {
+        match mac_address {
+            MacAddress::Short(addr) => u16::from_le_bytes(*addr) as u64,
+            MacAddress::Extended(addr) => u64::from_le_bytes(*addr),
+        }
+    }
+}
+
 impl From<MacAddress> for u64 {
     fn from(mac_address: MacAddress) -> Self {
+        u64::from(&mac_address)
+    }
+}
+
+impl From<&MacAddress> for Vec<u8> {
+    fn from(mac_address: &MacAddress) -> Self {
         match mac_address {
-            MacAddress::Short(addr) => u16::from_le_bytes(addr) as u64,
-            MacAddress::Extended(addr) => u64::from_le_bytes(addr),
+            MacAddress::Short(addr) => addr.to_vec(),
+            MacAddress::Extended(addr) => addr.to_vec(),
         }
     }
 }
 
+impl From<MacAddress> for Vec<u8> {
+    fn from(mac_address: MacAddress) -> Self {
+        Vec::<u8>::from(&mac_address)
+    }
+}
+
 impl TryFrom<String> for MacAddress {
     type Error = Error;
     fn try_from(mac_address: String) -> std::result::Result<Self, Error> {
diff --git a/src/session.rs b/src/session.rs
index eb4e063..2ee656a 100644
--- a/src/session.rs
+++ b/src/session.rs
@@ -17,711 +17,15 @@
 //! - [UCI] FiRa Consortium UWB Command Interface Generic Technical specification
 
 use crate::packets::uci::{self, *};
-use crate::{MacAddress, PicaCommand};
+use crate::{AppConfig, MacAddress};
 use bytes::BytesMut;
-use std::collections::HashMap;
 use std::time::Duration;
 use tokio::sync::mpsc;
 use tokio::task::JoinHandle;
 use tokio::time;
 
-use num_derive::{FromPrimitive, ToPrimitive};
-use num_traits::FromPrimitive;
-
 use super::UciPacket;
 
-pub const MAX_SESSION: usize = 255;
-pub const DEFAULT_RANGING_INTERVAL: Duration = time::Duration::from_millis(200);
-pub const DEFAULT_SLOT_DURATION: u16 = 2400; // RTSU unit
-/// cf. [UCI] 8.3 Table 29
-pub const MAX_NUMBER_OF_CONTROLEES: usize = 8;
-pub const FIRA_1_1_INITIATION_TIME_SIZE: usize = 4;
-pub const FIRA_2_0_INITIATION_TIME_SIZE: usize = 8;
-
-#[derive(Copy, Clone, FromPrimitive, PartialEq, Eq)]
-pub enum DeviceType {
-    /// [MAC] 5.1.2 Device utilizing the ranging features set through Control Messages
-    Controlee = 0x00,
-    /// [MAC] 5.1.1 Device controlling the ranging features through Control Messages
-    Controller = 0x01,
-}
-
-#[derive(Copy, Clone, FromPrimitive, PartialEq, Eq)]
-pub enum DeviceRole {
-    /// [MAC] 5.1.3 Device initiating a ranging exchange with a ranging initiation message
-    Initiator,
-    /// [MAC] 5.1.4 Device responding to ranging initiation messages
-    Responder,
-}
-
-/// cf. [UCI] 8.4 Table 29
-#[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq, Eq)]
-#[repr(u8)]
-pub enum MacAddressMode {
-    /// MAC address is 2 bytes and 2 bytes to be used in MAC header
-    AddressMode0 = 0x00,
-    /// Not Supported: MAC address is 8 bytes and 2 bytes to be used in MAC header
-    AddressMode1 = 0x01,
-    /// MAC address is 8 bytes and 8 bytes to be used in MAC header
-    AddressMode2 = 0x02,
-}
-
-/// cf. [UCI] 8.3 Table 29
-#[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq, Eq)]
-#[repr(u8)]
-pub enum ChannelNumber {
-    ChannelNumber5 = 0x05,
-    ChannelNumber6 = 0x06,
-    ChannelNumber8 = 0x08,
-    ChannelNumber9 = 0x09,
-    ChannelNumber10 = 0x0a,
-    ChannelNumber12 = 0x0c,
-    ChannelNumber13 = 0x0d,
-    ChannelNumber14 = 0x0e,
-}
-
-const DEFAULT_CHANNEL_NUMBER: ChannelNumber = ChannelNumber::ChannelNumber9;
-
-/// cf. [UCI] 8.3 Table 29
-#[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq)]
-#[repr(u8)]
-enum MultiNodeMode {
-    /// Single device to single device
-    Unicast = 0x00,
-    OneToMany = 0x01,
-    ManyToMany = 0x02,
-}
-
-/// cf. [UCI] 7.7
-#[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq)]
-#[repr(u8)]
-enum UpdateMulticastListAction {
-    Add = 0x00,
-    Delete = 0x01,
-    AddWithShortSubSessionKey = 0x02,
-    AddwithExtendedSubSessionKey = 0x03,
-}
-
-#[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq)]
-#[repr(u8)]
-enum RangingRoundUsage {
-    UlTdoa = 0x00,
-    SsTwrDeferredMode = 0x01,
-    DsTwrDeferredMode = 0x02,
-    SsTwrNonDeferredMode = 0x03,
-    DsTwrNonDeferredMode = 0x04,
-    DlTdoa = 0x05,
-    OwrAoaMeasurement = 0x06,
-    DataTransferMode = 0x09,
-}
-
-#[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq)]
-#[repr(u8)]
-enum StsConfig {
-    Static = 0x00,
-    Dynamic = 0x01,
-    DynamicForControleeIndividualKey = 0x02,
-    Provisioned = 0x03,
-    ProvisionedForControleeIndividualKey = 0x04,
-}
-
-#[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq)]
-#[repr(u8)]
-enum MacFcsType {
-    MacFcsTypeCrc16 = 0x00,
-    MacFcsTypeCrc32 = 0x01,
-}
-
-#[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq)]
-#[repr(u8)]
-enum AoaResultReq {
-    NoAoaResult = 0x00,
-    ReqAoaResults = 0x01,
-    ReqAoaResultsAzimuthOnly = 0x02,
-    ReqAoaResultsElevationOnly = 0x03,
-    ReqAoaResultsInterleaved = 0x04,
-}
-
-#[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq)]
-#[repr(u8)]
-enum RframeConfig {
-    Sp0 = 0x00,
-    Sp1 = 0x01,
-    Sp3 = 0x03,
-}
-
-#[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq)]
-#[repr(u8)]
-enum PsduDataRate {
-    Rate6M81 = 0x00,
-    Rate7M80 = 0x01,
-    Rate27M2 = 0x02,
-    Rate31M2 = 0x03,
-}
-
-#[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq)]
-#[repr(u8)]
-enum PreambleDuration {
-    PreambleDurationT32Symbols = 0x00,
-    PreambleDurationT64Symbols = 0x01,
-}
-
-#[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq)]
-#[repr(u8)]
-enum RangingTimeStruct {
-    IntervalBasedScheduling = 0x00,
-    BlockBasedScheduling = 0x01,
-}
-
-#[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq)]
-#[repr(u8)]
-enum PrfMode {
-    PrfModeBprf = 0x00,
-    PrfModeHprf = 0x01,
-}
-
-#[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq)]
-#[repr(u8)]
-enum SchedulingMode {
-    ContentionBased = 0x00,
-    TimeScheduled = 0x01,
-    HybridScheduled = 0x02,
-}
-
-#[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq)]
-#[repr(u8)]
-enum HoppingMode {
-    Disable = 0x00,
-    FiraEnable = 0x01,
-}
-
-#[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq)]
-#[repr(u8)]
-enum StsLength {
-    StsLength32 = 0x00,
-    StsLength64 = 0x01,
-    StsLength128 = 0x02,
-}
-
-#[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq)]
-#[repr(u8)]
-enum BprfPhrDataRate {
-    BprfPhrDataRate850K = 0x00,
-    BprfPhrDataRate6M81 = 0x01,
-}
-
-#[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq)]
-#[repr(u8)]
-enum SfdIdValue {
-    SfdIdValue0 = 0x00,
-    SfdIdValue1 = 0x01,
-    SfdIdValue2 = 0x02,
-    SfdIdValue3 = 0x03,
-    SfdIdValue4 = 0x04,
-}
-
-#[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq)]
-#[repr(u8)]
-enum StsSegmentCountValue {
-    StsSegmentCountValue0 = 0x00,
-    StsSegmentCountValue1 = 0x01,
-    StsSegmentCountValue2 = 0x02,
-}
-
-#[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq)]
-#[repr(u8)]
-pub enum RangeDataNtfConfig {
-    Disable = 0x00,
-    Enable = 0x01,
-    EnableProximityLevelTrig = 0x02,
-    EnableAoaLevelTrig = 0x03,
-    EnableProximityAoaLevelTrig = 0x04,
-    EnableProximityEdgeTrig = 0x05,
-    EnableAoaEdgeTrig = 0x06,
-    EnableProximityAoaEdgeTrig = 0x07,
-}
-
-#[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq)]
-#[repr(u8)]
-pub enum LinkLayerMode {
-    Bypass = 0x00,
-    Assigned = 0x01,
-}
-
-#[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq)]
-#[repr(u8)]
-pub enum DataRepetitionCount {
-    NoRepetition = 0x00,
-    Infinite = 0xFF,
-}
-
-#[derive(Copy, Clone, FromPrimitive, ToPrimitive, PartialEq)]
-#[repr(u8)]
-pub enum SessionDataTransferStatusNtfConfig {
-    Disable = 0x00,
-    Enable = 0x01,
-}
-/// cf. [UCI] 8.3 Table 29
-#[derive(Clone)]
-pub struct AppConfig {
-    /// Copy of the valid App Configuration parameters provided by host
-    raw: HashMap<AppConfigTlvType, Vec<u8>>,
-
-    device_type: DeviceType,
-    device_role: DeviceRole,
-    mac_address_mode: MacAddressMode,
-    pub device_mac_address: MacAddress,
-    number_of_controlees: usize,
-    dst_mac_addresses: Vec<MacAddress>,
-    ranging_interval: time::Duration,
-    slot_duration: u16,
-    channel_number: ChannelNumber,
-    multi_node_mode: MultiNodeMode,
-    ranging_round_usage: RangingRoundUsage,
-    sts_config: StsConfig,
-    mac_fcs_type: MacFcsType,
-    ranging_round_control: u8,
-    aoa_result_req: AoaResultReq,
-    rng_data_ntf: RangeDataNtfConfig,
-    rng_data_ntf_proximity_near: u16,
-    rng_data_ntf_proximity_far: u16,
-    r_frame_config: RframeConfig,
-    rssi_reporting: bool,
-    preamble_code_index: u8,
-    sfd_id: SfdIdValue,
-    psdu_data_rate: PsduDataRate,
-    preamble_duration: PreambleDuration,
-    ranging_time_struct: RangingTimeStruct,
-    slots_per_rr: u8,
-    tx_adaptive_payload_power: bool,
-    prf_mode: PrfMode,
-    schedule_mode: SchedulingMode,
-    key_rotation: bool,
-    key_rotation_rate: u8,
-    session_priority: u8,
-    number_of_sts_segments: StsSegmentCountValue,
-    max_rr_retry: u16,
-    hopping_mode: HoppingMode,
-    block_stride_length: u8,
-    result_report_config: bool,
-    in_band_termination_attempt_count: u8,
-    bprf_phr_data_rate: BprfPhrDataRate,
-    max_number_of_measurements: u8,
-    sts_length: StsLength,
-    uwb_initiation_time: u64,
-    vendor_id: Option<Vec<u8>>,
-    static_sts_iv: Option<Vec<u8>>,
-    session_key: Option<Vec<u8>>,
-    sub_session_key: Option<Vec<u8>>,
-    sub_session_id: u32,
-    link_layer_mode: LinkLayerMode,
-    data_repetition_count: DataRepetitionCount,
-    session_data_transfer_status_ntf_config: SessionDataTransferStatusNtfConfig,
-    application_data_endpoint: u8,
-}
-
-impl Default for AppConfig {
-    fn default() -> Self {
-        AppConfig {
-            raw: HashMap::new(),
-            mac_address_mode: MacAddressMode::AddressMode0,
-            device_role: DeviceRole::Responder,
-            device_type: DeviceType::Controlee,
-            ranging_interval: DEFAULT_RANGING_INTERVAL,
-            slot_duration: DEFAULT_SLOT_DURATION,
-            channel_number: DEFAULT_CHANNEL_NUMBER,
-            device_mac_address: MacAddress::Short([0x00, 0x00]),
-            number_of_controlees: 0,
-            dst_mac_addresses: Vec::new(),
-            multi_node_mode: MultiNodeMode::Unicast,
-            ranging_round_usage: RangingRoundUsage::DsTwrDeferredMode,
-            sts_config: StsConfig::Static,
-            mac_fcs_type: MacFcsType::MacFcsTypeCrc16,
-            ranging_round_control: 6_u8,
-            aoa_result_req: AoaResultReq::ReqAoaResults,
-            rng_data_ntf: RangeDataNtfConfig::Enable,
-            rng_data_ntf_proximity_near: 0,
-            rng_data_ntf_proximity_far: 0,
-            r_frame_config: RframeConfig::Sp3,
-            rssi_reporting: false,
-            preamble_code_index: 10,
-            sfd_id: SfdIdValue::SfdIdValue2,
-            psdu_data_rate: PsduDataRate::Rate6M81,
-            preamble_duration: PreambleDuration::PreambleDurationT64Symbols,
-            ranging_time_struct: RangingTimeStruct::IntervalBasedScheduling,
-            slots_per_rr: 25,
-            tx_adaptive_payload_power: false,
-            prf_mode: PrfMode::PrfModeBprf,
-            schedule_mode: SchedulingMode::TimeScheduled,
-            key_rotation: false,
-            key_rotation_rate: 0,
-            session_priority: 50,
-            number_of_sts_segments: StsSegmentCountValue::StsSegmentCountValue1,
-            max_rr_retry: 0,
-            hopping_mode: HoppingMode::Disable,
-            block_stride_length: 0,
-            result_report_config: true,
-            in_band_termination_attempt_count: 1,
-            bprf_phr_data_rate: BprfPhrDataRate::BprfPhrDataRate850K,
-            max_number_of_measurements: 0,
-            sts_length: StsLength::StsLength64,
-            uwb_initiation_time: 0,
-            vendor_id: None,
-            static_sts_iv: None,
-            session_key: None,
-            sub_session_key: None,
-            sub_session_id: 0,
-            link_layer_mode: LinkLayerMode::Bypass,
-            data_repetition_count: DataRepetitionCount::NoRepetition,
-            session_data_transfer_status_ntf_config: SessionDataTransferStatusNtfConfig::Disable,
-            application_data_endpoint: 0,
-        }
-    }
-}
-
-impl PartialEq for AppConfig {
-    fn eq(&self, other: &Self) -> bool {
-        self.mac_address_mode == other.mac_address_mode
-            && self.ranging_interval == other.ranging_interval
-            && self.slot_duration == other.slot_duration
-            && self.channel_number == other.channel_number
-            && self.multi_node_mode == other.multi_node_mode
-            && self.ranging_round_usage == other.ranging_round_usage
-            && self.sts_config == other.sts_config
-            && self.mac_fcs_type == other.mac_fcs_type
-            && self.ranging_round_control == other.ranging_round_control
-            && self.aoa_result_req == other.aoa_result_req
-            && self.rng_data_ntf == other.rng_data_ntf
-            && self.rng_data_ntf_proximity_near == other.rng_data_ntf_proximity_near
-            && self.rng_data_ntf_proximity_far == other.rng_data_ntf_proximity_far
-            && self.r_frame_config == other.r_frame_config
-            && self.rssi_reporting == other.rssi_reporting
-            && self.preamble_code_index == other.preamble_code_index
-            && self.sfd_id == other.sfd_id
-            && self.psdu_data_rate == other.psdu_data_rate
-            && self.preamble_duration == other.preamble_duration
-            && self.ranging_time_struct == other.ranging_time_struct
-            && self.slots_per_rr == other.slots_per_rr
-            && self.tx_adaptive_payload_power == other.tx_adaptive_payload_power
-            && self.prf_mode == other.prf_mode
-            && self.schedule_mode == other.schedule_mode
-            && self.key_rotation == other.key_rotation
-            && self.key_rotation_rate == other.key_rotation_rate
-            && self.session_priority == other.session_priority
-            && self.number_of_sts_segments == other.number_of_sts_segments
-            && self.max_rr_retry == other.max_rr_retry
-            && self.result_report_config == other.result_report_config
-            && self.bprf_phr_data_rate == other.bprf_phr_data_rate
-            && self.max_number_of_measurements == other.max_number_of_measurements
-            && self.sts_length == other.sts_length
-            && self.uwb_initiation_time == other.uwb_initiation_time
-            && self.vendor_id == other.vendor_id
-            && self.static_sts_iv == other.static_sts_iv
-    }
-}
-
-fn app_config_has_mandatory_parameters(configs: &[AppConfigTlv]) -> bool {
-    const MANDATORY_PARAMETERS: [AppConfigTlvType; 6] = [
-        AppConfigTlvType::DeviceRole,
-        AppConfigTlvType::MultiNodeMode,
-        AppConfigTlvType::NoOfControlee,
-        AppConfigTlvType::DeviceMacAddress,
-        AppConfigTlvType::DstMacAddress,
-        AppConfigTlvType::DeviceType,
-    ];
-
-    MANDATORY_PARAMETERS
-        .iter()
-        .all(|&mparam| configs.iter().any(|param| mparam == param.cfg_id))
-}
-
-impl AppConfig {
-    fn set_config(
-        &mut self,
-        id: AppConfigTlvType,
-        value: &[u8],
-    ) -> std::result::Result<(), StatusCode> {
-        match id {
-            AppConfigTlvType::MacAddressMode => {
-                let mode = MacAddressMode::from_u8(value[0]).unwrap();
-                if mode == MacAddressMode::AddressMode1 {
-                    return Err(StatusCode::UciStatusInvalidParam);
-                }
-                self.mac_address_mode = mode;
-            }
-            AppConfigTlvType::RangingDuration => {
-                let interval = u32::from_le_bytes(value[..].try_into().unwrap());
-                self.ranging_interval = time::Duration::from_millis(interval as u64)
-            }
-            AppConfigTlvType::SlotDuration => {
-                self.slot_duration = u16::from_le_bytes(value[..].try_into().unwrap())
-            }
-            AppConfigTlvType::ChannelNumber => {
-                self.channel_number = ChannelNumber::from_u8(value[0]).unwrap()
-            }
-            AppConfigTlvType::DeviceMacAddress => {
-                self.device_mac_address = match self.mac_address_mode {
-                    MacAddressMode::AddressMode0 => {
-                        MacAddress::Short(value[..].try_into().unwrap())
-                    }
-                    MacAddressMode::AddressMode2 => {
-                        MacAddress::Extended(value[..].try_into().unwrap())
-                    }
-                    _ => panic!("Unexpected MAC Address Mode"),
-                };
-            }
-            AppConfigTlvType::NoOfControlee => {
-                assert!(value[0] as usize <= MAX_NUMBER_OF_CONTROLEES);
-                self.number_of_controlees = value[0] as usize;
-            }
-            AppConfigTlvType::DstMacAddress => {
-                let mac_address_size = match self.mac_address_mode {
-                    MacAddressMode::AddressMode0 => 2,
-                    MacAddressMode::AddressMode2 => 8,
-                    _ => panic!("Unexpected MAC Address Mode"),
-                };
-                if value.len() % mac_address_size != 0
-                    || (value.len() / mac_address_size) != self.number_of_controlees
-                {
-                    return Err(StatusCode::UciStatusInvalidParam);
-                }
-                self.dst_mac_addresses = value
-                    .chunks(mac_address_size)
-                    .map(|c| match self.mac_address_mode {
-                        MacAddressMode::AddressMode0 => MacAddress::Short(c.try_into().unwrap()),
-                        MacAddressMode::AddressMode2 => MacAddress::Extended(c.try_into().unwrap()),
-                        _ => panic!("Unexpected MAC Address Mode"),
-                    })
-                    .collect();
-                assert_eq!(self.dst_mac_addresses.len(), self.number_of_controlees);
-            }
-            AppConfigTlvType::MultiNodeMode => {
-                self.multi_node_mode = MultiNodeMode::from_u8(value[0]).unwrap()
-            }
-            AppConfigTlvType::DeviceType => {
-                self.device_type = DeviceType::from_u8(value[0]).unwrap();
-            }
-            AppConfigTlvType::RangingRoundUsage => {
-                self.ranging_round_usage = RangingRoundUsage::from_u8(value[0]).unwrap()
-            }
-            AppConfigTlvType::StsConfig => self.sts_config = StsConfig::from_u8(value[0]).unwrap(),
-            AppConfigTlvType::MacFcsType => {
-                self.mac_fcs_type = MacFcsType::from_u8(value[0]).unwrap()
-            }
-            AppConfigTlvType::RangingRoundControl => self.ranging_round_control = value[0],
-            AppConfigTlvType::AoaResultReq => {
-                self.aoa_result_req = AoaResultReq::from_u8(value[0]).unwrap()
-            }
-            AppConfigTlvType::RngDataNtf => {
-                self.rng_data_ntf = RangeDataNtfConfig::from_u8(value[0]).unwrap()
-            }
-            AppConfigTlvType::RngDataNtfProximityNear => {
-                self.rng_data_ntf_proximity_near = u16::from_le_bytes(value[..].try_into().unwrap())
-            }
-            AppConfigTlvType::RngDataNtfProximityFar => {
-                self.rng_data_ntf_proximity_far = u16::from_le_bytes(value[..].try_into().unwrap())
-            }
-            AppConfigTlvType::DeviceRole => {
-                self.device_role = DeviceRole::from_u8(value[0]).unwrap();
-            }
-            AppConfigTlvType::RframeConfig => {
-                self.r_frame_config = RframeConfig::from_u8(value[0]).unwrap()
-            }
-            AppConfigTlvType::RssiReporting => {
-                self.rssi_reporting = match value[0] {
-                    0 => false,
-                    1 => true,
-                    _ => panic!("Invalid rssi reporting value!"),
-                }
-            }
-            AppConfigTlvType::PreambleCodeIndex => self.preamble_code_index = value[0],
-            AppConfigTlvType::SfdId => self.sfd_id = SfdIdValue::from_u8(value[0]).unwrap(),
-            AppConfigTlvType::PsduDataRate => {
-                self.psdu_data_rate = PsduDataRate::from_u8(value[0]).unwrap()
-            }
-            AppConfigTlvType::PreambleDuration => {
-                self.preamble_duration = PreambleDuration::from_u8(value[0]).unwrap()
-            }
-            AppConfigTlvType::RangingTimeStruct => {
-                self.ranging_time_struct = RangingTimeStruct::from_u8(value[0]).unwrap()
-            }
-            AppConfigTlvType::SlotsPerRr => self.slots_per_rr = value[0],
-            AppConfigTlvType::TxAdaptivePayloadPower => {
-                self.tx_adaptive_payload_power = match value[0] {
-                    0 => false,
-                    1 => true,
-                    _ => panic!("Invalid tx adaptive payload power value!"),
-                }
-            }
-            AppConfigTlvType::PrfMode => self.prf_mode = PrfMode::from_u8(value[0]).unwrap(),
-            AppConfigTlvType::ScheduledMode => {
-                self.schedule_mode = SchedulingMode::from_u8(value[0]).unwrap()
-            }
-            AppConfigTlvType::KeyRotation => {
-                self.key_rotation = match value[0] {
-                    0 => false,
-                    1 => true,
-                    _ => panic!("Invalid key rotation value!"),
-                }
-            }
-            AppConfigTlvType::KeyRotationRate => self.key_rotation_rate = value[0],
-            AppConfigTlvType::SessionPriority => self.session_priority = value[0],
-            AppConfigTlvType::VendorId => {
-                self.vendor_id = Some(value.to_vec());
-            }
-            AppConfigTlvType::StaticStsIv => {
-                self.static_sts_iv = Some(value.to_vec());
-            }
-            AppConfigTlvType::NumberOfStsSegments => {
-                self.number_of_sts_segments = StsSegmentCountValue::from_u8(value[0]).unwrap()
-            }
-            AppConfigTlvType::MaxRrRetry => {
-                self.max_rr_retry = u16::from_le_bytes(value[..].try_into().unwrap())
-            }
-            AppConfigTlvType::UwbInitiationTime => {
-                self.uwb_initiation_time = match value.len() {
-                    // Backward compatible with Fira 1.1 Version UCI host.
-                    FIRA_1_1_INITIATION_TIME_SIZE => {
-                        u32::from_le_bytes(value[..].try_into().unwrap()) as u64
-                    }
-                    FIRA_2_0_INITIATION_TIME_SIZE => {
-                        u64::from_le_bytes(value[..].try_into().unwrap())
-                    }
-                    _ => panic!("Invalid initiation time!"),
-                }
-            }
-            AppConfigTlvType::HoppingMode => {
-                self.hopping_mode = HoppingMode::from_u8(value[0]).unwrap()
-            }
-            AppConfigTlvType::BlockStrideLength => self.block_stride_length = value[0],
-            AppConfigTlvType::ResultReportConfig => {
-                self.result_report_config = match value[0] {
-                    0 => false,
-                    1 => true,
-                    _ => panic!("Invalid result report config value!"),
-                }
-            }
-            AppConfigTlvType::BprfPhrDataRate => {
-                self.bprf_phr_data_rate = BprfPhrDataRate::from_u8(value[0]).unwrap()
-            }
-            AppConfigTlvType::MaxNumberOfMeasurements => self.max_number_of_measurements = value[0],
-            AppConfigTlvType::StsLength => self.sts_length = StsLength::from_u8(value[0]).unwrap(),
-            AppConfigTlvType::InBandTerminationAttemptCount => {
-                self.in_band_termination_attempt_count = value[0]
-            }
-            AppConfigTlvType::SessionKey => self.session_key = Some(value.to_vec()),
-            AppConfigTlvType::SubSessionId => {
-                self.sub_session_id = u32::from_le_bytes(value[..].try_into().unwrap())
-            }
-            AppConfigTlvType::SubsessionKey => self.sub_session_key = Some(value.to_vec()),
-            AppConfigTlvType::LinkLayerMode => {
-                self.link_layer_mode = LinkLayerMode::from_u8(value[0]).unwrap()
-            }
-            AppConfigTlvType::DataRepetitionCount => {
-                self.data_repetition_count = DataRepetitionCount::from_u8(value[0]).unwrap()
-            }
-            AppConfigTlvType::SessionDataTransferStatusNtfConfig => {
-                self.session_data_transfer_status_ntf_config =
-                    SessionDataTransferStatusNtfConfig::from_u8(value[0]).unwrap()
-            }
-            AppConfigTlvType::ApplicationDataEndpoint => self.application_data_endpoint = value[0],
-            id => {
-                log::error!("Ignored AppConfig parameter {:?}", id);
-                return Err(StatusCode::UciStatusInvalidParam);
-            }
-        };
-
-        self.raw.insert(id, value.to_vec());
-
-        Ok(())
-    }
-
-    fn get_config(&self, id: AppConfigTlvType) -> Option<Vec<u8>> {
-        self.raw.get(&id).cloned()
-    }
-
-    pub fn is_compatible_for_ranging(&self, peer_config: &Self) -> bool {
-        self == peer_config
-            && self.device_role != peer_config.device_role
-            && self.device_type != peer_config.device_type
-            && peer_config
-                .dst_mac_addresses
-                .contains(&self.device_mac_address)
-            && self
-                .dst_mac_addresses
-                .contains(&peer_config.device_mac_address)
-    }
-
-    pub fn can_start_data_transfer(&self) -> bool {
-        self.device_role == DeviceRole::Initiator
-    }
-
-    pub fn can_receive_data_transfer(&self) -> bool {
-        self.device_role == DeviceRole::Responder
-    }
-
-    fn extend(&mut self, configs: &[AppConfigTlv]) -> Vec<AppConfigStatus> {
-        if !app_config_has_mandatory_parameters(configs) {
-            // TODO: What shall we do in this situation?
-        }
-
-        configs
-            .iter()
-            .fold(Vec::new(), |mut invalid_parameters, config| {
-                match self.set_config(config.cfg_id, &config.v) {
-                    Ok(_) => (),
-                    Err(status) => invalid_parameters.push(AppConfigStatus {
-                        cfg_id: config.cfg_id,
-                        status,
-                    }),
-                };
-                invalid_parameters
-            })
-    }
-}
-
-enum SubSessionKey {
-    None,
-    Short([u8; 16]),
-    Extended([u8; 32]),
-}
-struct Controlee {
-    short_address: MacAddress,
-    sub_session_id: u32,
-    #[allow(dead_code)]
-    session_key: SubSessionKey,
-}
-
-impl From<&uci::Controlee> for Controlee {
-    fn from(value: &uci::Controlee) -> Self {
-        Controlee {
-            short_address: MacAddress::Short(value.short_address),
-            sub_session_id: value.subsession_id,
-            session_key: SubSessionKey::None,
-        }
-    }
-}
-
-impl From<&uci::Controlee_V2_0_16_Byte_Version> for Controlee {
-    fn from(value: &uci::Controlee_V2_0_16_Byte_Version) -> Self {
-        Controlee {
-            short_address: MacAddress::Short(value.short_address),
-            sub_session_id: value.subsession_id,
-            session_key: SubSessionKey::Short(value.subsession_key),
-        }
-    }
-}
-
-impl From<&uci::Controlee_V2_0_32_Byte_Version> for Controlee {
-    fn from(value: &uci::Controlee_V2_0_32_Byte_Version) -> Self {
-        Controlee {
-            short_address: MacAddress::Short(value.short_address),
-            sub_session_id: value.subsession_id,
-            session_key: SubSessionKey::Extended(value.subsession_key),
-        }
-    }
-}
-
 pub struct Session {
     /// cf. [UCI] 7.1
     pub state: SessionState,
@@ -730,12 +34,11 @@
     device_handle: usize,
     data: BytesMut,
 
-    session_type: SessionType,
+    pub session_type: SessionType,
     pub sequence_number: u32,
     pub app_config: AppConfig,
-    ranging_task: Option<JoinHandle<()>>,
+    pub ranging_task: Option<JoinHandle<()>>,
     tx: mpsc::UnboundedSender<UciPacket>,
-    pica_tx: mpsc::Sender<PicaCommand>,
 }
 
 impl Session {
@@ -744,7 +47,6 @@
         session_type: SessionType,
         device_handle: usize,
         tx: mpsc::UnboundedSender<UciPacket>,
-        pica_tx: mpsc::Sender<PicaCommand>,
     ) -> Self {
         Self {
             state: SessionState::SessionStateDeinit,
@@ -756,7 +58,6 @@
             app_config: AppConfig::default(),
             ranging_task: None,
             tx,
-            pica_tx,
         }
     }
 
@@ -785,12 +86,18 @@
         });
     }
 
-    pub fn get_dst_mac_addresses(&self) -> &Vec<MacAddress> {
-        &self.app_config.dst_mac_addresses
+    pub fn get_dst_mac_address(&self) -> &[MacAddress] {
+        &self.app_config.dst_mac_address
     }
 
-    pub fn is_ranging_data_ntf_enabled(&self) -> RangeDataNtfConfig {
-        self.app_config.rng_data_ntf
+    pub fn is_session_info_ntf_enabled(&self) -> bool {
+        self.app_config.session_info_ntf_config != uci::SessionInfoNtfConfig::Disable
+    }
+
+    #[allow(unused)]
+    pub fn is_session_data_transfer_status_ntf_enabled(&self) -> bool {
+        self.app_config.session_data_transfer_status_ntf_config
+            != uci::SessionDataTransferStatusNtfConfig::Disable
     }
 
     pub fn data(&self) -> &BytesMut {
@@ -816,407 +123,20 @@
         );
     }
 
-    fn command_set_app_config(&mut self, cmd: SessionSetAppConfigCmd) -> SessionSetAppConfigRsp {
-        // TODO properly handle these asserts
-        log::debug!(
-            "[{}:0x{:x}] Session Set App Config",
-            self.device_handle,
-            self.id
-        );
-        assert_eq!(self.id, cmd.get_session_token());
-        assert!(
-            self.session_type.eq(&SessionType::FiraRangingSession)
-                || self
-                    .session_type
-                    .eq(&SessionType::FiraRangingAndInBandDataSession)
-        );
-
-        if self.state == SessionState::SessionStateActive {
-            const IMMUTABLE_PARAMETERS: &[AppConfigTlvType] = &[AppConfigTlvType::AoaResultReq];
-            if cmd
-                .get_tlvs()
-                .iter()
-                .any(|cfg| IMMUTABLE_PARAMETERS.contains(&cfg.cfg_id))
-            {
-                return SessionSetAppConfigRspBuilder {
-                    status: StatusCode::UciStatusSessionActive,
-                    cfg_status: vec![],
-                }
-                .build();
-            }
-        }
-
-        let (status, invalid_parameters) = if self.state != SessionState::SessionStateInit
-            && self.state != SessionState::SessionStateActive
-        {
-            (StatusCode::UciStatusRejected, Vec::new())
-        } else {
-            let mut app_config = self.app_config.clone();
-            let invalid_parameters = app_config.extend(cmd.get_tlvs());
-            if invalid_parameters.is_empty() {
-                self.app_config = app_config;
-                if self.state == SessionState::SessionStateInit {
-                    self.set_state(
-                        SessionState::SessionStateIdle,
-                        ReasonCode::StateChangeWithSessionManagementCommands,
-                    );
-                }
-                (StatusCode::UciStatusOk, invalid_parameters)
-            } else {
-                (StatusCode::UciStatusInvalidParam, invalid_parameters)
-            }
-        };
-
-        SessionSetAppConfigRspBuilder {
-            status,
-            cfg_status: invalid_parameters,
-        }
-        .build()
-    }
-
-    fn command_get_app_config(&self, cmd: SessionGetAppConfigCmd) -> SessionGetAppConfigRsp {
-        log::debug!(
-            "[{}:0x{:x}] Session Get App Config",
-            self.device_handle,
-            self.id
-        );
-        assert_eq!(self.id, cmd.get_session_token());
-
-        let (status, valid_parameters) = {
-            let (valid_parameters, invalid_parameters) = cmd.get_app_cfg().iter().fold(
-                (Vec::new(), Vec::new()),
-                |(mut valid_parameters, mut invalid_parameters), config_id| {
-                    match AppConfigTlvType::try_from(*config_id) {
-                        Ok(id) => match self.app_config.get_config(id) {
-                            Some(value) => valid_parameters.push(AppConfigTlv {
-                                cfg_id: id,
-                                v: value,
-                            }),
-                            None => invalid_parameters.push(AppConfigTlv {
-                                cfg_id: id,
-                                v: Vec::new(),
-                            }),
-                        },
-                        Err(_) => log::error!("Failed to parse AppConfigTlv: {:?}", *config_id),
-                    }
-                    (valid_parameters, invalid_parameters)
-                },
-            );
-            if invalid_parameters.is_empty() {
-                (StatusCode::UciStatusOk, valid_parameters)
-            } else {
-                (StatusCode::UciStatusFailed, Vec::new())
-            }
-        };
-        SessionGetAppConfigRspBuilder {
-            status,
-            tlvs: valid_parameters,
-        }
-        .build()
-    }
-
-    fn command_get_state(&self, cmd: SessionGetStateCmd) -> SessionGetStateRsp {
-        log::debug!("[{}:0x{:x}] Session Get State", self.device_handle, self.id);
-        assert_eq!(self.id, cmd.get_session_token());
-        SessionGetStateRspBuilder {
-            status: StatusCode::UciStatusOk,
-            session_state: self.state,
-        }
-        .build()
-    }
-
-    fn command_update_controller_multicast_list(
-        &mut self,
-        cmd: SessionUpdateControllerMulticastListCmd,
-    ) -> SessionUpdateControllerMulticastListRsp {
-        log::debug!(
-            "[{}:0x{:x}] Session Update Controller Multicast List",
-            self.device_handle,
-            self.id
-        );
-        assert_eq!(self.id, cmd.get_session_token());
-        if (self.state != SessionState::SessionStateActive
-            && self.state != SessionState::SessionStateIdle)
-            || self.app_config.device_type != DeviceType::Controller
-            || (self.app_config.multi_node_mode != MultiNodeMode::OneToMany
-                && self.app_config.multi_node_mode != MultiNodeMode::ManyToMany)
-        {
-            return SessionUpdateControllerMulticastListRspBuilder {
-                status: StatusCode::UciStatusRejected,
-            }
-            .build();
-        }
-        let action = UpdateMulticastListAction::from_u8(cmd.get_action().into()).unwrap();
-        let mut dst_addresses = self.app_config.dst_mac_addresses.clone();
-        let new_controlees: Vec<Controlee> = match action {
-            UpdateMulticastListAction::Add | UpdateMulticastListAction::Delete => {
-                if let Ok(packet) =
-                    SessionUpdateControllerMulticastListCmdPayload::parse(cmd.get_payload())
-                {
-                    packet
-                        .controlees
-                        .iter()
-                        .map(|controlee| controlee.into())
-                        .collect()
-                } else {
-                    return SessionUpdateControllerMulticastListRspBuilder {
-                        status: StatusCode::UciStatusSyntaxError,
-                    }
-                    .build();
-                }
-            }
-            UpdateMulticastListAction::AddWithShortSubSessionKey => {
-                if let Ok(packet) =
-                    SessionUpdateControllerMulticastListCmd_2_0_16_Byte_Payload::parse(
-                        cmd.get_payload(),
-                    )
-                {
-                    packet
-                        .controlees
-                        .iter()
-                        .map(|controlee| controlee.into())
-                        .collect()
-                } else {
-                    return SessionUpdateControllerMulticastListRspBuilder {
-                        status: StatusCode::UciStatusSyntaxError,
-                    }
-                    .build();
-                }
-            }
-            UpdateMulticastListAction::AddwithExtendedSubSessionKey => {
-                if let Ok(packet) =
-                    SessionUpdateControllerMulticastListCmd_2_0_32_Byte_Payload::parse(
-                        cmd.get_payload(),
-                    )
-                {
-                    packet
-                        .controlees
-                        .iter()
-                        .map(|controlee| controlee.into())
-                        .collect()
-                } else {
-                    return SessionUpdateControllerMulticastListRspBuilder {
-                        status: StatusCode::UciStatusSyntaxError,
-                    }
-                    .build();
-                }
-            }
-        };
-        let mut controlee_status = Vec::new();
-
-        let session_id = self.id;
-        let mut status = StatusCode::UciStatusOk;
-
-        match action {
-            UpdateMulticastListAction::Add
-            | UpdateMulticastListAction::AddWithShortSubSessionKey
-            | UpdateMulticastListAction::AddwithExtendedSubSessionKey => {
-                new_controlees.iter().for_each(|controlee| {
-                    let mut update_status = MulticastUpdateStatusCode::StatusOkMulticastListUpdate;
-                    if !dst_addresses.contains(&controlee.short_address) {
-                        if dst_addresses.len() == MAX_NUMBER_OF_CONTROLEES {
-                            status = StatusCode::UciStatusMulticastListFull;
-                            update_status = MulticastUpdateStatusCode::StatusErrorMulticastListFull;
-                        } else if (action == UpdateMulticastListAction::AddWithShortSubSessionKey
-                            || action == UpdateMulticastListAction::AddwithExtendedSubSessionKey)
-                            && self.app_config.sts_config
-                                != StsConfig::ProvisionedForControleeIndividualKey
-                        {
-                            // If Action is 0x02 or 0x03 for STS_CONFIG values other than
-                            // 0x04, the UWBS shall return SESSION_UPDATE_CONTROLLER_MULTICAST_LIST_NTF
-                            // with Status set to STATUS_ERROR_SUB_SESSION_KEY_NOT_APPLICABLE for each
-                            // Controlee in the Controlee List.
-                            status = StatusCode::UciStatusFailed;
-                            update_status =
-                                MulticastUpdateStatusCode::StatusErrorSubSessionKeyNotApplicable;
-                        } else {
-                            dst_addresses.push(controlee.short_address);
-                        };
-                    }
-                    controlee_status.push(ControleeStatus {
-                        mac_address: match controlee.short_address {
-                            MacAddress::Short(address) => address,
-                            MacAddress::Extended(_) => panic!("Extended address is not supported!"),
-                        },
-                        subsession_id: controlee.sub_session_id,
-                        status: update_status,
-                    });
-                });
-            }
-            UpdateMulticastListAction::Delete => {
-                new_controlees.iter().for_each(|controlee: &Controlee| {
-                    let pica_tx = self.pica_tx.clone();
-                    let address = controlee.short_address;
-                    let attempt_count = self.app_config.in_band_termination_attempt_count;
-                    let mut update_status = MulticastUpdateStatusCode::StatusOkMulticastListUpdate;
-                    if !dst_addresses.contains(&address) {
-                        status = StatusCode::UciStatusAddressNotFound;
-                        update_status = MulticastUpdateStatusCode::StatusErrorKeyFetchFail;
-                    } else {
-                        dst_addresses.retain(|value| *value != address);
-                        // If IN_BAND_TERMINATION_ATTEMPT_COUNT is not equal to 0x00, then the
-                        // UWBS shall transmit the RCM with the “Stop Ranging” bit set to ‘1’
-                        // for IN_BAND_TERMINATION_ATTEMPT_COUNT times to the corresponding
-                        // Controlee.
-                        if attempt_count != 0 {
-                            tokio::spawn(async move {
-                                for _ in 0..attempt_count {
-                                    pica_tx
-                                        .send(PicaCommand::StopRanging(address, session_id))
-                                        .await
-                                        .unwrap()
-                                }
-                            });
-                        }
-                    }
-                    controlee_status.push(ControleeStatus {
-                        mac_address: match address {
-                            MacAddress::Short(addr) => addr,
-                            MacAddress::Extended(_) => panic!("Extended address is not supported!"),
-                        },
-                        subsession_id: controlee.sub_session_id,
-                        status: update_status,
-                    });
-                });
-            }
-        }
-        self.app_config.number_of_controlees = dst_addresses.len();
-        self.app_config.dst_mac_addresses = dst_addresses.clone();
-        // If the multicast list becomes empty, the UWBS shall move the session to
-        // SESSION_STATE_IDLE by sending the SESSION_STATUS_NTF with Reason Code
-        // set to ERROR_INVALID_NUM_OF_CONTROLEES.
-        if self.app_config.dst_mac_addresses.is_empty() {
-            self.set_state(
-                SessionState::SessionStateIdle,
-                ReasonCode::ErrorInvalidNumOfControlees,
-            )
-        }
-        let tx = self.tx.clone();
-        tokio::spawn(async move {
-            tx.send(
-                SessionUpdateControllerMulticastListNtfBuilder {
-                    controlee_status,
-                    remaining_multicast_list_size: dst_addresses.len() as u8,
-                    session_token: session_id,
-                }
-                .build()
-                .into(),
-            )
-            .unwrap()
-        });
-        SessionUpdateControllerMulticastListRspBuilder { status }.build()
-    }
-
-    fn command_range_start(&mut self, cmd: SessionStartCmd) -> SessionStartRsp {
-        log::debug!("[{}:0x{:x}] Range Start", self.device_handle, self.id);
-        assert_eq!(self.id, cmd.get_session_id());
-
-        let status = if self.state != SessionState::SessionStateIdle {
-            StatusCode::UciStatusSessionNotConfigured
-        } else {
-            assert!(self.ranging_task.is_none());
-            assert_eq!(self.state, SessionState::SessionStateIdle);
-
-            let session_id = self.id;
-            let ranging_interval = self.app_config.ranging_interval;
-            let device_handle = self.device_handle;
-            let tx = self.pica_tx.clone();
-            self.ranging_task = Some(tokio::spawn(async move {
-                loop {
-                    time::sleep(ranging_interval).await;
-                    tx.send(PicaCommand::Ranging(device_handle, session_id))
-                        .await
-                        .unwrap();
-                }
-            }));
-            self.set_state(
-                SessionState::SessionStateActive,
-                ReasonCode::StateChangeWithSessionManagementCommands,
-            );
-            StatusCode::UciStatusOk
-        };
-        SessionStartRspBuilder { status }.build()
-    }
-
     pub fn stop_ranging_task(&mut self) {
         if let Some(handle) = &self.ranging_task {
             handle.abort();
             self.ranging_task = None;
         }
     }
-    fn command_range_stop(&mut self, cmd: SessionStopCmd) -> SessionStopRsp {
-        log::debug!("[{}:0x{:x}] Range Stop", self.device_handle, self.id);
-        assert_eq!(self.id, cmd.get_session_id());
 
-        let status = if self.state != SessionState::SessionStateActive {
-            StatusCode::UciStatusSessionActive
-        } else {
-            self.stop_ranging_task();
-            self.set_state(
-                SessionState::SessionStateIdle,
-                ReasonCode::StateChangeWithSessionManagementCommands,
-            );
-            StatusCode::UciStatusOk
-        };
-        SessionStopRspBuilder { status }.build()
-    }
-
-    fn command_get_ranging_count(
-        &self,
-        cmd: SessionGetRangingCountCmd,
-    ) -> SessionGetRangingCountRsp {
-        log::debug!(
-            "[{}:0x{:x}] Range Get Ranging Count",
-            self.device_handle,
-            self.id
-        );
-        assert_eq!(self.id, cmd.get_session_id());
-
-        SessionGetRangingCountRspBuilder {
-            status: StatusCode::UciStatusOk,
-            count: self.sequence_number,
-        }
-        .build()
-    }
-
-    pub fn session_command(&mut self, cmd: SessionConfigCommand) -> SessionConfigResponse {
-        match cmd.specialize() {
-            SessionConfigCommandChild::SessionSetAppConfigCmd(cmd) => {
-                self.command_set_app_config(cmd).into()
-            }
-            SessionConfigCommandChild::SessionGetAppConfigCmd(cmd) => {
-                self.command_get_app_config(cmd).into()
-            }
-            SessionConfigCommandChild::SessionGetStateCmd(cmd) => {
-                self.command_get_state(cmd).into()
-            }
-            SessionConfigCommandChild::SessionUpdateControllerMulticastListCmd(cmd) => {
-                self.command_update_controller_multicast_list(cmd).into()
-            }
-            _ => panic!("Unsupported session command"),
-        }
-    }
-
-    pub fn ranging_command(&mut self, cmd: SessionControlCommand) -> SessionControlResponse {
-        match cmd.specialize() {
-            SessionControlCommandChild::SessionStartCmd(cmd) => {
-                self.command_range_start(cmd).into()
-            }
-            SessionControlCommandChild::SessionStopCmd(cmd) => self.command_range_stop(cmd).into(),
-            SessionControlCommandChild::SessionGetRangingCountCmd(cmd) => {
-                self.command_get_ranging_count(cmd).into()
-            }
-            _ => panic!("Unsupported ranging command"),
-        }
-    }
-
-    pub fn data_message_snd(&mut self, data: DataMessageSnd) -> SessionControlNotification {
+    pub fn data_message_snd(&mut self, data: DataMessageSnd) -> ControlPacket {
         log::debug!("[{}] data_message_snd", self.device_handle);
         let session_token = data.get_session_handle();
         let uci_sequence_number = data.get_data_sequence_number() as u8;
 
         if self.session_type != SessionType::FiraRangingAndInBandDataSession {
-            return DataTransferStatusNtfBuilder {
+            return SessionDataTransferStatusNtfBuilder {
                 session_token,
                 status: DataTransferNtfStatusCode::UciDataTransferStatusSessionTypeNotSupported,
                 tx_count: 1, // TODO: support for retries?
@@ -1230,7 +150,7 @@
 
         self.data.extend_from_slice(data.get_application_data());
 
-        DataCreditNtfBuilder {
+        SessionDataCreditNtfBuilder {
             credit_availability: CreditAvailability::CreditAvailable,
             session_token,
         }
diff --git a/src/uci_packets.pdl b/src/uci_packets.pdl
index 07b19b6..05ba3f3 100644
--- a/src/uci_packets.pdl
+++ b/src/uci_packets.pdl
@@ -15,154 +15,126 @@
 little_endian_packets
 
 enum PacketBoundaryFlag : 1 {
-    COMPLETE = 0x00,
-    NOT_COMPLETE = 0x01,
+    COMPLETE = 0,
+    NOT_COMPLETE = 1,
+}
+
+enum MessageType : 3 {
+    DATA = 0x0,
+    COMMAND = 0x1,
+    RESPONSE = 0x2,
+    NOTIFICATION = 0x3,
 }
 
 enum GroupId : 4 {
-    CORE = 0x00,
-    SESSION_CONFIG = 0x01,
-    SESSION_CONTROL = 0x02,
-    DATA_CONTROL = 0x03,
-    TEST = 0x0d,
-    VENDOR_RESERVED_9 = 0x09,
-    VENDOR_RESERVED_A = 0x0a,
-    VENDOR_RESERVED_B = 0x0b,
-    VENDOR_ANDROID    = 0x0c,
-    VENDOR_RESERVED_E = 0x0e,
-    VENDOR_RESERVED_F = 0x0f,
+    CORE = 0x0,
+    SESSION_CONFIG = 0x1,
+    SESSION_CONTROL = 0x2,
+    DATA_CONTROL = 0x3,
+    VENDOR_RESERVED_9 = 0x9,
+    VENDOR_RESERVED_A = 0xa,
+    VENDOR_RESERVED_B = 0xb,
+    VENDOR_ANDROID    = 0xc,
+    TEST = 0xd,
+    VENDOR_RESERVED_E = 0xe,
+    VENDOR_RESERVED_F = 0xf,
 }
 
-enum DataPacketFormat: 4 {
+enum DataPacketFormat : 4 {
     DATA_SND = 0x01,
     DATA_RCV = 0x02,
 }
 
-// Define a merged enum across GroupId & DataPacketFormat as they are at the same bits in
-// |UciPacketHal|.
-enum GroupIdOrDataPacketFormat : 4 {
-    CORE = 0x00,
-    SESSION_CONFIG_OR_DATA_SND = 0x01,
-    SESSION_CONTROL_OR_DATA_RCV = 0x02,
-    DATA_CONTROL = 0x03,
-    TEST = 0x0d,
-    VENDOR_RESERVED_9 = 0x09,
-    VENDOR_RESERVED_A = 0x0a,
-    VENDOR_RESERVED_B = 0x0b,
-    VENDOR_ANDROID    = 0x0c,
-    VENDOR_RESERVED_E = 0x0e,
-    VENDOR_RESERVED_F = 0x0f,
+enum CoreOpcodeId : 6 {
+    DEVICE_RESET = 0x00,
+    DEVICE_STATUS = 0x01,
+    GET_DEVICE_INFO = 0x02,
+    GET_CAPS_INFO = 0x03,
+    SET_CONFIG = 0x04,
+    GET_CONFIG = 0x05,
+    GENERIC_ERROR = 0x07,
+    QUERY_UWBS_TIMESTAMP = 0x08,
 }
 
-enum CoreOpCode : 6 {
-    CORE_DEVICE_RESET = 0x00,
-    CORE_DEVICE_STATUS_NTF = 0x01,
-    CORE_DEVICE_INFO = 0x02,
-    CORE_GET_CAPS_INFO = 0x03,
-    CORE_SET_CONFIG = 0x04,
-    CORE_GET_CONFIG = 0x05,
-    CORE_DEVICE_SUSPEND = 0x06,
-    CORE_GENERIC_ERROR_NTF = 0x07,
-    CORE_QUERY_UWBS_TIMESTAMP = 0x08,
+enum SessionConfigOpcodeId : 6 {
+    INIT = 0x00,
+    DEINIT = 0x01,
+    STATUS = 0x02,
+    SET_APP_CONFIG = 0x03,
+    GET_APP_CONFIG = 0x04,
+    GET_COUNT = 0x05,
+    GET_STATE = 0x06,
+    UPDATE_CONTROLLER_MULTICAST_LIST = 0x07,
+    UPDATE_DT_ANCHOR_RANGING_ROUNDS = 0x08,
+    UPDATE_DT_TAG_RANGING_ROUNDS = 0x09,
+    QUERY_DATA_SIZE_IN_RANGING = 0x0b,
 }
 
-enum SessionConfigOpCode : 6 {
-    SESSION_INIT = 0x00,
-    SESSION_DEINIT = 0x01,
-    SESSION_STATUS_NTF = 0x02,
-    SESSION_SET_APP_CONFIG = 0x03,
-    SESSION_GET_APP_CONFIG = 0x04,
-    SESSION_GET_COUNT = 0x05,
-    SESSION_GET_STATE = 0x06,
-    SESSION_UPDATE_CONTROLLER_MULTICAST_LIST = 0x07,
-    SESSION_UPDATE_ACTIVE_ROUNDS_ANCHOR = 0x08,
-    SESSION_UPDATE_ACTIVE_ROUNDS_DT_TAG = 0x09,
-    SESSION_SET_INITIATOR_DT_ANCHOR_RR_RDM_LIST = 0x0a,
-    SESSION_QUERY_DATA_SIZE_IN_RANGING = 0x0b,
-    SESSION_SET_HUS_CONFIG = 0x0c,
+enum SessionControlOpcodeId : 6 {
+    START = 0x00, // INFO_NTF
+    STOP = 0x01,
+    GET_RANGING_COUNT = 0x03,
+    DATA_CREDIT = 0x04,
+    DATA_TRANSFER_STATUS = 0x05,
 }
 
-enum SessionControlOpCode : 6 {
-    SESSION_START = 0x00,
-    SESSION_STOP = 0x01,
-    SESSION_RESERVED = 0x02,
-    SESSION_GET_RANGING_COUNT = 0x03,
-    SESSION_DATA_CREDIT_NTF = 0x04,
-    SESSION_DATA_TRANSFER_STATUS_NTF = 0x05,
+enum AndroidOpcodeId : 6 {
+    GET_POWER_STATS = 0x00,
+    SET_COUNTRY_CODE = 0x01,
+    FIRA_RANGE_DIAGNOSTICS = 0x02,
 }
 
-enum AppDataOpCode : 6 {
-    APP_DATA_TX = 0x00,
-    APP_DATA_RX = 0x01,
-}
-
-// Android vendor commands
-enum AndroidOpCode : 6 {
-    ANDROID_GET_POWER_STATS = 0x0,
-    ANDROID_SET_COUNTRY_CODE = 0x1,
-    ANDROID_FIRA_RANGE_DIAGNOSTICS = 0x2,
-}
-
-enum StatusCode : 8 {
+/// [UCI] 8.5 Status Codes
+enum Status : 8 {
     // Generic Status Codes
-    UCI_STATUS_OK = 0x00,
-    UCI_STATUS_REJECTED = 0x01,
-    UCI_STATUS_FAILED = 0x02,
-    UCI_STATUS_SYNTAX_ERROR = 0x03,
-    UCI_STATUS_INVALID_PARAM = 0x04,
-    UCI_STATUS_INVALID_RANGE = 0x05,
-    UCI_STATUS_INVALID_MSG_SIZE = 0x06,
-    UCI_STATUS_UNKNOWN_GID = 0x07,
-    UCI_STATUS_UNKNOWN_OID = 0x08,
-    UCI_STATUS_READ_ONLY = 0x09,
-    UCI_STATUS_COMMAND_RETRY = 0x0A,
-    UCI_STATUS_UNKNOWN = 0x0B,
-    UCI_STATUS_NOT_APPLICABLE = 0x0C,
-    RFU_STATUS_CODE_RANGE_1 = 0x0D..0x10,
+    OK = 0x00,
+    REJECTED = 0x01,
+    FAILED = 0x02,
+    SYNTAX_ERROR = 0x03,
+    INVALID_PARAM = 0x04,
+    INVALID_RANGE = 0x05,
+    INVALID_MESSAGE_SIZE = 0x06,
+    UNKNOWN_GID = 0x07,
+    UNKNOWN_OID = 0x08,
+    READ_ONLY = 0x09,
+    UCI_MESSAGE_RETRY = 0x0A,
+    UNKNOWN = 0x0B,
+    NOT_APPLICABLE = 0x0C,
 
     // UWB Session Specific Status Codes
-    UCI_STATUS_SESSION_NOT_EXIST = 0x11,
-    UCI_STATUS_SESSION_DUPLICATE = 0x12,
-    UCI_STATUS_SESSION_ACTIVE = 0x13,
-    UCI_STATUS_MAX_SESSIONS_EXCEEDED = 0x14,
-    UCI_STATUS_SESSION_NOT_CONFIGURED = 0x15,
-    UCI_STATUS_ACTIVE_SESSIONS_ONGOING = 0x16,
-    UCI_STATUS_MULTICAST_LIST_FULL = 0x17,
-    UCI_STATUS_ADDRESS_NOT_FOUND = 0x18,
-    UCI_STATUS_ADDRESS_ALREADY_PRESENT = 0x19,
-    UCI_STATUS_ERROR_UWB_INITIATION_TIME_TOO_OLD = 0x1A,
-    UCI_STATUS_OK_NEGATIVE_DISTANCE_REPORT = 0x1B,
-    RFU_STATUS_CODE_RANGE_2 = 0x1C..0x1F,
+    ERROR_SESSION_NOT_EXIST = 0x11,
+    ERROR_SESSION_DUPLICATE = 0x12,
+    ERROR_SESSION_ACTIVE = 0x13,
+    ERROR_MAX_SESSIONS_EXCEEDED = 0x14,
+    ERROR_SESSION_NOT_CONFIGURED = 0x15,
+    ERROR_ACTIVE_SESSIONS_ONGOING = 0x16,
+    ERROR_MULTICAST_LIST_FULL = 0x17,
+    ERROR_UWB_INITIATION_TIME_TOO_OLD = 0x1A,
+    OK_NEGATIVE_DISTANCE_REPORT = 0x1B,
 
     // UWB Ranging Session Specific Status Codes
-    UCI_STATUS_RANGING_TX_FAILED = 0x20,
-    UCI_STATUS_RANGING_RX_TIMEOUT = 0x21,
-    UCI_STATUS_RANGING_RX_PHY_DEC_FAILED = 0x22,
-    UCI_STATUS_RANGING_RX_PHY_TOA_FAILED = 0x23,
-    UCI_STATUS_RANGING_RX_PHY_STS_FAILED = 0x24,
-    UCI_STATUS_RANGING_RX_MAC_DEC_FAILED = 0x25,
-    UCI_STATUS_RANGING_RX_MAC_IE_DEC_FAILED = 0x26,
-    UCI_STATUS_RANGING_RX_MAC_IE_MISSING = 0x27,
-    UCI_STATUS_ERROR_ROUND_INDEX_NOT_ACTIVATED = 0x28,
-    UCI_STATUS_ERROR_NUMBER_OF_ACTIVE_RANGING_ROUNDS_EXCEEDED = 0x29,
-    UCI_STATUS_ERROR_DL_TDOA_DEVICE_ADDRESS_NOT_MATCHING_IN_REPLY_TIME_LIST = 0x2A,
-    RFU_STATUS_CODE_RANGE_3 = 0x2B..0x2F,
-
-    // UWB Data Session Specific Status Codes
-    UCI_STATUS_DATA_MAX_TX_PSDU_SIZE_EXCEEDED = 0x30,
-    UCI_STATUS_DATA_RX_CRC_ERROR = 0x31,
-    RFU_STATUS_CODE_RANGE_4 = 0x32..0x4F,
+    RANGING_TX_FAILED = 0x20,
+    RANGING_RX_TIMEOUT = 0x21,
+    RANGING_RX_PHY_DEC_FAILED = 0x22,
+    RANGING_RX_PHY_TOA_FAILED = 0x23,
+    RANGING_RX_PHY_STS_FAILED = 0x24,
+    RANGING_RX_MAC_DEC_FAILED = 0x25,
+    RANGING_RX_MAC_IE_DEC_FAILED = 0x26,
+    RANGING_RX_MAC_IE_MISSING = 0x27,
+    ERROR_ROUND_INDEX_NOT_ACTIVATED = 0x28,
+    ERROR_NUMBER_OF_ACTIVE_RANGING_ROUNDS_EXCEEDED = 0x29,
+    ERROR_DL_TDOA_DEVICE_ADDRESS_NOT_MATCHING_IN_REPLY_TIME_LIST = 0x2A,
 
     // Vendor Specific Status Codes
-    VENDOR_SPECIFIC_STATUS_CODE_RANGE_1 = 0x50..0xFE {
-        UCI_STATUS_ERROR_CCC_SE_BUSY = 0x50,
-        UCI_STATUS_ERROR_CCC_LIFECYCLE = 0x51,
-        UCI_STATUS_ERROR_STOPPED_DUE_TO_OTHER_SESSION_CONFLICT = 0x52,
-        UCI_STATUS_REGULATION_UWB_OFF = 0x53,
+    VENDOR_SPECIFIC = 0x50..0xFF {
+        ERROR_CCC_SE_BUSY = 0x50,
+        ERROR_CCC_LIFECYCLE = 0x51,
+        ERROR_STOPPED_DUE_TO_OTHER_SESSION_CONFLICT = 0x52,
+        REGULATION_UWB_OFF = 0x53,
     },
 
-    // For internal usage, we will use 0xFF as default.
-    VENDOR_SPECIFIC_STATUS_CODE_2 = 0xFF,
+    // All others reserved for future use
+    RFU = ..,
 }
 
 // This needs a separate StatusCode as the Status code values in the DATA_RCV packet have
@@ -194,18 +166,14 @@
     UWBS_RESET = 0x00,
 }
 
-enum DeviceConfigId : 8 {
-    DEVICE_STATE = 0x00,
-    LOW_POWER_MODE = 0x01,
-}
-
+// [UCI] Table 45: APP Configuration Parameters IDs
 enum AppConfigTlvType : 8 {
     DEVICE_TYPE = 0x00,
     RANGING_ROUND_USAGE = 0x01,
     STS_CONFIG = 0x02,
     MULTI_NODE_MODE = 0x03,
     CHANNEL_NUMBER = 0x04,
-    NO_OF_CONTROLEE = 0x05,
+    NUMBER_OF_CONTROLEES = 0x05,
     DEVICE_MAC_ADDRESS = 0x06,
     DST_MAC_ADDRESS = 0x07,
     SLOT_DURATION = 0x08,
@@ -214,9 +182,9 @@
     MAC_FCS_TYPE = 0x0B,
     RANGING_ROUND_CONTROL = 0x0C,
     AOA_RESULT_REQ = 0x0D,
-    RNG_DATA_NTF = 0x0E,
-    RNG_DATA_NTF_PROXIMITY_NEAR = 0x0F,
-    RNG_DATA_NTF_PROXIMITY_FAR = 0x10,
+    SESSION_INFO_NTF_CONFIG = 0x0E,
+    NEAR_PROXIMITY_CONFIG = 0x0F,
+    FAR_PROXIMITY_CONFIG = 0x10,
     DEVICE_ROLE = 0x11,
     RFRAME_CONFIG = 0x12,
     RSSI_REPORTING = 0x13,
@@ -228,14 +196,11 @@
     DATA_REPETITION_COUNT = 0x19,
     RANGING_TIME_STRUCT = 0x1A,
     SLOTS_PER_RR = 0x1B,
-    TX_ADAPTIVE_PAYLOAD_POWER = 0x1C,
-    // TODO: Ensure this value is correct in the final 2.0 specification.
-    RNG_DATA_NTF_AOA_BOUND = 0x1D,
-    RESPONDER_SLOT_INDEX = 0x1E,
+    AOA_BOUND_CONFIG = 0x1D,
     PRF_MODE = 0x1F,
     CAP_SIZE_RANGE = 0x20,
     TX_JITTER_WINDOW_SIZE = 0x21,
-    SCHEDULED_MODE = 0x22,
+    SCHEDULE_MODE = 0x22,
     KEY_ROTATION = 0x23,
     KEY_ROTATION_RATE = 0x24,
     SESSION_PRIORITY = 0x25,
@@ -252,13 +217,7 @@
     SUB_SESSION_ID = 0x30,
     BPRF_PHR_DATA_RATE = 0x31,
     MAX_NUMBER_OF_MEASUREMENTS = 0x32,
-    UL_TDOA_TX_INTERVAL = 0x33,
-    UL_TDOA_RANDOM_WINDOW = 0x34,
     STS_LENGTH = 0x35,
-    SUSPEND_RANGING_ROUNDS = 0x36,
-    UL_TDOA_NTF_REPORT_CONFIG = 0x37,
-    UL_TDOA_DEVICE_ID = 0x38,
-    UL_TDOA_TX_TIMESTAMP = 0x39,
     MIN_FRAMES_PER_RR = 0x3A,
     MTU_SIZE = 0x3B,
     INTER_FRAME_INTERVAL = 0x3C,
@@ -268,10 +227,10 @@
     DL_TDOA_ANCHOR_CFO = 0x40,
     DL_TDOA_ANCHOR_LOCATION = 0x41,
     DL_TDOA_TX_ACTIVE_RANGING_ROUNDS = 0x42,
-    DL_TDOA_BLOCK_STRIDING = 0x43,
+    DL_TDOA_BLOCK_SKIPPING = 0x43,
     DL_TDOA_TIME_REFERENCE_ANCHOR = 0x44,
     SESSION_KEY = 0x45,
-    SUBSESSION_KEY = 0x46,
+    SUB_SESSION_KEY = 0x46,
     SESSION_DATA_TRANSFER_STATUS_NTF_CONFIG = 0x47,
     SESSION_TIME_BASE = 0x48,
     DL_TDOA_RESPONDER_TOF = 0x49,
@@ -279,9 +238,9 @@
     SECURE_RANGING_CSW_LENGTH = 0x4B,
     APPLICATION_DATA_ENDPOINT = 0x4C,
     OWR_AOA_MEASUREMENT_NTF_PERIOD = 0x4D,
-    RFU_APP_CFG_TLV_TYPE_RANGE = 0x4E..0x9F,
+    RFU = 0x4E..0x9F,
 
-    VENDOR_SPECIFIC_APP_CFG_TLV_TYPE_RANGE_1 = 0xA0..0xDF {
+    VENDOR_SPECIFIC_1 = 0xA0..0xDF {
         // CCC specific
         CCC_HOP_MODE_KEY = 0xA0,
         CCC_UWB_TIME0 = 0xA1,
@@ -293,9 +252,10 @@
     },
 
     // Reserved for extension IDs.
-    RFU_APP_CFG_TLV_TYPE_RANGE_3 = 0xE0..0xE2,
+    // ID is 2 Octets in length. Refer section 8.1 for details
+    ID_EXTENSION = 0xE0..0xE2,
 
-    VENDOR_SPECIFIC_APP_CFG_TLV_TYPE_RANGE_2 = 0xE3..0xFF {
+    VENDOR_SPECIFIC_2 = 0xE3..0xFF {
         // Interleaving ratio if AOA_RESULT_REQ is set to 0xF0.
         NB_OF_RANGE_MEASUREMENTS = 0xE3,
         NB_OF_AZIMUTH_MEASUREMENTS = 0xE4,
@@ -305,10 +265,189 @@
     },
 }
 
-enum FrameReportTlvType : 8 {
-    RSSI = 0x0,
-    AOA = 0x1,
-    CIR = 0x2,
+enum DeviceType : 8 {
+    // [MAC] 5.1.2
+    // Device utilizing the ranging features set through Control Messages
+    CONTROLEE = 0x00,
+    // [MAC] 5.1.1
+    // Device controlling the ranging features through Control Messages
+    CONTROLLER = 0x01,
+}
+
+enum RangingRoundUsage : 8 {
+    SS_TWR_DEFERRED_MODE = 0x01,
+    DS_TWR_DEFERRED_MODE = 0x02,
+    SS_TWR_NON_DEFERRED_MODE = 0x03,
+    DS_TWR_NON_DEFERRED_MODE = 0x04,
+    ON_WAY_RANGING_DL_TDOA = 0x05,
+    OWR_AOA_MEASUREMENT = 0x06,
+    ESS_TWR_NON_DEFERRED = 0x07,
+    ADS_TWR_NON_DEFERRED = 0x08,
+}
+
+enum StsConfig : 8 {
+    STATIC = 0x00, // Default
+    DYNAMIC = 0x01,
+    DYNAMIC_FOR_RESPONDER_SUB_SESSION_KEY = 0x02,
+    PROVISIONED = 0x03,
+    PROVISIONED_FOR_RESPONDER_SUB_SESSION_KEY = 0x04,
+}
+
+enum MultiNodeMode : 8 {
+    ONE_TO_ONE = 0x00,
+    ONE_TO_MANY = 0x01,
+}
+
+enum ChannelNumber : 8 {
+    CHANNEL_NUMBER_5 = 0x05,
+    CHANNEL_NUMBER_6 = 0x06,
+    CHANNEL_NUMBER_8 = 0x08,
+    CHANNEL_NUMBER_9 = 0x09, // Default
+    CHANNEL_NUMBER_10 = 0x0a,
+    CHANNEL_NUMBER_12 = 0x0c,
+    CHANNEL_NUMBER_13 = 0x0d,
+    CHANNEL_NUMBER_14 = 0x0e,
+}
+
+enum MacFcsType : 8 {
+    CRC_16 = 0x00, // Default
+    CRC_32 = 0x01,
+}
+
+struct RangingRoundControl {
+    rrrm : 1, // Default 1
+    _fixed_ = 1 : 1,
+    rcp : 1, // Default 0
+    _reserved_ : 3,
+    mrp : 1, // Default 0
+    mrm : 1, // Default 0
+}
+
+enum AoaResultReq : 8 {
+    AOA_DISABLED = 0x00,
+    AOA_ENABLED = 0x01, // Default
+    AOA_ENABLED_AZIMUTH_ONLY = 0x02,
+    AOA_ENABLED_ELEVATION_ONLY = 0x03,
+}
+
+enum SessionInfoNtfConfig : 8 {
+    DISABLE = 0x00,
+    ENABLE = 0x01, // Default
+    ENABLE_PROXIMITY_TRIGGER = 0x02,
+    ENABLE_AOA_TRIGGER = 0x03,
+    ENABLE_PROXIMITY_AOA_TRIGGER = 0x04,
+    ENABLE_PROXIMITY_EDGE_TRIGGER = 0x05,
+    ENABLE_AOA_EDGE_TRIGGER = 0x06,
+    ENABLE_PROXIMITY_AOA_EDGE_TRIGGER = 0x07,
+}
+
+enum DeviceRole : 8 {
+    // [MAC] 5.1.3
+    // Device initiating a ranging exchange with a ranging initiation message
+    RESPONDER = 0x00,
+    // [MAC] 5.1.4
+    // Device responding to ranging initiation messages
+    INITIATOR = 0x01,
+    ADVERTISER = 0x05,
+    OBSERVER = 0x06,
+    DT_ANCHOR = 0x07,
+    DT_TAG = 0x08,
+}
+
+enum RframeConfig : 8 {
+    SP0 = 0x00,
+    SP1 = 0x01,
+    SP3 = 0x03, // Default
+}
+
+enum RssiReporting : 8 {
+    DISABLE = 0x00, // Default
+    ENABLE = 0x01,
+}
+
+enum PsduDataRate : 8 {
+    DATA_RATE_6M81 = 0x00,
+    DATA_RATE_7M80 = 0x01,
+    DATA_RATE_27M2 = 0x02,
+    DATA_RATE_31M2 = 0x03,
+}
+
+enum PreambleDuration : 8 {
+    DURATION_32_SYMBOLS = 0x00,
+    DURATION_64_SYMBOLS = 0x01, // Default
+}
+
+enum LinkLayerMode : 8 {
+    BYPASS_MODE = 0x00, // Default
+}
+
+enum RangingTimeStruct : 8 {
+    BLOCK_BASED_SCHEDULING = 0x01, // Default
+}
+
+enum PrfMode : 8 {
+    BPRF_MODE = 0x00, // Default
+    HPRF_MODE_124M8 = 0x01,
+    HPRF_MODE_249M6 = 0x02,
+}
+
+enum ScheduleMode : 8 {
+    CONTENTION_BASED = 0x00,
+    TIME_SCHEDULED = 0x01,
+}
+
+enum KeyRotation : 8 {
+    DISABLE = 0x00, // Default
+    ENABLE = 0x01,
+}
+
+enum MacAddressMode : 8 {
+    // MAC address is 2 bytes and 2 bytes to be used in MAC header
+    MODE_0 = 0x00, // Default
+    // MAC address is 8 bytes and 2 bytes to be used in MAC header
+    // (Not supported).
+    MODE_1 = 0x01,
+    // MAC address is 8 bytes and 8 bytes to be used in MAC header
+    MODE_2 = 0x02,
+}
+
+enum HoppingMode : 8 {
+    DISABLE = 0x00, // Default
+    ENABLE = 0x01,
+}
+
+struct ResultReportConfig {
+    tof : 1, // Default 1
+    aoa_azimuth : 1,
+    aoa_elevation : 1,
+    aoa_fom : 1,
+    _reserved_ : 4,
+}
+
+enum BprfPhrDataRate : 8 {
+    DATA_RATE_850K = 0x00, // Default
+    DATA_RATE_6M81 = 0x01
+}
+
+enum StsLength : 8 {
+    LENGTH_32_SYMBOLS = 0x00, // Default
+    LENGTH_64_SYMBOLS = 0x01,
+    LENGTH_128_SYMBOLS = 0x02,
+}
+
+enum DlTdoaRangingMethod : 8 {
+    SS_TWR = 0x00,
+    DS_TWR = 0x01, // Default
+}
+
+enum DlTdoaAnchorCfo : 8 {
+    ANCHOR_CFO_NOT_INCLUDED = 0x00,
+    ANCHOR_CFO_INCLUDED = 0x01, // Default
+}
+
+enum SessionDataTransferStatusNtfConfig : 8 {
+    DISABLE = 0x00, // Default
+    ENABLE = 0x01,
 }
 
 enum CapTlvType : 8 {
@@ -441,15 +580,17 @@
     VENDOR_SPECIFIC_REASON_CODE_2 = 0xFF,
 }
 
-enum MulticastUpdateStatusCode : 8 {
-    STATUS_OK_MULTICAST_LIST_UPDATE = 0x00,
-    STATUS_ERROR_MULTICAST_LIST_FULL = 0x01,
-    STATUS_ERROR_KEY_FETCH_FAIL = 0x02,
-    STATUS_ERROR_SUB_SESSION_ID_NOT_FOUND = 0x03,
-    STATUS_ERROR_SUB_SESSION_KEY_NOT_FOUND = 0x05,
-    STATUS_ERROR_SUB_SESSION_KEY_NOT_APPLICABLE = 0x06,
-    STATUS_ERROR_SESSION_KEY_NOT_FOUND = 0x07,
-    STATUS_ERROR_ADDRESS_ALREADY_PRESENT = 0x08,
+/// [UCI] Table 40: Multicast list update status codes
+enum MulticastUpdateStatus : 8 {
+    OK_MULTICAST_LIST_UPDATE = 0x00,
+    ERROR_MULTICAST_LIST_FULL = 0x01,
+    ERROR_KEY_FETCH_FAIL = 0x02,
+    ERROR_SUB_SESSION_ID_NOT_FOUND = 0x03,
+    ERROR_SUB_SESSION_KEY_NOT_FOUND = 0x04,
+    ERROR_SUB_SESSION_KEY_NOT_APPLICABLE = 0x05,
+    ERROR_SESSION_KEY_NOT_FOUND = 0x06,
+    ERROR_ADDRESS_NOT_FOUND = 0x07,
+    ERROR_ADDRESS_ALREADY_PRESENT = 0x08,
 }
 
 enum MacAddressIndicator : 8 {
@@ -468,15 +609,6 @@
     DEVICE_TEST_MODE = 0xD0,
 }
 
-enum MessageType: 3 {
-    DATA = 0x00,
-    COMMAND = 0x01,
-    RESPONSE = 0x02,
-    NOTIFICATION = 0x03,
-    RESERVED_FOR_TESTING_1 = 0x04,
-    RESERVED_FOR_TESTING_2 = 0x05,
-}
-
 // Used to parse message type
 packet CommonPacketHeader {
   _reserved_ : 4,
@@ -509,9 +641,6 @@
     gid : GroupId,
     _reserved_ : 1,
     mt : MessageType,
-    opcode: 6,
-    _reserved_: 2,
-    _reserved_: 16,
     _payload_,
 }
 
@@ -534,109 +663,76 @@
 
 packet DataMessageRcv : DataPacket (dpf = DATA_RCV, mt = DATA) {
     session_handle: 32,
-    status : StatusCode, 
+    status: Status,
     source_address: 64,
     data_sequence_number: 16,
     _size_(application_data): 16,
     application_data: 8[]
 }
 
-// TODO(b/202760099): Handle fragmentation of packets if the size exceed max allowed.
-packet UciCommand : ControlPacket (mt = COMMAND) {
-    _payload_,
+packet CorePacket : ControlPacket (gid = CORE) {
+  oid : CoreOpcodeId,
+  _reserved_ : 2,
+  _reserved_ : 16,
+  _payload_,
 }
 
-packet UciResponse : ControlPacket (mt = RESPONSE) {
-    _payload_,
+packet SessionConfigPacket : ControlPacket (gid = SESSION_CONFIG) {
+  oid : SessionConfigOpcodeId,
+  _reserved_ : 2,
+  _reserved_ : 16,
+  _payload_,
 }
 
-packet UciNotification : ControlPacket (mt = NOTIFICATION) {
-    _payload_,
+packet SessionControlPacket : ControlPacket (gid = SESSION_CONTROL) {
+  oid : SessionControlOpcodeId,
+  _reserved_ : 2,
+  _reserved_ : 16,
+  _payload_,
 }
 
-packet CoreCommand : UciCommand (gid = CORE) {
-    _body_,
+packet AndroidPacket : ControlPacket (gid = VENDOR_ANDROID) {
+  oid : AndroidOpcodeId,
+  _reserved_ : 2,
+  _reserved_ : 16,
+  _payload_,
 }
 
-packet CoreResponse : UciResponse (gid = CORE) {
-    _body_,
-}
+// ---------------------------- Core group ---------------------------------- //
 
-packet CoreNotification : UciNotification (gid = CORE) {
-    _body_,
-}
-
-packet SessionConfigCommand : UciCommand (gid = SESSION_CONFIG) {
-    _body_,
-}
-
-packet SessionConfigResponse : UciResponse (gid = SESSION_CONFIG) {
-    _body_,
-}
-
-packet SessionConfigNotification : UciNotification (gid = SESSION_CONFIG) {
-    _body_,
-}
-
-packet SessionControlCommand : UciCommand (gid = SESSION_CONTROL) {
-    session_id: 32,
-    _body_,
-}
-
-packet SessionControlResponse : UciResponse (gid = SESSION_CONTROL) {
-    _body_,
-}
-
-packet SessionControlNotification : UciNotification (gid = SESSION_CONTROL) {
-    _body_,
-}
-
-packet AndroidCommand : UciCommand (gid = VENDOR_ANDROID) {
-    _body_,
-}
-
-packet AndroidResponse : UciResponse (gid = VENDOR_ANDROID) {
-    _body_,
-}
-
-packet AndroidNotification : UciNotification (gid = VENDOR_ANDROID) {
-    _body_,
-}
-
-// TODO: b/202760099: Use the correspnding opcode enum instead of the raw value in the |opcode| field.
-packet DeviceResetCmd : CoreCommand (opcode = 0x0) { //CORE_DEVICE_RESET
+packet CoreDeviceResetCmd : CorePacket (mt = COMMAND, oid = DEVICE_RESET) {
     reset_config: ResetConfig,
 }
 
-test DeviceResetCmd {
+test CoreDeviceResetCmd {
     "\x20\x00\x00\x01\x00\x00\x00\x00",
 }
 
-packet DeviceResetRsp : CoreResponse (opcode = 0x0) { //CORE_DEVICE_RESET
-    status: StatusCode,
+packet CoreDeviceResetRsp : CorePacket (mt = RESPONSE, oid = DEVICE_RESET) {
+    status: Status,
 }
 
-test DeviceResetRsp {
+test CoreDeviceResetRsp {
     "\x40\x00\x00\x01\x00\x00\x00\x00",
 }
 
-packet DeviceStatusNtf : CoreNotification (opcode = 0x1) { //CORE_DEVICE_STATUS_NTF
+packet CoreDeviceStatusNtf : CorePacket (mt = NOTIFICATION, oid = DEVICE_STATUS) {
     device_state: DeviceState,
 }
 
-test DeviceStatusNtf {
+test CoreDeviceStatusNtf {
     "\x60\x01\x00\x01\x00\x00\x00\x01",
 }
 
-packet GetDeviceInfoCmd : CoreCommand (opcode = 0x2) { //CORE_DEVICE_INFO
+packet CoreGetDeviceInfoCmd : CorePacket (mt = COMMAND, oid = GET_DEVICE_INFO) {
 }
 
-test GetDeviceInfoCmd {
+test CoreGetDeviceInfoCmd {
     "\x20\x02\x00\x00\x00\x00\x00",
 }
 
-packet GetDeviceInfoRsp : CoreResponse (opcode = 0x2) { //CORE_DEVICE_INFO
-    status: StatusCode,
+packet CoreGetDeviceInfoRsp : CorePacket (mt = RESPONSE, oid = GET_DEVICE_INFO) {
+    status: Status,
     uci_version: 16,
     mac_version: 16,
     phy_version: 16,
@@ -645,14 +741,14 @@
     vendor_spec_info: 8[],
 }
 
-test GetDeviceInfoRsp {
+test CoreGetDeviceInfoRsp {
     "\x40\x02\x00\x0b\x00\x00\x00\x01\x01\x00\x02\x00\x03\x00\x04\x00\x01\x0a",
 }
 
-packet GetCapsInfoCmd : CoreCommand (opcode = 0x3) { //CORE_GET_CAPS_INFO
+packet CoreGetCapsInfoCmd : CorePacket (mt = COMMAND, oid = GET_CAPS_INFO) {
 }
 
-test GetCapsInfoCmd {
+test CoreGetCapsInfoCmd {
     "\x20\x03\x00\x00\x00\x00\x00",
 }
 
@@ -663,84 +759,91 @@
 }
 
 
-packet GetCapsInfoRsp : CoreResponse (opcode = 0x3) { //CORE_GET_CAPS_INFO
-    status: StatusCode,
+packet CoreGetCapsInfoRsp : CorePacket (mt = RESPONSE, oid = GET_CAPS_INFO) {
+    status: Status,
     _count_(tlvs): 8,
     tlvs: CapTlv[],
 }
 
-test GetCapsInfoRsp {
+test CoreGetCapsInfoRsp {
     "\x40\x03\x00\x05\x00\x00\x00\x00\x01\x00\x01\x01",
 }
 
-struct DeviceConfigTlv {
-    cfg_id: DeviceConfigId,
-    _count_(v): 8,
-    v: 8[],
+// [UCI] Table 44: Device Configuration Parameters
+enum ConfigParameterId : 8 {
+    DEVICE_STATE = 0x00,
+    LOW_POWER_MODE = 0x01,
+    RFU = ..,
 }
 
-packet SetConfigCmd : CoreCommand (opcode = 0x4) { //CORE_SET_CONFIG
-    _count_(tlvs): 8,
-    tlvs: DeviceConfigTlv[],
+struct ConfigParameter {
+    id: ConfigParameterId,
+    _size_(value): 8,
+    value: 8[],
 }
 
-test SetConfigCmd {
+packet CoreSetConfigCmd : CorePacket (mt = COMMAND, oid = SET_CONFIG) {
+    _count_(parameters): 8,
+    parameters: ConfigParameter[],
+}
+
+test CoreSetConfigCmd {
     "\x20\x04\x00\x03\x00\x00\x00\x01\x01\x00",
 }
 
-struct DeviceConfigStatus {
-    cfg_id: DeviceConfigId,
-    status: StatusCode,
+struct ConfigParameterStatus {
+    id: ConfigParameterId,
+    status: Status,
 }
 
-packet SetConfigRsp : CoreResponse (opcode = 0x4) { //CORE_SET_CONFIG
-    status: StatusCode,
-    _count_(cfg_status): 8,
-    cfg_status: DeviceConfigStatus[],
+packet CoreSetConfigRsp : CorePacket (mt = RESPONSE, oid = SET_CONFIG) {
+    status: Status,
+    _count_(parameters): 8,
+    parameters: ConfigParameterStatus[],
 }
 
-test SetConfigRsp {
+test CoreSetConfigRsp {
     "\x40\x04\x00\x04\x00\x00\x00\x01\x01\x01\x01",
     "\x40\x04\x00\x04\x00\x00\x00\x01\x01\x01\x0B",
 }
 
-packet GetConfigCmd : CoreCommand (opcode = 0x5) { //CORE_GET_CONFIG
-    _count_(cfg_id): 8,
-    cfg_id: 8[], // DeviceConfigId (Infra does not allow array of enums)
+packet CoreGetConfigCmd : CorePacket (mt = COMMAND, oid = GET_CONFIG) {
+    _count_(parameter_ids): 8,
+    parameter_ids: ConfigParameterId[],
 }
 
-test GetConfigCmd {
+test CoreGetConfigCmd {
     "\x20\x05\x00\x02\x00\x00\x00\x01\x01",
 }
 
-packet GetConfigRsp : CoreResponse (opcode = 0x5) { //CORE_GET_CONFIG
-    status: StatusCode,
-    _count_(tlvs): 8,
-    tlvs: DeviceConfigTlv[]
+packet CoreGetConfigRsp : CorePacket (mt = RESPONSE, oid = GET_CONFIG) {
+    status: Status,
+    _count_(parameters): 8,
+    parameters: ConfigParameter[]
 }
 
-test GetConfigRsp {
+test CoreGetConfigRsp {
     "\x40\x05\x00\x05\x00\x00\x00\x01\x01\x00\x01\x01",
 }
 
-packet GenericError : CoreNotification (opcode = 0x7) { //CORE_GENERIC_ERROR_NTF
-    status: StatusCode,
+packet CoreGenericErrorNtf : CorePacket (mt = NOTIFICATION, oid = GENERIC_ERROR) {
+    status: Status,
 }
 
-test GenericError {
+test CoreGenericErrorNtf {
     "\x60\x07\x00\x01\x00\x00\x00\x01",
 }
 
 
-packet CoreQueryTimeStampCmd : CoreCommand (opcode = 0x8) { //CORE_QUERY_UWBS_TIMESTAMP
+packet CoreQueryTimeStampCmd : CorePacket (mt = COMMAND, oid = QUERY_UWBS_TIMESTAMP) {
 }
 
 test CoreQueryTimeStampCmd {
     "\x20\x08\x00\\x00",
 }
 
-packet CoreQueryTimeStampRsp : CoreResponse (opcode = 0x8) { //CORE_QUERY_UWBS_TIMESTAMP
-    status: StatusCode,
+packet CoreQueryTimeStampRsp : CorePacket (mt = RESPONSE, oid = QUERY_UWBS_TIMESTAMP) {
+    status: Status,
     timeStamp: 64,
 }
 
@@ -748,7 +851,9 @@
     "\x40\x08\x00\x09\x00\x00\x00\x01\x01\x00\x01\x01\x01",
 }
 
-packet SessionInitCmd : SessionConfigCommand (opcode = 0x0) { //SESSION_INIT
+// ---------------------- Session Config group ------------------------------ //
+
+packet SessionInitCmd : SessionConfigPacket (mt = COMMAND, oid = INIT) {
     session_id: 32,
     session_type: SessionType,
 }
@@ -759,8 +864,8 @@
 
 // FIRA version 2 introduces a new version of SESSION_INIT_RSP which
 // includes UWBS generated session handle.
-packet SessionInitRsp_V2 : SessionConfigResponse (opcode = 0x0) { //SESSION_INIT
-    status: StatusCode,
+packet SessionInitRsp_V2 : SessionConfigPacket (mt = RESPONSE, oid = INIT) {
+    status: Status,
     session_handle: 32,
 }
 
@@ -768,15 +873,15 @@
     "\x41\x00\x00\x01\x00\x00\x00\x11\x00\x00\x00\x01",
 }
 
-packet SessionInitRsp : SessionConfigResponse (opcode = 0x0) { //SESSION_INIT
-    status: StatusCode,
+packet SessionInitRsp : SessionConfigPacket (mt = RESPONSE, oid = INIT) {
+    status: Status,
 }
 
 test SessionInitRsp {
     "\x41\x00\x00\x01\x00\x00\x00\x11",
 }
 
-packet SessionDeinitCmd : SessionConfigCommand (opcode = 0x1) { //SESSION_DEINIT
+packet SessionDeinitCmd : SessionConfigPacket (mt = COMMAND, oid = DEINIT) {
     session_token: 32, // Session ID or Session Handle (based on UWBS version)
 }
 
@@ -784,15 +889,15 @@
     "\x21\x01\x00\x04\x00\x00\x00\x01\x02\x03\x04",
 }
 
-packet SessionDeinitRsp : SessionConfigResponse (opcode = 0x1) { //SESSION_DEINIT
-    status: StatusCode,
+packet SessionDeinitRsp : SessionConfigPacket (mt = RESPONSE, oid = DEINIT) {
+    status: Status,
 }
 
 test SessionDeinitRsp {
     "\x41\x01\x00\x01\x00\x00\x00\x00",
 }
 
-packet SessionStatusNtf : SessionConfigNotification (opcode = 0x2) { //SESSION_STATUS_NTF
+packet SessionStatusNtf : SessionConfigPacket (mt = NOTIFICATION, oid = STATUS) {
     session_token: 32, // Session ID or Session Handle (based on UWBS version)
     session_state: SessionState,
     // TODO(b/272775225): Switch back to the enum type ReasonCode, once PDL supports defining a
@@ -811,7 +916,7 @@
     v: 8[],
 }
 
-packet SessionSetAppConfigCmd : SessionConfigCommand (opcode = 0x3) { //SESSION_SET_APP_CONFIG
+packet SessionSetAppConfigCmd : SessionConfigPacket (mt = COMMAND, oid = SET_APP_CONFIG) {
     session_token: 32, // Session ID or Session Handle (based on UWBS version)
     _count_(tlvs): 8,
     tlvs: AppConfigTlv[]
@@ -823,11 +928,11 @@
 
 struct AppConfigStatus {
     cfg_id: AppConfigTlvType,
-    status: StatusCode,
+    status: Status,
 }
 
-packet SessionSetAppConfigRsp : SessionConfigResponse (opcode = 0x3) { //SESSION_SET_APP_CONFIG
-    status: StatusCode,
+packet SessionSetAppConfigRsp : SessionConfigPacket (mt = RESPONSE, oid = SET_APP_CONFIG) {
+    status: Status,
     _count_(cfg_status): 8,
     cfg_status: AppConfigStatus[],
 }
@@ -836,18 +941,18 @@
     "\x41\x03\x00\x04\x00\x00\x00\x01\x01\x01\x00",
 }
 
-packet SessionGetAppConfigCmd : SessionConfigCommand (opcode = 0x4) { //SESSION_GET_APP_CONFIG
+packet SessionGetAppConfigCmd : SessionConfigPacket (mt = COMMAND, oid = GET_APP_CONFIG) {
     session_token: 32, // Session ID or Session Handle (based on UWBS version)
     _count_(app_cfg): 8,
-    app_cfg: 8[], // AppConfigTlvType (Infra does not allow array of enums)
+    app_cfg: AppConfigTlvType[],
 }
 
 test SessionGetAppConfigCmd {
     "\x21\x04\x00\x05\x00\x00\x00\x01\x02\x03\x04\x00",
 }
 
-packet SessionGetAppConfigRsp : SessionConfigResponse (opcode = 0x4) { //SESSION_GET_APP_CONFIG
-    status: StatusCode,
+packet SessionGetAppConfigRsp : SessionConfigPacket (mt = RESPONSE, oid = GET_APP_CONFIG) {
+    status: Status,
     _count_(tlvs): 8,
     tlvs: AppConfigTlv[],
 }
@@ -856,15 +961,15 @@
     "\x41\x04\x00\x02\x00\x00\x00\x01\x00",
 }
 
-packet SessionGetCountCmd : SessionConfigCommand (opcode = 0x5) { //SESSION_GET_COUNT
+packet SessionGetCountCmd : SessionConfigPacket (mt = COMMAND, oid = GET_COUNT) {
 }
 
 test SessionGetCountCmd {
     "\x21\x05\x00\x00\x00\x00\x00",
 }
 
-packet SessionGetCountRsp : SessionConfigResponse (opcode = 0x5) { //SESSION_GET_COUNT
-    status: StatusCode,
+packet SessionGetCountRsp : SessionConfigPacket (mt = RESPONSE, oid = GET_COUNT) {
+    status: Status,
     session_count: 8,
 }
 
@@ -872,7 +977,7 @@
     "\x41\x05\x00\x02\x00\x00\x00\x00\x01",
 }
 
-packet SessionGetStateCmd : SessionConfigCommand (opcode = 0x6) { //SESSION_GET_STATE
+packet SessionGetStateCmd : SessionConfigPacket (mt = COMMAND, oid = GET_STATE) {
     session_token: 32, // Session ID or Session Handle (based on UWBS version)
 }
 
@@ -880,8 +985,8 @@
     "\x21\x06\x00\x04\x00\x00\x00\x00\x01\x02\x03",
 }
 
-packet SessionGetStateRsp : SessionConfigResponse (opcode = 0x6) { //SESSION_GET_STATE
-    status: StatusCode,
+packet SessionGetStateRsp : SessionConfigPacket (mt = RESPONSE, oid = GET_STATE) {
+    status: Status,
     session_state: SessionState,
 }
 
@@ -889,7 +994,15 @@
     "\x41\x06\x00\x02\x00\x00\x00\x00\x01",
 }
 
-packet SessionUpdateDtTagRangingRoundsCmd : SessionConfigCommand (opcode = 0x9) { //SESSION_UPDATE_ACTIVE_ROUNDS_DT_TAG
+packet SessionUpdateDtAnchorRangingRoundsCmd : SessionConfigPacket (mt = COMMAND, oid = UPDATE_DT_ANCHOR_RANGING_ROUNDS) {
+    // TODO
+}
+
+packet SessionUpdateDtAnchorRangingRoundsRsp : SessionConfigPacket (mt = RESPONSE, oid = UPDATE_DT_ANCHOR_RANGING_ROUNDS) {
+    // TODO
+}
+
+packet SessionUpdateDtTagRangingRoundsCmd : SessionConfigPacket (mt = COMMAND, oid = UPDATE_DT_TAG_RANGING_ROUNDS) {
     session_token: 32, // Session ID or Session Handle (based on UWBS version)
     _count_(ranging_round_indexes): 8,
     ranging_round_indexes: 8[],
@@ -899,8 +1012,8 @@
     "\x21\x09\x00\x0a\x00\x00\x00\x03\x03\x0f\x0c\x05\x08\x00\x00\x00\x00",
 }
 
-packet SessionUpdateDtTagRangingRoundsRsp : SessionConfigResponse (opcode = 0x9) { //SESSION_UPDATE_ACTIVE_ROUNDS_DT_TAG
-    status: StatusCode,
+packet SessionUpdateDtTagRangingRoundsRsp : SessionConfigPacket (mt = RESPONSE, oid = UPDATE_DT_TAG_RANGING_ROUNDS) {
+    status: Status,
     _count_(ranging_round_indexes): 8,
     ranging_round_indexes: 8[],
 }
@@ -926,36 +1039,20 @@
     subsession_key: 8[32],
 }
 
+/// cf. [UCI] 7.7
 enum UpdateMulticastListAction: 8 {
     ADD_CONTROLEE = 0x00,
     REMOVE_CONTROLEE = 0x01,
     ADD_CONTROLEE_WITH_SHORT_SUB_SESSION_KEY = 0x02,
-    ADD_CONTROLEE_WITH_LONG_SUB_SESSION_KEY = 0x03,
+    ADD_CONTROLEE_WITH_EXTENDED_SUB_SESSION_KEY = 0x03,
 }
 
-packet SessionUpdateControllerMulticastListCmd : SessionConfigCommand (opcode = 0x7) { //SESSION_UPDATE_CONTROLLER_MULTICAST_LIST
+packet SessionUpdateControllerMulticastListCmd : SessionConfigPacket (mt = COMMAND, oid = UPDATE_CONTROLLER_MULTICAST_LIST) {
     session_token: 32, // Session ID or Session Handle (based on UWBS version)
     action: UpdateMulticastListAction,
     _payload_,
 }
 
-struct PhaseList {
-    session_token: 32,
-    start_slot_index: 16,
-    end_slot_index: 16,
-}
-
-packet SessionSetHybridConfigCmd : SessionConfigCommand (opcode = 0x0c) { //SESSION_SET_HUS_CONFIG
-    session_token: 32,
-    number_of_phases: 8,
-    update_time: 8[8],
-    phase_list: PhaseList[],
-}
-
-packet SessionSetHybridConfigRsp : SessionConfigResponse (opcode = 0x0c) { //SESSION_SET_HUS_CONFIG
-    status: StatusCode,
-}
-
 struct SessionUpdateControllerMulticastListCmdPayload {
     _count_(controlees): 8,
     controlees: Controlee[],
@@ -971,8 +1068,8 @@
     controlees: Controlee_V2_0_32_Byte_Version[],
 }
 
-packet SessionUpdateControllerMulticastListRsp : SessionConfigResponse (opcode = 0x7) { //SESSION_UPDATE_CONTROLLER_MULTICAST_LIST
-    status: StatusCode,
+packet SessionUpdateControllerMulticastListRsp : SessionConfigPacket (mt = RESPONSE, oid = UPDATE_CONTROLLER_MULTICAST_LIST) {
+    status: Status,
 }
 
 test SessionUpdateControllerMulticastListRsp {
@@ -981,13 +1078,11 @@
 
 struct ControleeStatus {
     mac_address: 8[2],
-    subsession_id: 32,
-    status: MulticastUpdateStatusCode,
+    status: MulticastUpdateStatus,
 }
 
-packet SessionUpdateControllerMulticastListNtf : SessionConfigNotification (opcode = 0x7) { //SESSION_UPDATE_CONTROLLER_MULTICAST_LIST
+packet SessionUpdateControllerMulticastListNtf : SessionConfigPacket (mt = NOTIFICATION, oid = UPDATE_CONTROLLER_MULTICAST_LIST) {
     session_token: 32, // Session ID or Session Handle (based on UWBS version)
-    remaining_multicast_list_size: 8,
     _count_(controlee_status): 8,
     controlee_status: ControleeStatus[],
 }
@@ -996,52 +1091,55 @@
     "\x61\x07\x00\x06\x00\x00\x00\x00\x01\x02\x03\x04\x00",
 }
 
-packet DataCreditNtf : SessionControlNotification (opcode = 0x04) { // SESSION_DATA_CREDIT_NTF
+// ---------------------- Session Control group ----------------------------- //
+
+packet SessionDataCreditNtf : SessionControlPacket (mt = NOTIFICATION, oid = DATA_CREDIT) {
     session_token: 32, // Session ID or Session Handle (based on UWBS version)
     credit_availability: CreditAvailability,
 }
 
-test DataCreditNtf {
+test SessionDataCreditNtf {
     "\x62\x04\x00\x05\x00\x00\x00\x00\x00\x00\x01\x01",
 }
 
-packet DataTransferStatusNtf : SessionControlNotification (opcode = 0x05) { // SESSION_DATA_TRANSFER_STATUS_NTF
+packet SessionDataTransferStatusNtf : SessionControlPacket (mt = NOTIFICATION, oid = DATA_TRANSFER_STATUS) {
     session_token: 32, // Session ID or Session Handle (based on UWBS version)
     uci_sequence_number: 8,
     status: DataTransferNtfStatusCode,
     tx_count: 8,
 }
 
-test DataTransferStatusNtf {
+test SessionDataTransferStatusNtf {
     "\x62\x05\x00\x06\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00",
 }
 
-packet SessionQueryMaxDataSizeCmd : SessionConfigCommand (opcode = 0xB) { //QUERY_MAX_DATA_SIZE
+packet SessionQueryMaxDataSizeInRangingCmd : SessionConfigPacket (mt = COMMAND, oid = QUERY_DATA_SIZE_IN_RANGING) {
     session_token: 32, // Session ID or Session Handle (based on UWBS version)
 }
 
-test SessionQueryMaxDataSizeCmd {
+test SessionQueryMaxDataSizeInRangingCmd {
  "\x21\x0B\x00\x04\x00\x00\x00\x00",
 }
 
-packet SessionQueryMaxDataSizeRsp : SessionConfigResponse (opcode = 0xB) { //QUER_MAX_DATA_SIZE
+packet SessionQueryMaxDataSizeInRangingRsp : SessionConfigPacket (mt = RESPONSE, oid = QUERY_DATA_SIZE_IN_RANGING) {
     session_token: 32, // Session ID or Session Handle (based on UWBS version)
     max_data_size: 16,
 }
 
-test SessionQueryMaxDataSizeRsp {
+test SessionQueryMaxDataSizeInRangingRsp {
   "\x41\x0B\x00\x06\x00\x00\x00\x00\x0E7\0x07",
 }
 
-packet SessionStartCmd : SessionControlCommand (opcode = 0x0) { //RANGE_START
+packet SessionStartCmd : SessionControlPacket (mt = COMMAND, oid = START) {
+    session_id: 32,
 }
 
 test SessionStartCmd {
     "\x22\x00\x00\x04\x00\x00\x00\x00\x01\x02\x03",
 }
 
-packet SessionStartRsp : SessionControlResponse (opcode = 0x0) { //RANGE_START
-    status: StatusCode,
+packet SessionStartRsp : SessionControlPacket (mt = RESPONSE, oid = START) {
+    status: Status,
 }
 
 test SessionStartRsp {
@@ -1050,7 +1148,7 @@
 
 struct ShortAddressTwoWayRangingMeasurement {
     mac_address: 16,
-    status: StatusCode,
+    status: Status,
     nlos: 8,
     distance: 16,
     aoa_azimuth: 16,
@@ -1072,7 +1170,7 @@
 
 struct ExtendedAddressTwoWayRangingMeasurement {
     mac_address: 64,
-    status: StatusCode,
+    status: Status,
     nlos: 8,
     distance: 16,
     aoa_azimuth: 16,
@@ -1090,7 +1188,7 @@
 
 struct ShortAddressOwrAoaRangingMeasurement {
     mac_address: 16,
-    status: StatusCode,
+    status: Status,
     nlos: 8,
     frame_sequence_number: 8,
     block_index: 16,
@@ -1102,7 +1200,7 @@
 
 struct ExtendedAddressOwrAoaRangingMeasurement {
     mac_address: 64,
-    status: StatusCode,
+    status: Status,
     nlos: 8,
     frame_sequence_number: 8,
     block_index: 16,
@@ -1119,7 +1217,7 @@
     OWR_AOA = 0x03,
 }
 
-packet SessionInfoNtf : SessionControlNotification (opcode = 0x0) { // SESSION_INFO
+packet SessionInfoNtf : SessionControlPacket (mt = NOTIFICATION, oid = START) {
     sequence_number: 32,
     session_token: 32, // Session ID or Session Handle (based on UWBS version)
     rcr_indicator: 8,
@@ -1191,30 +1289,32 @@
     "\x62\x00\x00\x2c\x00\x00\x00\x00\x02\x03\x04\x05\x06\x07\x08\x00\x0a\x01\x01\x01\x03\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xbb\xcc\xdd\x01\x02\x03\x04\x00\x00\x01\x01\x00\x03\x04\x60\x05\x06\x50",
 }
 
-packet SessionStopCmd : SessionControlCommand (opcode = 0x1) { // SESSION_STOP
+packet SessionStopCmd : SessionControlPacket (mt = COMMAND, oid = STOP) {
+    session_id: 32,
 }
 
 test SessionStopCmd {
     "\x22\x01\x00\x04\x00\x00\x00\x00\x02\x03\x04",
 }
 
-packet SessionStopRsp : SessionControlResponse (opcode = 0x1) { // SESSION_STOP
-    status: StatusCode,
+packet SessionStopRsp : SessionControlPacket (mt = RESPONSE, oid = STOP) {
+    status: Status,
 }
 
 test SessionStopRsp {
     "\x42\x01\x00\x01\x00\x00\x00\x00",
 }
 
-packet SessionGetRangingCountCmd : SessionControlCommand (opcode = 0x3) { // SESSION_GET_RANGING_COUNT
+packet SessionGetRangingCountCmd : SessionControlPacket (mt = COMMAND, oid = GET_RANGING_COUNT) {
+    session_id: 32,
 }
 
 test SessionGetRangingCountCmd {
     "\x22\x03\x00\x04\x00\x00\x00\x00\x02\x03\x04",
 }
 
-packet SessionGetRangingCountRsp : SessionControlResponse (opcode = 0x3) { // SESSION_GET_RANGING_COUNT
-    status: StatusCode,
+packet SessionGetRangingCountRsp : SessionControlPacket (mt = RESPONSE, oid = GET_RANGING_COUNT) {
+    status: Status,
     count: 32,
 }
 
@@ -1222,7 +1322,9 @@
     "\x42\x03\x00\x05\x00\x00\x00\x00\x02\x03\x04\x05",
 }
 
-packet AndroidGetPowerStatsCmd: AndroidCommand (opcode = 0x0) { //ANDROID_GET_POWER_STATS
+// -------------------------- Android group --------------------------------- //
+
+packet AndroidGetPowerStatsCmd : AndroidPacket (mt = COMMAND, oid = GET_POWER_STATS) {
 }
 
 test AndroidGetPowerStatsCmd {
@@ -1230,14 +1332,14 @@
 }
 
 struct PowerStats {
-    status: StatusCode,
+    status: Status,
     idle_time_ms: 32,
     tx_time_ms: 32,
     rx_time_ms: 32,
     total_wake_count:32,
 }
 
-packet AndroidGetPowerStatsRsp : AndroidResponse (opcode = 0x0) { //ANDROID_GET_POWER_STATS
+packet AndroidGetPowerStatsRsp : AndroidPacket (mt = RESPONSE, oid = GET_POWER_STATS) {
     stats: PowerStats,
 }
 
@@ -1245,7 +1347,7 @@
     "\x4c\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
 }
 
-packet AndroidSetCountryCodeCmd: AndroidCommand (opcode = 0x1) { //ANDROID_SET_COUNTRY_CODE
+packet AndroidSetCountryCodeCmd: AndroidPacket (mt = COMMAND, oid = SET_COUNTRY_CODE) {
     country_code : 8[2],
 }
 
@@ -1254,14 +1356,20 @@
     "\x2c\x01\x00\x02\x00\x00\x00\x55\x53",
 }
 
-packet AndroidSetCountryCodeRsp : AndroidResponse (opcode = 0x1) { //ANDROID_SET_COUNTRY_CODE
-    status: StatusCode,
+packet AndroidSetCountryCodeRsp : AndroidPacket (mt = RESPONSE, oid = SET_COUNTRY_CODE) {
+    status: Status,
 }
 
 test AndroidSetCountryCodeRsp {
     "\x4c\x01\x00\x01\x00\x00\x00\x00",
 }
 
+enum FrameReportTlvType : 8 {
+    RSSI = 0x0,
+    AOA = 0x1,
+    CIR = 0x2,
+}
+
 struct FrameReportTlv {
     t: FrameReportTlvType,
     _size_(v): 16,
@@ -1324,7 +1432,7 @@
     frame_report_tlvs: FrameReportTlv[],
 }
 
-packet AndroidRangeDiagnosticsNtf : AndroidNotification (opcode = 0x2) { //FIRA_RANGE_DIAGNOSTICS
+packet AndroidRangeDiagnosticsNtf : AndroidPacket (mt = NOTIFICATION, oid = FIRA_RANGE_DIAGNOSTICS) {
     session_token: 32, // Session ID or Session Handle (based on UWBS version)
     sequence_number: 32,
     _count_(frame_reports): 8,
@@ -1335,67 +1443,3 @@
     "\x6c\x02\x00\x11\x00\x00\x00\x01\x01\x01\x01\x02\x02\x02\x02\x01\x00\x01\x02\x01\x00\x01\x00\x00",
     "\x6c\x02\x00\x34\x00\x00\x00\x01\x01\x01\x01\x02\x02\x02\x02\x01\x00\x01\x02\x03\x01\x08\x00\x01\x02\x01\x02\x01\x02\x01\x01\x02\x15\x00\x01\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x00\x02\x04\x00\x01\x02\x03\x04\x00\x01\x00\x00",
 }
-
-packet UciVendor_9_Command : UciCommand (gid = VENDOR_RESERVED_9) {
-    _payload_,
-}
-
-packet UciVendor_A_Command : UciCommand (gid = VENDOR_RESERVED_A) {
-    _payload_,
-}
-
-packet UciVendor_B_Command : UciCommand (gid = VENDOR_RESERVED_B) {
-    _payload_,
-}
-
-packet UciVendor_E_Command : UciCommand (gid = VENDOR_RESERVED_E) {
-    _payload_,
-}
-
-packet UciVendor_F_Command : UciCommand (gid = VENDOR_RESERVED_F) {
-    _payload_,
-}
-
-packet UciVendor_9_Response : UciResponse (gid = VENDOR_RESERVED_9) {
-    _payload_,
-}
-
-packet UciVendor_A_Response : UciResponse (gid = VENDOR_RESERVED_A) {
-    _payload_,
-}
-
-packet UciVendor_B_Response : UciResponse (gid = VENDOR_RESERVED_B) {
-    _payload_,
-}
-
-packet UciVendor_E_Response : UciResponse (gid = VENDOR_RESERVED_E) {
-    _payload_,
-}
-
-packet UciVendor_F_Response : UciResponse (gid = VENDOR_RESERVED_F) {
-    _payload_,
-}
-
-packet UciVendor_9_Notification : UciNotification (gid = VENDOR_RESERVED_9) {
-    _payload_,
-}
-
-packet UciVendor_A_Notification : UciNotification (gid = VENDOR_RESERVED_A) {
-    _payload_,
-}
-
-packet UciVendor_B_Notification : UciNotification (gid = VENDOR_RESERVED_B) {
-    _payload_,
-}
-
-packet UciVendor_E_Notification : UciNotification (gid = VENDOR_RESERVED_E) {
-    _payload_,
-}
-
-packet UciVendor_F_Notification : UciNotification (gid = VENDOR_RESERVED_F) {
-    _payload_,
-}
-
-packet TestNotification : UciNotification (gid = TEST) {
-    _payload_,
-}
\ No newline at end of file
diff --git a/tests/data_transfer.py b/tests/data_transfer.py
index 241a6b9..6d4fb8c 100755
--- a/tests/data_transfer.py
+++ b/tests/data_transfer.py
@@ -35,7 +35,7 @@
         )
     )
 
-    await host.expect_control(uci.SessionInitRsp(status=uci.StatusCode.UCI_STATUS_OK))
+    await host.expect_control(uci.SessionInitRsp(status=uci.Status.OK))
 
     await host.expect_control(
         uci.SessionStatusNtf(
@@ -45,32 +45,45 @@
         )
     )
 
-    mac_address_mode = 0x0
+    ranging_round_usage = 0x06
     ranging_duration = int(1000).to_bytes(4, byteorder="little")
-    device_role_initiator = bytes([0])
-    device_type_controller = bytes([1])
+
     host.send_control(
         uci.SessionSetAppConfigCmd(
             session_token=0,
             tlvs=[
                 uci.AppConfigTlv(
-                    cfg_id=uci.AppConfigTlvType.DEVICE_ROLE, v=device_role_initiator
+                    cfg_id=uci.AppConfigTlvType.DEVICE_ROLE,
+                    v=bytes([uci.DeviceRole.INITIATOR]),
                 ),
                 uci.AppConfigTlv(
-                    cfg_id=uci.AppConfigTlvType.DEVICE_TYPE, v=device_type_controller
+                    cfg_id=uci.AppConfigTlvType.DEVICE_TYPE,
+                    v=bytes([uci.DeviceType.CONTROLLER]),
                 ),
                 uci.AppConfigTlv(
                     cfg_id=uci.AppConfigTlvType.DEVICE_MAC_ADDRESS, v=host.mac_address
                 ),
                 uci.AppConfigTlv(
                     cfg_id=uci.AppConfigTlvType.MAC_ADDRESS_MODE,
-                    v=bytes([mac_address_mode]),
+                    v=bytes([uci.MacAddressMode.MODE_0]),
+                ),
+                uci.AppConfigTlv(
+                    cfg_id=uci.AppConfigTlvType.MULTI_NODE_MODE,
+                    v=bytes([uci.MultiNodeMode.ONE_TO_ONE]),
+                ),
+                uci.AppConfigTlv(
+                    cfg_id=uci.AppConfigTlvType.SCHEDULE_MODE,
+                    v=bytes([uci.ScheduleMode.CONTENTION_BASED]),
+                ),
+                uci.AppConfigTlv(
+                    cfg_id=uci.AppConfigTlvType.RANGING_ROUND_USAGE,
+                    v=bytes([ranging_round_usage]),
                 ),
                 uci.AppConfigTlv(
                     cfg_id=uci.AppConfigTlvType.RANGING_DURATION, v=ranging_duration
                 ),
                 uci.AppConfigTlv(
-                    cfg_id=uci.AppConfigTlvType.NO_OF_CONTROLEE, v=bytes([1])
+                    cfg_id=uci.AppConfigTlvType.NUMBER_OF_CONTROLEES, v=bytes([1])
                 ),
                 uci.AppConfigTlv(
                     cfg_id=uci.AppConfigTlvType.DST_MAC_ADDRESS, v=peer.mac_address
@@ -80,7 +93,7 @@
     )
 
     await host.expect_control(
-        uci.SessionSetAppConfigRsp(status=uci.StatusCode.UCI_STATUS_OK, cfg_status=[])
+        uci.SessionSetAppConfigRsp(status=uci.Status.OK, cfg_status=[])
     )
 
     await host.expect_control(
@@ -96,7 +109,7 @@
     # START SESSION CMD
     host.send_control(uci.SessionStartCmd(session_id=0))
 
-    await host.expect_control(uci.SessionStartRsp(status=uci.StatusCode.UCI_STATUS_OK))
+    await host.expect_control(uci.SessionStartRsp(status=uci.Status.OK))
 
     await host.expect_control(
         uci.SessionStatusNtf(
@@ -107,7 +120,7 @@
     )
 
     await host.expect_control(
-        uci.DeviceStatusNtf(device_state=uci.DeviceState.DEVICE_STATE_ACTIVE)
+        uci.CoreDeviceStatusNtf(device_state=uci.DeviceState.DEVICE_STATE_ACTIVE)
     )
 
     event = await host.expect_control(uci.ShortMacTwoWaySessionInfoNtf, timeout=2.0)
@@ -119,7 +132,7 @@
     # STOP SESSION
     host.send_control(uci.SessionStopCmd(session_id=0))
 
-    await host.expect_control(uci.SessionStopRsp(status=uci.StatusCode.UCI_STATUS_OK))
+    await host.expect_control(uci.SessionStopRsp(status=uci.Status.OK))
 
     await host.expect_control(
         uci.SessionStatusNtf(
@@ -130,13 +143,13 @@
     )
 
     await host.expect_control(
-        uci.DeviceStatusNtf(device_state=uci.DeviceState.DEVICE_STATE_READY)
+        uci.CoreDeviceStatusNtf(device_state=uci.DeviceState.DEVICE_STATE_READY)
     )
 
     # DEINIT
     host.send_control(uci.SessionDeinitCmd(session_token=0))
 
-    await host.expect_control(uci.SessionDeinitRsp(status=uci.StatusCode.UCI_STATUS_OK))
+    await host.expect_control(uci.SessionDeinitRsp(status=uci.Status.OK))
 
 
 async def controlee(host: Host, peer: Host, file: Path):
@@ -149,7 +162,7 @@
         )
     )
 
-    await host.expect_control(uci.SessionInitRsp(status=uci.StatusCode.UCI_STATUS_OK))
+    await host.expect_control(uci.SessionInitRsp(status=uci.Status.OK))
 
     await host.expect_control(
         uci.SessionStatusNtf(
@@ -159,32 +172,45 @@
         )
     )
 
-    mac_address_mode = 0x0
+    ranging_round_usage = 0x06
     ranging_duration = int(1000).to_bytes(4, byteorder="little")
-    device_role_responder = bytes([1])
-    device_type_controllee = bytes([0])
+
     host.send_control(
         uci.SessionSetAppConfigCmd(
             session_token=0,
             tlvs=[
                 uci.AppConfigTlv(
-                    cfg_id=uci.AppConfigTlvType.DEVICE_ROLE, v=device_role_responder
+                    cfg_id=uci.AppConfigTlvType.DEVICE_ROLE,
+                    v=bytes([uci.DeviceRole.RESPONDER]),
                 ),
                 uci.AppConfigTlv(
-                    cfg_id=uci.AppConfigTlvType.DEVICE_TYPE, v=device_type_controllee
+                    cfg_id=uci.AppConfigTlvType.DEVICE_TYPE,
+                    v=bytes([uci.DeviceType.CONTROLEE]),
                 ),
                 uci.AppConfigTlv(
                     cfg_id=uci.AppConfigTlvType.DEVICE_MAC_ADDRESS, v=host.mac_address
                 ),
                 uci.AppConfigTlv(
                     cfg_id=uci.AppConfigTlvType.MAC_ADDRESS_MODE,
-                    v=bytes([mac_address_mode]),
+                    v=bytes([uci.MacAddressMode.MODE_0]),
+                ),
+                uci.AppConfigTlv(
+                    cfg_id=uci.AppConfigTlvType.MULTI_NODE_MODE,
+                    v=bytes([uci.MultiNodeMode.ONE_TO_ONE]),
+                ),
+                uci.AppConfigTlv(
+                    cfg_id=uci.AppConfigTlvType.SCHEDULE_MODE,
+                    v=bytes([uci.ScheduleMode.CONTENTION_BASED]),
+                ),
+                uci.AppConfigTlv(
+                    cfg_id=uci.AppConfigTlvType.RANGING_ROUND_USAGE,
+                    v=bytes([ranging_round_usage]),
                 ),
                 uci.AppConfigTlv(
                     cfg_id=uci.AppConfigTlvType.RANGING_DURATION, v=ranging_duration
                 ),
                 uci.AppConfigTlv(
-                    cfg_id=uci.AppConfigTlvType.NO_OF_CONTROLEE, v=bytes([1])
+                    cfg_id=uci.AppConfigTlvType.NUMBER_OF_CONTROLEES, v=bytes([1])
                 ),
                 uci.AppConfigTlv(
                     cfg_id=uci.AppConfigTlvType.DST_MAC_ADDRESS, v=peer.mac_address
@@ -194,7 +220,7 @@
     )
 
     await host.expect_control(
-        uci.SessionSetAppConfigRsp(status=uci.StatusCode.UCI_STATUS_OK, cfg_status=[])
+        uci.SessionSetAppConfigRsp(status=uci.Status.OK, cfg_status=[])
     )
 
     await host.expect_control(
@@ -207,7 +233,7 @@
 
     host.send_control(uci.SessionStartCmd(session_id=0))
 
-    await host.expect_control(uci.SessionStartRsp(status=uci.StatusCode.UCI_STATUS_OK))
+    await host.expect_control(uci.SessionStartRsp(status=uci.Status.OK))
 
     await host.expect_control(
         uci.SessionStatusNtf(
@@ -218,7 +244,7 @@
     )
 
     await host.expect_control(
-        uci.DeviceStatusNtf(device_state=uci.DeviceState.DEVICE_STATE_ACTIVE)
+        uci.CoreDeviceStatusNtf(device_state=uci.DeviceState.DEVICE_STATE_ACTIVE)
     )
 
     with file.open("rb") as f:
@@ -226,8 +252,8 @@
         event = await host.expect_data(
             uci.DataMessageRcv(
                 session_handle=0,
-                status=uci.StatusCode.UCI_STATUS_OK,
-                source_address=int.from_bytes(peer.mac_address, "big"),
+                status=uci.Status.OK,
+                source_address=int.from_bytes(peer.mac_address, "little"),
                 data_sequence_number=0x01,
                 application_data=application_data,
             ),
@@ -240,7 +266,7 @@
 
     host.send_control(uci.SessionStopCmd(session_id=0))
 
-    await host.expect_control(uci.SessionStopRsp(status=uci.StatusCode.UCI_STATUS_OK))
+    await host.expect_control(uci.SessionStopRsp(status=uci.Status.OK))
 
     await host.expect_control(
         uci.SessionStatusNtf(
@@ -251,12 +277,12 @@
     )
 
     await host.expect_control(
-        uci.DeviceStatusNtf(device_state=uci.DeviceState.DEVICE_STATE_READY)
+        uci.CoreDeviceStatusNtf(device_state=uci.DeviceState.DEVICE_STATE_READY)
     )
 
     host.send_control(uci.SessionDeinitCmd(session_token=0))
 
-    await host.expect_control(uci.SessionDeinitRsp(status=uci.StatusCode.UCI_STATUS_OK))
+    await host.expect_control(uci.SessionDeinitRsp(status=uci.Status.OK))
 
 
 async def data_transfer(
@@ -296,7 +322,7 @@
                         seq_num = 0
 
                     event = await host.expect_control(
-                        uci.DataCreditNtf(
+                        uci.SessionDataCreditNtf(
                             session_token=int(session_id),
                             credit_availability=uci.CreditAvailability.CREDIT_AVAILABLE,
                         )
@@ -312,7 +338,7 @@
                     )
                 )
                 event = await host.expect_control(
-                    uci.DataCreditNtf(
+                    uci.SessionDataCreditNtf(
                         session_token=int(session_id),
                         credit_availability=uci.CreditAvailability.CREDIT_AVAILABLE,
                     )
@@ -325,8 +351,8 @@
 
 async def run(address: str, uci_port: int, file: Path):
     try:
-        host0 = await Host.connect(address, uci_port, bytes([0, 0]))
-        host1 = await Host.connect(address, uci_port, bytes([0, 1]))
+        host0 = await Host.connect(address, uci_port, bytes([0x34, 0x12]))
+        host1 = await Host.connect(address, uci_port, bytes([0x78, 0x56]))
     except Exception as e:
         raise Exception(
             f"Failed to connect to Pica server at address {address}:{uci_port}\n"
diff --git a/tests/helper.py b/tests/helper.py
index bbce7ad..f5d9db5 100644
--- a/tests/helper.py
+++ b/tests/helper.py
@@ -18,13 +18,13 @@
 
 async def init(host: Host):
     await host.expect_control(
-        uci.DeviceStatusNtf(device_state=uci.DeviceState.DEVICE_STATE_READY)
+        uci.CoreDeviceStatusNtf(device_state=uci.DeviceState.DEVICE_STATE_READY)
     )
 
-    host.send_control(uci.DeviceResetCmd(reset_config=uci.ResetConfig.UWBS_RESET))
+    host.send_control(uci.CoreDeviceResetCmd(reset_config=uci.ResetConfig.UWBS_RESET))
 
-    await host.expect_control(uci.DeviceResetRsp(status=uci.StatusCode.UCI_STATUS_OK))
+    await host.expect_control(uci.CoreDeviceResetRsp(status=uci.Status.OK))
 
     await host.expect_control(
-        uci.DeviceStatusNtf(device_state=uci.DeviceState.DEVICE_STATE_READY)
+        uci.CoreDeviceStatusNtf(device_state=uci.DeviceState.DEVICE_STATE_READY)
     )
diff --git a/tests/ranging.py b/tests/ranging.py
index 7af8224..165c5e3 100755
--- a/tests/ranging.py
+++ b/tests/ranging.py
@@ -32,7 +32,7 @@
         )
     )
 
-    await host.expect_control(uci.SessionInitRsp(status=uci.StatusCode.UCI_STATUS_OK))
+    await host.expect_control(uci.SessionInitRsp(status=uci.Status.OK))
 
     await host.expect_control(
         uci.SessionStatusNtf(
@@ -42,32 +42,45 @@
         )
     )
 
-    mac_address_mode = 0x0
+    ranging_round_usage = 0x06
     ranging_duration = int(1000).to_bytes(4, byteorder="little")
-    device_role_initiator = bytes([0])
-    device_type_controller = bytes([1])
+
     host.send_control(
         uci.SessionSetAppConfigCmd(
             session_token=0,
             tlvs=[
                 uci.AppConfigTlv(
-                    cfg_id=uci.AppConfigTlvType.DEVICE_ROLE, v=device_role_initiator
+                    cfg_id=uci.AppConfigTlvType.DEVICE_ROLE,
+                    v=bytes([uci.DeviceRole.INITIATOR]),
                 ),
                 uci.AppConfigTlv(
-                    cfg_id=uci.AppConfigTlvType.DEVICE_TYPE, v=device_type_controller
+                    cfg_id=uci.AppConfigTlvType.DEVICE_TYPE,
+                    v=bytes([uci.DeviceType.CONTROLLER]),
                 ),
                 uci.AppConfigTlv(
                     cfg_id=uci.AppConfigTlvType.DEVICE_MAC_ADDRESS, v=host.mac_address
                 ),
                 uci.AppConfigTlv(
                     cfg_id=uci.AppConfigTlvType.MAC_ADDRESS_MODE,
-                    v=bytes([mac_address_mode]),
+                    v=bytes([uci.MacAddressMode.MODE_0]),
+                ),
+                uci.AppConfigTlv(
+                    cfg_id=uci.AppConfigTlvType.MULTI_NODE_MODE,
+                    v=bytes([uci.MultiNodeMode.ONE_TO_ONE]),
+                ),
+                uci.AppConfigTlv(
+                    cfg_id=uci.AppConfigTlvType.SCHEDULE_MODE,
+                    v=bytes([uci.ScheduleMode.CONTENTION_BASED]),
+                ),
+                uci.AppConfigTlv(
+                    cfg_id=uci.AppConfigTlvType.RANGING_ROUND_USAGE,
+                    v=bytes([ranging_round_usage]),
                 ),
                 uci.AppConfigTlv(
                     cfg_id=uci.AppConfigTlvType.RANGING_DURATION, v=ranging_duration
                 ),
                 uci.AppConfigTlv(
-                    cfg_id=uci.AppConfigTlvType.NO_OF_CONTROLEE, v=bytes([1])
+                    cfg_id=uci.AppConfigTlvType.NUMBER_OF_CONTROLEES, v=bytes([1])
                 ),
                 uci.AppConfigTlv(
                     cfg_id=uci.AppConfigTlvType.DST_MAC_ADDRESS, v=peer.mac_address
@@ -77,7 +90,7 @@
     )
 
     await host.expect_control(
-        uci.SessionSetAppConfigRsp(status=uci.StatusCode.UCI_STATUS_OK, cfg_status=[])
+        uci.SessionSetAppConfigRsp(status=uci.Status.OK, cfg_status=[])
     )
 
     await host.expect_control(
@@ -90,7 +103,7 @@
 
     host.send_control(uci.SessionStartCmd(session_id=0))
 
-    await host.expect_control(uci.SessionStartRsp(status=uci.StatusCode.UCI_STATUS_OK))
+    await host.expect_control(uci.SessionStartRsp(status=uci.Status.OK))
 
     await host.expect_control(
         uci.SessionStatusNtf(
@@ -101,7 +114,7 @@
     )
 
     await host.expect_control(
-        uci.DeviceStatusNtf(device_state=uci.DeviceState.DEVICE_STATE_ACTIVE)
+        uci.CoreDeviceStatusNtf(device_state=uci.DeviceState.DEVICE_STATE_ACTIVE)
     )
 
     for _ in range(1, 3):
@@ -110,7 +123,7 @@
 
     host.send_control(uci.SessionStopCmd(session_id=0))
 
-    await host.expect_control(uci.SessionStopRsp(status=uci.StatusCode.UCI_STATUS_OK))
+    await host.expect_control(uci.SessionStopRsp(status=uci.Status.OK))
 
     await host.expect_control(
         uci.SessionStatusNtf(
@@ -121,12 +134,12 @@
     )
 
     await host.expect_control(
-        uci.DeviceStatusNtf(device_state=uci.DeviceState.DEVICE_STATE_READY)
+        uci.CoreDeviceStatusNtf(device_state=uci.DeviceState.DEVICE_STATE_READY)
     )
 
     host.send_control(uci.SessionDeinitCmd(session_token=0))
 
-    await host.expect_control(uci.SessionDeinitRsp(status=uci.StatusCode.UCI_STATUS_OK))
+    await host.expect_control(uci.SessionDeinitRsp(status=uci.Status.OK))
 
 
 async def controlee(host: Host, peer: Host):
@@ -138,7 +151,7 @@
         )
     )
 
-    await host.expect_control(uci.SessionInitRsp(status=uci.StatusCode.UCI_STATUS_OK))
+    await host.expect_control(uci.SessionInitRsp(status=uci.Status.OK))
 
     await host.expect_control(
         uci.SessionStatusNtf(
@@ -148,32 +161,45 @@
         )
     )
 
-    mac_address_mode = 0x0
+    ranging_round_usage = 0x06
     ranging_duration = int(1000).to_bytes(4, byteorder="little")
-    device_role_responder = bytes([1])
-    device_type_controlee = bytes([0])
+
     host.send_control(
         uci.SessionSetAppConfigCmd(
             session_token=0,
             tlvs=[
                 uci.AppConfigTlv(
-                    cfg_id=uci.AppConfigTlvType.DEVICE_ROLE, v=device_role_responder
+                    cfg_id=uci.AppConfigTlvType.DEVICE_ROLE,
+                    v=bytes([uci.DeviceRole.RESPONDER]),
                 ),
                 uci.AppConfigTlv(
-                    cfg_id=uci.AppConfigTlvType.DEVICE_TYPE, v=device_type_controlee
+                    cfg_id=uci.AppConfigTlvType.DEVICE_TYPE,
+                    v=bytes([uci.DeviceType.CONTROLEE]),
                 ),
                 uci.AppConfigTlv(
                     cfg_id=uci.AppConfigTlvType.DEVICE_MAC_ADDRESS, v=host.mac_address
                 ),
                 uci.AppConfigTlv(
                     cfg_id=uci.AppConfigTlvType.MAC_ADDRESS_MODE,
-                    v=bytes([mac_address_mode]),
+                    v=bytes([uci.MacAddressMode.MODE_0]),
+                ),
+                uci.AppConfigTlv(
+                    cfg_id=uci.AppConfigTlvType.MULTI_NODE_MODE,
+                    v=bytes([uci.MultiNodeMode.ONE_TO_ONE]),
+                ),
+                uci.AppConfigTlv(
+                    cfg_id=uci.AppConfigTlvType.SCHEDULE_MODE,
+                    v=bytes([uci.ScheduleMode.CONTENTION_BASED]),
+                ),
+                uci.AppConfigTlv(
+                    cfg_id=uci.AppConfigTlvType.RANGING_ROUND_USAGE,
+                    v=bytes([ranging_round_usage]),
                 ),
                 uci.AppConfigTlv(
                     cfg_id=uci.AppConfigTlvType.RANGING_DURATION, v=ranging_duration
                 ),
                 uci.AppConfigTlv(
-                    cfg_id=uci.AppConfigTlvType.NO_OF_CONTROLEE, v=bytes([1])
+                    cfg_id=uci.AppConfigTlvType.NUMBER_OF_CONTROLEES, v=bytes([1])
                 ),
                 uci.AppConfigTlv(
                     cfg_id=uci.AppConfigTlvType.DST_MAC_ADDRESS, v=peer.mac_address
@@ -183,7 +209,7 @@
     )
 
     await host.expect_control(
-        uci.SessionSetAppConfigRsp(status=uci.StatusCode.UCI_STATUS_OK, cfg_status=[])
+        uci.SessionSetAppConfigRsp(status=uci.Status.OK, cfg_status=[])
     )
 
     await host.expect_control(
@@ -196,7 +222,7 @@
 
     host.send_control(uci.SessionStartCmd(session_id=0))
 
-    await host.expect_control(uci.SessionStartRsp(status=uci.StatusCode.UCI_STATUS_OK))
+    await host.expect_control(uci.SessionStartRsp(status=uci.Status.OK))
 
     await host.expect_control(
         uci.SessionStatusNtf(
@@ -207,7 +233,7 @@
     )
 
     await host.expect_control(
-        uci.DeviceStatusNtf(device_state=uci.DeviceState.DEVICE_STATE_ACTIVE)
+        uci.CoreDeviceStatusNtf(device_state=uci.DeviceState.DEVICE_STATE_ACTIVE)
     )
 
     for _ in range(1, 3):
@@ -216,7 +242,7 @@
 
     host.send_control(uci.SessionStopCmd(session_id=0))
 
-    await host.expect_control(uci.SessionStopRsp(status=uci.StatusCode.UCI_STATUS_OK))
+    await host.expect_control(uci.SessionStopRsp(status=uci.Status.OK))
 
     await host.expect_control(
         uci.SessionStatusNtf(
@@ -227,12 +253,12 @@
     )
 
     await host.expect_control(
-        uci.DeviceStatusNtf(device_state=uci.DeviceState.DEVICE_STATE_READY)
+        uci.CoreDeviceStatusNtf(device_state=uci.DeviceState.DEVICE_STATE_READY)
     )
 
     host.send_control(uci.SessionDeinitCmd(session_token=0))
 
-    await host.expect_control(uci.SessionDeinitRsp(status=uci.StatusCode.UCI_STATUS_OK))
+    await host.expect_control(uci.SessionDeinitRsp(status=uci.Status.OK))
 
 
 async def run(address: str, uci_port: int):