""" IEEE 1394 Data decoders for Chapter 10 data types Supports IEEE 1394 Formats 0-1 (0x58-0x59) """ import struct from typing import Dict, Any, Optional from .base import DataTypeDecoder, DecodedPayload class IEEE1394Decoder(DataTypeDecoder): """Decoder for IEEE 1394 Data types (0x58-0x59)""" def __init__(self): super().__init__() self.data_type_base = 0x58 self.data_type_name = "IEEE 1394 Data" self.supported_formats = [0x58, 0x59] def can_decode(self, data_type: int) -> bool: return data_type in [0x58, 0x59] def get_data_type_name(self, data_type: int) -> str: format_names = { 0x58: "IEEE 1394 Transaction", 0x59: "IEEE 1394 Physical Layer" } return format_names.get(data_type, f"IEEE 1394 Format {data_type & 0x0F}") def decode(self, payload: bytes, ch10_header: Dict[str, Any]) -> Optional[DecodedPayload]: """Decode IEEE 1394 payload""" data_type = ch10_header.get('data_type', 0) if not self.can_decode(data_type): return None if data_type == 0x58: return self._decode_transaction(payload, ch10_header) elif data_type == 0x59: return self._decode_physical_layer(payload, ch10_header) return None def _decode_transaction(self, payload: bytes, ch10_header: Dict[str, Any]) -> DecodedPayload: """Decode IEEE 1394 Transaction data""" decoded_data = {} errors = [] # Parse IPH iph = self._parse_intra_packet_header(payload) if iph: decoded_data.update(iph) data_start = iph['data_start'] else: data_start = 0 errors.append("Failed to parse intra-packet header") # Parse 1394 transaction header if data_start + 16 <= len(payload): tx_header = self._safe_unpack('> 16) & 0xFFFF, 'destination_offset': tx_header[2], 'data_length': tx_header[3] }) # Decode transaction code tx_codes = { 0: "Write Request", 1: "Write Response", 4: "Read Request", 5: "Read Response", 6: "Lock Request", 7: "Lock Response" } decoded_data['transaction_type'] = tx_codes.get( decoded_data['transaction_code'], f"Unknown ({decoded_data['transaction_code']})" ) # Extract transaction data tx_data_start = data_start + 16 tx_data_length = decoded_data['data_length'] if tx_data_start + tx_data_length <= len(payload): tx_data = payload[tx_data_start:tx_data_start + tx_data_length] decoded_data['transaction_data'] = tx_data[:64].hex() else: errors.append("Failed to parse 1394 transaction header") return DecodedPayload( data_type=0x58, data_type_name="IEEE 1394 Transaction", format_version=0, decoded_data=decoded_data, raw_payload=payload, errors=errors, metadata={'decoder': 'IEEE1394Decoder'} ) def _decode_physical_layer(self, payload: bytes, ch10_header: Dict[str, Any]) -> DecodedPayload: """Decode IEEE 1394 Physical Layer data""" decoded_data = {} errors = [] # Parse IPH iph = self._parse_intra_packet_header(payload) if iph: decoded_data.update(iph) data_start = iph['data_start'] else: data_start = 0 errors.append("Failed to parse intra-packet header") # Parse physical layer data if data_start < len(payload): phy_data = payload[data_start:] decoded_data['phy_data_length'] = len(phy_data) decoded_data['phy_data_hex'] = phy_data[:64].hex() # Basic PHY packet analysis if len(phy_data) >= 4: phy_header = struct.unpack('> 28) & 0x0F decoded_data['phy_speed'] = (phy_header >> 26) & 0x03 speed_names = {0: "100 Mbps", 1: "200 Mbps", 2: "400 Mbps", 3: "Reserved"} decoded_data['phy_speed_description'] = speed_names.get( decoded_data['phy_speed'], "Unknown" ) return DecodedPayload( data_type=0x59, data_type_name="IEEE 1394 Physical Layer", format_version=1, decoded_data=decoded_data, raw_payload=payload, errors=errors, metadata={'decoder': 'IEEE1394Decoder'} )