Ich hatte auch nicht versprochen, dass es einfach wird. Hast du denn mal in meine PHP-Funktionen zum SDS dekodieren geschaut? Ich habe mir soviel Mühe gegeben, ordentliche Kommentare im Code zu hinterlassen.

// decode_PDU
// liefert ein Array mit decodierten Protokoll-Feldern eines übergebenen hexadezimalen User-Daten-Teils einer TETRA-SDS (SDS-PDU)
// ETSI EN 300 392-2 V3.4.1
// 29.4.1 PDU general structure (Table 29.10: PDU layout)
// 29.4.3.9 Protocol identifier (Table 29.21: Protocol identifier information element contents)
function decode_PDU ($PDU)
{
$ret=array();
$PDUbin=hextobin($PDU); // Hex-String in Binär-String wandeln
// Protocol Identifyer 8 Bit [0-255]
$ret["StringPos"]=0;
$SubStrLen=8;
$ret["ProtoIdent"] = array();
$ret["ProtoIdent"]["value"] = bindec(substr("$PDUbin",$ret["StringPos"],$SubStrLen));
$ret["StringPos"]+=$SubStrLen;
switch($ret["ProtoIdent"]["value"])
{
case 1: // Over The Air re-Keying for end to end encryption
$ret["ProtoIdent"]["name"] = "OTAK";
break;
case 2: // Simple Text Messaging
$ret["ProtoIdent"]["name"] = "Simple Text Messaging";
break;
case 3: // Simple location system
$ret["ProtoIdent"]["name"] = "Simple location system";
break;
case 4: // Wireless Datagram Protocol WAP
$ret["ProtoIdent"]["name"] = "Wireless Datagram Protocol WAP";
break;
case 5: // Wireless Control Message Protocol WCMP
$ret["ProtoIdent"]["name"] = "Wireless Control Message Protocol WCMP";
break;
case 6: // Managed DMO
$ret["ProtoIdent"]["name"] = "Managed DMO";
break;
case 7: // PIN authentication
$ret["ProtoIdent"]["name"] = "PIN authentication";
break;
case 8: // End-to-end encrypted message
$ret["ProtoIdent"]["name"] = "End-to-end encrypted message";
break;
case 9: // Simple immediate text messaging
$ret["ProtoIdent"]["name"] = "Simple immediate text messaging";
break;
case 10: // Location information protocol
$ret["ProtoIdent"]["name"] = "Location Information Protocol";
foreach(get_LipPDU($PDUbin,$ret["StringPos"]) as $key => $value) { $ret[$key] = $value; }
break;
case 11: // Net Assist Protocol (NAP)
$ret["ProtoIdent"]["name"] = "Net Assist Protocol (NAP)";
break;
case 12: // Concatenated SDS message
$ret["ProtoIdent"]["name"] = "Concatenated SDS message";
break;
case 13: // DOTAM
$ret["ProtoIdent"]["name"] = "DOTAM";
break;
case 130: // Text Messaging
$ret["ProtoIdent"]["name"] = "Text Messaging";
foreach(get_TextPDU($PDUbin,$ret["StringPos"]) as $key => $value) { $ret[$key] = $value; }
break;
case 131: // Location system
$ret["ProtoIdent"]["name"] = "Location system";
break;
case 132: // Wireless Datagram Protocol WAP
$ret["ProtoIdent"]["name"] = "Wireless Datagram Protocol WAP";
break;
case 133: // Wireless Control Message Protocol WCMP
$ret["ProtoIdent"]["name"] = "Wireless Control Message Protocol WCMP";
break;
case 134: // Managed DMO
$ret["ProtoIdent"]["name"] = "Managed DMO";
break;
case 136: // End-to-end encrypted message
$ret["ProtoIdent"]["name"] = "End-to-end encrypted message";
break;
case 137: // Immediate text messaging
$ret["ProtoIdent"]["name"] = "Immediate text messaging";
break;
case 138: // Message with User Data Header
$ret["ProtoIdent"]["name"] = "Message with User Data Header";
break;
case 140: // Concatenated SDS message
$ret["ProtoIdent"]["name"] = "Concatenated SDS message";
break;
default:
if((($ret["ProtoIdent"]["value"] > 63) && ($ret["ProtoIdent"]["value"] < 127)) || (($ret["ProtoIdent"]["value"] > 191) && ($ret["ProtoIdent"]["value"] < 255)))
{
$ret["ProtoIdent"]["name"] = "user application defined (value=".$ret["ProtoIdent"]["value"].")";
}
else
{
$ret["ProtoIdent"]["name"] = "Reserved (value=".$ret["ProtoIdent"]["value"].")";
}
}
return $ret;
}

Die Zahlen hinter den Case-Verzweigungen sind die Dezimalwerte der Protocol Identifier. Die folgenden Protokoll-Bestandteile sind teils variabel und abhängig von vorangehenden Feldern.

Die Länge der SDS-PDU sollte sich aus dem Produkt der Anzahl der Hexziffern mit 4 (Bit je Hexziffer) ergeben. Das hat mir aber bis jetzt auch noch nie Sorgen bereitet.