pretty good
This commit is contained in:
142
analyzer/protocols/decoders/ieee1394.py
Normal file
142
analyzer/protocols/decoders/ieee1394.py
Normal file
@@ -0,0 +1,142 @@
|
||||
"""
|
||||
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('<IIII', payload, data_start)
|
||||
if tx_header:
|
||||
decoded_data.update({
|
||||
'transaction_timestamp': tx_header[0],
|
||||
'transaction_code': tx_header[1] & 0x0F,
|
||||
'source_id': (tx_header[1] >> 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('<I', phy_data[:4])[0]
|
||||
decoded_data['phy_packet_type'] = (phy_header >> 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'}
|
||||
)
|
||||
Reference in New Issue
Block a user