57
57
import io .github .dsheirer .module .decode .dmr .message .data .csbk .standard .announcement .VoteNowAdvice ;
58
58
import io .github .dsheirer .module .decode .dmr .message .data .csbk .standard .grant .ChannelGrant ;
59
59
import io .github .dsheirer .module .decode .dmr .message .data .header .HeaderMessage ;
60
+ import io .github .dsheirer .module .decode .dmr .message .data .header .hytera .HyteraDataEncryptionHeader ;
60
61
import io .github .dsheirer .module .decode .dmr .message .data .lc .LCMessage ;
61
62
import io .github .dsheirer .module .decode .dmr .message .data .lc .full .GPSInformation ;
62
63
import io .github .dsheirer .module .decode .dmr .message .data .lc .full .GroupVoiceChannelUser ;
74
75
import io .github .dsheirer .module .decode .dmr .message .type .ServiceOptions ;
75
76
import io .github .dsheirer .module .decode .dmr .message .voice .VoiceEMBMessage ;
76
77
import io .github .dsheirer .module .decode .dmr .message .voice .VoiceMessage ;
77
- import io .github .dsheirer .module .decode .dmr .message .voice .embedded .Arc4EncryptionParameters ;
78
78
import io .github .dsheirer .module .decode .dmr .message .voice .embedded .EmbeddedParameters ;
79
+ import io .github .dsheirer .module .decode .dmr .message .voice .embedded .EncryptionParameters ;
79
80
import io .github .dsheirer .module .decode .event .DecodeEvent ;
80
81
import io .github .dsheirer .module .decode .event .DecodeEventType ;
81
82
import io .github .dsheirer .module .decode .event .PlottableDecodeEvent ;
82
83
import io .github .dsheirer .module .decode .ip .hytera .sds .HyteraUnknownPacket ;
84
+ import io .github .dsheirer .module .decode .ip .hytera .shortdata .HyteraShortDataPacket ;
83
85
import io .github .dsheirer .module .decode .ip .hytera .sms .HyteraSmsPacket ;
86
+ import io .github .dsheirer .module .decode .ip .mototrbo .ars .ARSPacket ;
87
+ import io .github .dsheirer .module .decode .ip .mototrbo .lrrp .LRRPPacket ;
88
+ import io .github .dsheirer .module .decode .ip .mototrbo .xcmp .XCMPPacket ;
84
89
import io .github .dsheirer .protocol .Protocol ;
85
90
import io .github .dsheirer .source .tuner .channel .rotation .AddChannelRotationActiveStateRequest ;
86
91
import io .github .dsheirer .util .PacketUtil ;
@@ -320,6 +325,32 @@ private void processPacket(DMRPacketMessage packet)
320
325
.build ();
321
326
broadcast (smsEvent );
322
327
}
328
+ //Hytera Short Data - Radio Registration Service (RRS)
329
+ else if (packet .getPacket () instanceof HyteraShortDataPacket hsdp )
330
+ {
331
+ MutableIdentifierCollection mic = new MutableIdentifierCollection (packet .getIdentifiers ());
332
+
333
+ StringBuilder sb = new StringBuilder ();
334
+ sb .append ("HYTERA" );
335
+
336
+ if (hsdp .getPacketSequence ().isEncrypted ())
337
+ {
338
+ HyteraDataEncryptionHeader hdeh = (HyteraDataEncryptionHeader )hsdp .getPacketSequence ().getProprietaryDataHeader ();
339
+ sb .append (" ENCRYPTED ALGORITHM:" ).append (hdeh .getAlgorithm ());
340
+ sb .append (" KEY:" ).append (hdeh .getKeyId ());
341
+ sb .append (" IV:" ).append (hdeh .getIV ());
342
+ }
343
+
344
+ sb .append (" SHORT DATA:" ).append (hsdp .getMessage ().toHexString ());
345
+
346
+
347
+ DecodeEvent shortDataEvent = DMRDecodeEvent .builder (DecodeEventType .RADIO_REGISTRATION_SERVICE , packet .getTimestamp ())
348
+ .identifiers (mic )
349
+ .timeslot (getTimeslot ())
350
+ .details (sb .toString ())
351
+ .build ();
352
+ broadcast (shortDataEvent );
353
+ }
323
354
//Unknown Hytera Long Data Service Token Message
324
355
else if (packet .getPacket () instanceof HyteraUnknownPacket hyteraUnknownPacket )
325
356
{
@@ -328,10 +359,46 @@ else if(packet.getPacket() instanceof HyteraUnknownPacket hyteraUnknownPacket)
328
359
DecodeEvent unknownTokenEvent = DMRDecodeEvent .builder (DecodeEventType .UNKNOWN_PACKET , packet .getTimestamp ())
329
360
.identifiers (mic )
330
361
.timeslot (getTimeslot ())
331
- .details ("HYTERA UNK TOKEN MSG:" + hyteraUnknownPacket .getHeader ().toString ())
362
+ .details ("HYTERA LONG DATA UNK TOKEN MSG:" + hyteraUnknownPacket .getHeader ().toString ())
332
363
.build ();
333
364
broadcast (unknownTokenEvent );
334
365
}
366
+ //Motorola ARS
367
+ else if (packet .getPacket () instanceof ARSPacket ars )
368
+ {
369
+ MutableIdentifierCollection mic = new MutableIdentifierCollection (packet .getIdentifiers ());
370
+
371
+ DecodeEvent shortDataEvent = DMRDecodeEvent .builder (DecodeEventType .RADIO_REGISTRATION_SERVICE , packet .getTimestamp ())
372
+ .identifiers (mic )
373
+ .timeslot (getTimeslot ())
374
+ .details (ars .toString ())
375
+ .build ();
376
+ broadcast (shortDataEvent );
377
+ }
378
+ //Motorola LRRP
379
+ else if (packet .getPacket () instanceof LRRPPacket lrrp )
380
+ {
381
+ MutableIdentifierCollection mic = new MutableIdentifierCollection (packet .getIdentifiers ());
382
+
383
+ DecodeEvent shortDataEvent = DMRDecodeEvent .builder (DecodeEventType .LRRP , packet .getTimestamp ())
384
+ .identifiers (mic )
385
+ .timeslot (getTimeslot ())
386
+ .details (lrrp .toString ())
387
+ .build ();
388
+ broadcast (shortDataEvent );
389
+ }
390
+ //Motorola XCMP
391
+ else if (packet .getPacket () instanceof XCMPPacket xcmp )
392
+ {
393
+ MutableIdentifierCollection mic = new MutableIdentifierCollection (packet .getIdentifiers ());
394
+
395
+ DecodeEvent shortDataEvent = DMRDecodeEvent .builder (DecodeEventType .XCMP , packet .getTimestamp ())
396
+ .identifiers (mic )
397
+ .timeslot (getTimeslot ())
398
+ .details (xcmp .toString ())
399
+ .build ();
400
+ broadcast (shortDataEvent );
401
+ }
335
402
else
336
403
{
337
404
DecodeEvent packetEvent = DMRDecodeEvent .builder (DecodeEventType .DATA_PACKET , packet .getTimestamp ())
@@ -380,7 +447,7 @@ private void processVoice(VoiceMessage message)
380
447
{
381
448
EmbeddedParameters embedded = voiceEmb .getEmbeddedParameters ();
382
449
383
- if (embedded .getShortBurst () instanceof Arc4EncryptionParameters arc4 )
450
+ if (embedded .getShortBurst () instanceof EncryptionParameters arc4 )
384
451
{
385
452
updateEncryptedCall (arc4 , true , voiceEmb .getTimestamp ());
386
453
}
@@ -972,6 +1039,15 @@ private void processLinkControl(LCMessage message, boolean isTerminator)
972
1039
{
973
1040
switch (message .getOpcode ())
974
1041
{
1042
+ case FULL_ENCRYPTION_PARAMETERS :
1043
+ if (message instanceof io .github .dsheirer .module .decode .dmr .message .data .lc .full .EncryptionParameters ep )
1044
+ {
1045
+ if (mCurrentCallEvent != null )
1046
+ {
1047
+ mCurrentCallEvent .setDetails (ep .getDetails ());
1048
+ }
1049
+ }
1050
+ break ;
975
1051
case SHORT_CAPACITY_PLUS_REST_CHANNEL_NOTIFICATION :
976
1052
if (message instanceof CapacityPlusRestChannel )
977
1053
{
@@ -1141,7 +1217,7 @@ private void processLinkControl(LCMessage message, boolean isTerminator)
1141
1217
* @param encryptionParameters decoded from the Voice Frame F
1142
1218
* @param isGroup true for group or false for individual call.
1143
1219
*/
1144
- private void updateEncryptedCall (Arc4EncryptionParameters encryptionParameters , boolean isGroup , long timestamp )
1220
+ private void updateEncryptedCall (EncryptionParameters encryptionParameters , boolean isGroup , long timestamp )
1145
1221
{
1146
1222
if (mCurrentCallEvent != null )
1147
1223
{
@@ -1151,7 +1227,7 @@ private void updateEncryptedCall(Arc4EncryptionParameters encryptionParameters,
1151
1227
{
1152
1228
details = encryptionParameters .toString ();
1153
1229
}
1154
- else if (!details .contains (encryptionParameters .toString ()))
1230
+ else if (!details .contains (encryptionParameters .toString ()) && ! details . contains ( "ENCRYPTION" ) )
1155
1231
{
1156
1232
details += " " + encryptionParameters ;
1157
1233
}
0 commit comments