From bb2199ee848da79f658e886157eb7b463c31d8e0 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Mon, 2 Jan 2023 08:04:22 -0500 Subject: [PATCH] Con+ CSBK and Tuning Fixes; Group Call Options; --- examples/Example_Usage.md | 5 +- include/dsd.h | 5 +- src/dmr_csbk.c | 137 ++++++++++++++++++++------------------ src/dmr_data.c | 4 +- src/dsd_main.c | 19 +++++- src/dsd_ncurses.c | 24 +++++-- src/p25p2_vpdu.c | 27 +++++++- 7 files changed, 142 insertions(+), 79 deletions(-) diff --git a/examples/Example_Usage.md b/examples/Example_Usage.md index 104619d..441f28e 100644 --- a/examples/Example_Usage.md +++ b/examples/Example_Usage.md @@ -151,7 +151,8 @@ t - toggle trunking (needs either rtl input, or rigctl connection) 2 - Lockout Tuning/Playback of TG in Slot 2 (Current Session Only) 0 - Toggle Audio Smoothing - May produce crackling if enabled on RTL/TCP or wav/bin files w - Toggle Trunking/Playback White List (Allow A Groups Only) / Black List (Block B or DE groups only) Mode -e - Toggle Trunking Tuning to Data Calls -E - Toggle Trunking Tuning to Private Calls +g - Toggle Trunking Tuning to Group Calls (DMR T3, Con+, Cap+, P25) +u - Toggle Trunking Tuning to Private Calls (DMR T3, P25) +d - Toggle Trunking Tuning to Data Calls (DMR T3) ``` \ No newline at end of file diff --git a/include/dsd.h b/include/dsd.h index dad61c9..05050ff 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -339,10 +339,13 @@ typedef struct //Trunking - Use Group List as Allow List uint8_t trunk_use_allow_list; + //Trunking - Tune Group Calls + uint8_t trunk_tune_group_calls; + //Trunking - Tune Private Calls uint8_t trunk_tune_private_calls; - //Trunking - Tune Data Calls...why? + //Trunking - Tune Data Calls uint8_t trunk_tune_data_calls; } dsd_opts; diff --git a/src/dmr_csbk.c b/src/dmr_csbk.c index e79b531..2128dd9 100644 --- a/src/dmr_csbk.c +++ b/src/dmr_csbk.c @@ -37,6 +37,10 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8 csbk_pf = ( (cs_pdu[1] & 0x80) >> 7); csbk = ((cs_pdu[0] & 0x3F) << 8) | cs_pdu[1]; //opcode and fid combo set + //update time to prevent random 'Control Channel Signal Lost' hopping + //in the middle of voice call on current Control Channel (con+ and t3) + state->last_cc_sync_time = time(NULL); + if (csbk_pf == 1) //check the protect flag, don't run if set { fprintf (stderr, "%s", KRED); @@ -143,14 +147,17 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8 (stderr, "\n Frequency [%.6lf] MHz", (double)freq/1000000); } - //Skip tuning private calls if private calls are disabled - if (opts->trunk_tune_private_calls == 0 && csbk_o != 49) goto SKIPCALL; + //Skip tuning group calls if group calls are disabled + if (opts->trunk_tune_group_calls == 0 && csbk_o == 49) goto SKIPCALL; //Allow tuning of data calls if user wishes by flipping the csbk_o to a group voice call if (csbk_o == 51 || csbk_o == 52 || csbk_o == 54) { if (opts->trunk_tune_data_calls == 1) csbk_o = 49; } + + //Skip tuning private calls if private calls are disabled + if (opts->trunk_tune_private_calls == 0 && csbk_o != 49) goto SKIPCALL; //if not a data channel grant (only tuning to voice channel grants) if (csbk_o == 48 || csbk_o == 49 || csbk_o == 50 || csbk_o == 53) //48, 49, 50 are voice grants, 51 and 52 are data grants, 53 Duplex Private Voice, 54 Duplex Private Data @@ -707,6 +714,9 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8 fprintf (stderr, "%s", KNRM); + //Skip tuning group calls if group calls are disabled + if (opts->trunk_tune_group_calls == 0) goto SKIPCAP; + //don't tune if currently a vc on the current channel if ( (time(NULL) - state->last_vc_sync_time > 2) ) { @@ -759,15 +769,13 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8 } } + SKIPCAP: ; //do nothing } //Connect+ Section if (csbk_fid == 0x06) { - //maintain this to allow users to hardset the cc freq as map[0]; otherwise, set from rigctl or rtl freq - // if (state->p25_cc_freq == 0 && state->trunk_chan_map[0] != 0) state->p25_cc_freq = state->trunk_chan_map[0]; - if (csbk_o == 0x01) { //initial line break @@ -802,6 +810,9 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8 sprintf (state->dmr_branding, "%s", "Motorola"); sprintf(state->dmr_branding_sub, "Con+ "); + //Skip tuning group calls if group calls are disabled + if (opts->trunk_tune_group_calls == 0) goto SKIPCON; + //if using rigctl we can set an unknown or updated cc frequency //by polling rigctl for the current frequency if (opts->use_rigctl == 1 && opts->p25_is_tuned == 0) //&& state->p25_cc_freq == 0 @@ -841,7 +852,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8 } //don't tune if currently a vc on the control channel - if ( (time(NULL) - state->last_vc_sync_time > 2) ) + if ( (opts->trunk_tune_group_calls == 1) && (time(NULL) - state->last_vc_sync_time > 2) ) { if (state->p25_cc_freq != 0 && opts->p25_trunk == 1 && (strcmp(mode, "B") != 0) && (strcmp(mode, "DE") != 0) ) @@ -873,72 +884,70 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8 } } + SKIPCON: ; //do nothing + } - if (csbk_o == 0x06) + //upon further examination, opcodes 6 and C (12) do not appear to be a channel grants or tlcs, + //it is present in Connect+, but its purpose isn't entirely clear + //DSDPlus only regards it as a 'CSBK [LB=1 CSBKO=6 (?) FID=06 v1=115213 v2=10488576 v3=0] + //unsure of what the v1 v2 v3 fields specify + // if (csbk_o == 0x06 || csbk_o == 0x0C) + if (csbk_o != 0x01 && csbk_o != 0x03) { - //initial line break - fprintf (stderr, "\n"); - uint32_t srcAddr = ( (cs_pdu[2] << 16) + (cs_pdu[3] << 8) + cs_pdu[4] ); - uint32_t grpAddr = ( (cs_pdu[5] << 16) + (cs_pdu[6] << 8) + cs_pdu[7] ); - uint8_t lcn = ( (cs_pdu[8] & 0xF0 ) >> 4 ) ; - uint8_t tslot = ( (cs_pdu[8] & 0x08 ) >> 3 ); - fprintf (stderr, "%s", KYEL); - fprintf (stderr, " Connect Plus Data Channel Grant\n"); - fprintf (stderr, " srcAddr(%8d), grpAddr(%8d), LCN(%d), TS(%d)",srcAddr, grpAddr, lcn, tslot); - state->dmr_mfid = 0x06; - sprintf (state->dmr_branding, "%s", "Motorola"); - sprintf(state->dmr_branding_sub, "Con+ "); + + uint32_t v1 = ( (cs_pdu[2] << 16) + (cs_pdu[3] << 8) + cs_pdu[4] ); + uint32_t v2 = ( (cs_pdu[5] << 16) + (cs_pdu[6] << 8) + cs_pdu[7] ); + uint32_t v3 = ( (cs_pdu[7] << 16) + (cs_pdu[8] << 8) + cs_pdu[9] ); + + // debug print + // initial line break + // fprintf (stderr, "\n"); + // fprintf (stderr, "%s", KYEL); + // fprintf (stderr, " Connect Plus CSBK 0x%X\n", csbk_o); + // fprintf (stderr, " v1(%d), v2(%d), v3(%d)",v1, v2, v3); + // state->dmr_mfid = 0x06; + // sprintf (state->dmr_branding, "%s", "Motorola"); + // sprintf(state->dmr_branding_sub, "Con+ "); } - if (csbk_o == 0x0C) - { - //initial line break - fprintf (stderr, "\n"); - uint32_t srcAddr = ( (cs_pdu[2] << 16) + (cs_pdu[3] << 8) + cs_pdu[4] ); - uint32_t grpAddr = ( (cs_pdu[5] << 16) + (cs_pdu[6] << 8) + cs_pdu[7] ); - uint8_t lcn = ( (cs_pdu[8] & 0xF0 ) >> 4 ); - uint8_t tslot = ( (cs_pdu[8] & 0x08 ) >> 3 ); - fprintf (stderr, "%s", KYEL); - fprintf (stderr, " Connect Plus Terminate Channel Grant\n"); - fprintf (stderr, " srcAddr(%8d), grpAddr(%8d), LCN(%d), TS(%d)",srcAddr, grpAddr, lcn, tslot); - state->dmr_mfid = 0x06; - sprintf (state->dmr_branding, "%s", "Motorola"); - sprintf(state->dmr_branding_sub, "Con+ "); - } + //the validity of these last three csbk opcodes cannot be confirmed + //I recall making these based on observation and speculation long ago, + //but cannot verify the accuracy of them now, so they will remain disabled + //they offer no particular interest to trunking/listening - if (csbk_o == 0x11) - { - //initial line break - fprintf (stderr, "\n"); - fprintf (stderr, "%s", KYEL); - fprintf (stderr, " Connect Plus Registration Request"); - state->dmr_mfid = 0x06; - sprintf (state->dmr_branding, "%s", "Motorola"); - sprintf(state->dmr_branding_sub, "Con+ "); - } + // if (csbk_o == 0x11) + // { + // //initial line break + // fprintf (stderr, "\n"); + // fprintf (stderr, "%s", KYEL); + // fprintf (stderr, " Connect Plus Registration Request"); + // state->dmr_mfid = 0x06; + // sprintf (state->dmr_branding, "%s", "Motorola"); + // sprintf(state->dmr_branding_sub, "Con+ "); + // } - if (csbk_o == 0x12) - { - //initial line break - fprintf (stderr, "\n"); - fprintf (stderr, "%s", KYEL); - fprintf (stderr, " Connect Plus Registration Response"); - state->dmr_mfid = 0x06; - sprintf (state->dmr_branding, "%s", "Motorola"); - sprintf(state->dmr_branding_sub, "Con+ "); - } + // if (csbk_o == 0x12) + // { + // //initial line break + // fprintf (stderr, "\n"); + // fprintf (stderr, "%s", KYEL); + // fprintf (stderr, " Connect Plus Registration Response"); + // state->dmr_mfid = 0x06; + // sprintf (state->dmr_branding, "%s", "Motorola"); + // sprintf(state->dmr_branding_sub, "Con+ "); + // } - if (csbk_o == 0x18) - { - //initial line break - fprintf (stderr, "\n"); - fprintf (stderr, "%s", KYEL); - fprintf (stderr, " Connect Plus Talkgroup Affiliation"); - state->dmr_mfid = 0x06; - sprintf (state->dmr_branding, "%s", "Motorola"); - sprintf(state->dmr_branding_sub, "Con+ "); - } + // if (csbk_o == 0x18) + // { + // //initial line break + // fprintf (stderr, "\n"); + // fprintf (stderr, "%s", KYEL); + // fprintf (stderr, " Connect Plus Talkgroup Affiliation"); + // state->dmr_mfid = 0x06; + // sprintf (state->dmr_branding, "%s", "Motorola"); + // sprintf(state->dmr_branding_sub, "Con+ "); + // } fprintf (stderr, "%s", KNRM); diff --git a/src/dmr_data.c b/src/dmr_data.c index d408975..0b46d6a 100644 --- a/src/dmr_data.c +++ b/src/dmr_data.c @@ -319,8 +319,8 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state) //con+ voice channels can have extremely long idle periods without properly tearing down if (opts->p25_trunk == 1 && opts->p25_is_tuned == 1 && state->is_con_plus == 1) { - //at 3 seconds, the CC was sending back to the VC even without voice present, increased to 5 - if ( (time(NULL) - state->last_vc_sync_time > 5) ) + //bug fixed that caused hopping from CC to VC; decreased to 2 seconds. + if ( (time(NULL) - state->last_vc_sync_time > 2) ) { if (opts->use_rigctl == 1) //rigctl tuning { diff --git a/src/dsd_main.c b/src/dsd_main.c index 3991a68..08811ba 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -125,6 +125,8 @@ noCarrier (dsd_opts * opts, dsd_state * state) //zero out vc frequencies? state->p25_vc_freq[0] = 0; state->p25_vc_freq[1] = 0; + + state->is_con_plus = 0; //flag off } state->dibit_buf_p = state->dibit_buf + 200; @@ -492,6 +494,9 @@ initOpts (dsd_opts * opts) //Trunking - Use Group List as Allow List opts->trunk_use_allow_list = 0; //disabled by default + //Trunking - Tune Group Calls + opts->trunk_tune_group_calls = 1; //enabled by default + //Trunking - Tune Private Calls opts->trunk_tune_private_calls = 1; //enabled by default @@ -941,11 +946,13 @@ usage () printf (" -T Enable Trunking Features (NXDN/P25/EDACS/DMR) with RIGCTL/TCP or RTL Input\n"); printf (" -W Use Imported Group List as a Trunking Allow/White List -- Only Tune with Mode A\n"); printf (" -p Disable Tune to Private Calls (DMR TIII and P25)\n"); + printf (" -E Disable Tune to Group Calls (DMR TIII, Con+, Cap+ and P25)\n"); + printf (" (NOTE: NXDN and EDACS, simply disable trunking if desired) \n"); printf (" -e Enable Tune to Data Calls (DMR TIII)\n"); - printf (" (NOTE: DMR Con+ and P25 Data Channels Not Enabled (no handling) \n"); + printf (" (NOTE: P25 Data Channels Not Enabled (no handling) \n"); printf (" -U Enable RIGCTL/TCP; Set TCP Port for RIGCTL. (4532 on SDR++)\n"); printf (" -B Set RIGCTL Setmod Bandwidth in Hertz (0 - default - OFF)\n"); - printf (" P25 - 7000; P25 (QPSK) - 12000; NXDN48 - 4000; DMR - 7000; EDACS/PV - 12500;\n"); + printf (" P25 - 7000-12000; P25 (QPSK) - 12000; NXDN48 - 4000; DMR - 7000; EDACS/PV - 12500;\n"); printf (" May vary based on system stregnth, etc.\n"); printf (" -t Set Trunking VC/sync loss hangtime in seconds. (default = 1 second)\n"); printf ("\n"); @@ -1162,7 +1169,7 @@ main (int argc, char **argv) exitflag = 0; // signal (SIGINT, sigfun); - while ((c = getopt (argc, argv, "haepPqs:t:v:z:i:o:d:c:g:nw:B:C:R:f:m:u:x:A:S:M:G:D:L:VU:Y:K:H:X:NQWrlZTF01:2:345:6:7:89:")) != -1) + while ((c = getopt (argc, argv, "haepPqs:t:v:z:i:o:d:c:g:nw:B:C:R:f:m:u:x:A:S:M:G:D:L:VU:Y:K:H:X:NQWrlZTF01:2:345:6:7:89:E")) != -1) { opterr = 0; switch (c) @@ -1192,6 +1199,12 @@ main (int argc, char **argv) fprintf (stderr, "Using Group List as Allow/White List. \n"); break; + //Trunking - Tune Group Calls + case 'E': + opts.trunk_tune_group_calls = 0; //disable + fprintf (stderr, "Disable Tuning to Group Calls. \n"); + break; + //Trunking - Tune Private Calls case 'p': opts.trunk_tune_private_calls = 0; //disable diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index 0abe253..cfdd002 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -2145,10 +2145,16 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) } if (opts->p25_trunk == 1 && (opts->use_rigctl == 1 || opts->audio_in_type == 3) ) { - printw ("| Trunk Tracking Active"); - printw (" - Group"); - if (opts->trunk_tune_private_calls == 1) printw (" Private"); - if (opts->trunk_tune_data_calls == 1) printw (" Data"); + printw ("| Trunk Tracking Active -"); + if (opts->trunk_tune_group_calls == 0) attron(COLOR_PAIR(2)); + printw (" Group(g)"); + attron(COLOR_PAIR(4)); + if (opts->trunk_tune_private_calls == 0) attron(COLOR_PAIR(2)); + printw (" Private(u)"); + attron(COLOR_PAIR(4)); + if (opts->trunk_tune_data_calls == 0) attron(COLOR_PAIR(2)); + printw (" Data(d)"); + attron(COLOR_PAIR(4)); printw (" Calls"); if (opts->trunk_use_allow_list == 1) printw (" - White List Mode\n"); else printw (" - Black List Mode\n"); @@ -3196,18 +3202,24 @@ if (opts->p25_trunk == 1 && c == 119) //'w' key, toggle white list/black list mo else opts->trunk_use_allow_list = 1; } -if (opts->p25_trunk == 1 && c == 69) //'E' key, toggle tune private calls +if (opts->p25_trunk == 1 && c == 117) //'u' key, toggle tune private calls { if (opts->trunk_tune_private_calls == 1) opts->trunk_tune_private_calls = 0; else opts->trunk_tune_private_calls = 1; } -if (opts->p25_trunk == 1 && c == 101) //'e' key, toggle tune data calls +if (opts->p25_trunk == 1 && c == 100) //'d' key, toggle tune data calls { if (opts->trunk_tune_data_calls == 1) opts->trunk_tune_data_calls = 0; else opts->trunk_tune_data_calls = 1; } +if (opts->p25_trunk == 1 && c == 103) //'g' key, toggle tune group calls +{ + if (opts->trunk_tune_group_calls == 1) opts->trunk_tune_group_calls = 0; + else opts->trunk_tune_group_calls = 1; +} + //anything with an entry box will need the inputs and outputs stopped first //so probably just write a function to handle c input, and when c = certain values //needing an entry box, then stop all of those diff --git a/src/p25p2_vpdu.c b/src/p25p2_vpdu.c index 0ba1cce..b0694c2 100644 --- a/src/p25p2_vpdu.c +++ b/src/p25p2_vpdu.c @@ -105,6 +105,9 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon } } + //Skip tuning group calls if group calls are disabled + if (opts->trunk_tune_group_calls == 0) goto SKIPCALL; + //tune if tuning available if (opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0)) { @@ -170,6 +173,9 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon } } + //Skip tuning group calls if group calls are disabled + if (opts->trunk_tune_group_calls == 0) goto SKIPCALL; + //tune if tuning available if (opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0)) { @@ -233,6 +239,9 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon fprintf (stderr, "\n Channel 2 [%04X] Group 2 [%d][%04X]", channel2, group2, group2); freq2 = process_channel_to_freq (opts, state, channel2); + //Skip tuning group calls if group calls are disabled + if (opts->trunk_tune_group_calls == 0) goto SKIPCALL; + //monstrocity below should get us evaluating and tuning groups...hopefully, will be first come first served though, no priority //see how many loops we need to run on when to tune if first group is blocked int loop = 1; @@ -343,6 +352,9 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon } } + //Skip tuning group calls if group calls are disabled + if (opts->trunk_tune_group_calls == 0) goto SKIPCALL; + //tune if tuning available if (opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0)) { @@ -460,7 +472,6 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon } } - SKIPCALL: ; //do nothing } //Group Voice Channel Grant Update Multiple - Explicit @@ -486,6 +497,9 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon freq1t = process_channel_to_freq (opts, state, channelt2); freq1r = process_channel_to_freq (opts, state, channelr2); + //Skip tuning group calls if group calls are disabled + if (opts->trunk_tune_group_calls == 0) goto SKIPCALL; + int loop = 1; if (channelt2 == channelt2) loop = 1; else loop = 2; @@ -590,6 +604,9 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon fprintf (stderr, "\n Channel 3 [%04X] Group 3 [%d][%04X]", channel3, group3, group3); freq3 = process_channel_to_freq (opts, state, channel3); + //Skip tuning group calls if group calls are disabled + if (opts->trunk_tune_group_calls == 0) goto SKIPCALL; + int loop = 3; long int tunable_freq = 0; @@ -693,6 +710,9 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon fprintf (stderr, "\n Channel 2 [%04X] Group 2 [%d][%04X]", channel2, group2, group2); freq2 = process_channel_to_freq (opts, state, channel2); + //Skip tuning group calls if group calls are disabled + if (opts->trunk_tune_group_calls == 0) goto SKIPCALL; + int loop = 1; if (channel1 == channel2) loop = 1; else loop = 2; @@ -805,6 +825,9 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon } } + //Skip tuning group calls if group calls are disabled + if (opts->trunk_tune_group_calls == 0) goto SKIPCALL; + //tune if tuning available if (opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0)) { @@ -1315,6 +1338,8 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon } + SKIPCALL: ; //do nothing + if ( (len_b + len_c) < 24 && len_c != 0) { len_a = len_b;