Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: AllStarLink/app_rpt
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 3.0.4
Choose a base ref
...
head repository: AllStarLink/app_rpt
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 3.0.5
Choose a head ref
  • 7 commits
  • 15 files changed
  • 3 contributors

Commits on Sep 14, 2024

  1. Update configs for missing options (#357)

    This updates simpleusb and usbradio config files for missing parallel port options.
    KB4MDD authored Sep 14, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    9471615 View commit details
  2. app_rpt: Correct crash when using rpt page

    This updates app_rpt to address a crash that occurred when using the rpt page command.
    
    ast_sendtext should not require locking according to the documentation but that does not seem to be the case.  In some instances, the main processing loop had control of the channel.  ast_sendtext would cause an assert abort in channel.c.
    
    This was shown by the message ast_sendtext_data: Thread LWP 88692 is blocking 'Radio/usb_2231', already blocked by thread LWP 88688 in procedure ast_waitfor_nandfds.
    
    Adding rpt_mutex_lock around ast_sendtext resolved the problem.
    
    Corrected an if statement in the same routine that was already flagged in the code as a bug.
    
    Remove chan_usbradio as a destination for paging.  chan_usbradio does not implement paging. Sending pages to chan_usbradio resulted in a stuck PTT.
    
    Applied coding standards to the routine.
    KB4MDD authored Sep 14, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    dcfe5d6 View commit details
  3. Update the permissions of the "archivedir" .WAV files. (#379)

    Allan-N authored Sep 14, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    af81d14 View commit details
  4. app_rpt: Correct VOX operation for autopatch

    This change restores the operation of the autopatch VOX function.
    
    Changes were made in #363 to get the autopatch working.  Part of those changes did not correctly address the operation of the VOX channel.  This change removes some of those changes and restores the operation of the VOX channel.
    
    For the VOX channel to work properly, this change along with changes to the DAHDI driver are required.  The changes to the DAHDI driver are located at https://github.com/KB4MDD/dahdi-linux
    
    We will be attempting to get these changes into the main DAHDI channel.
    KB4MDD authored Sep 14, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    be580fb View commit details

Commits on Sep 20, 2024

  1. Add RX Audio Statistics and ADC Clip Detection feature

    This feature adds a new ast_radio_check_rx_audio() function to res_usbradio.c that is called from simpleusb.c (and usbradio.c) during the processing of received USB audio frames.
    
    Statistics collected the include peak and average RMS audio levels averaged over the previous 1 second. For SimpleUSB devices, the statistics can be displayed using the simpleusb-tune-menu 'R' option or with the AMI 'susb tune menu-support y' (or 'radio tune menu-support-y') function. For USBRadio devices, use the radio-tune-menu 'R' option or the AMI 'radio tune menu-support-y' function.
    
    A new "clipledgpio" parameter has also been added to "simpleusb.conf: and "usbradio.conf".  If specified and ADC clipping is detected then the GPIO pin is set for 500mS to support illumination of a node / audio interface Clip LED.
    davidgsd authored Sep 20, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    5cc0a66 View commit details
  2. Fix LastKeyedTime/LastTxKeyedTime info in RPT events (#406)

    The rpt_manager_trigger() function uses ctime(3) to add formatted date/time
    strings for LastKeyedTime and LastTxKeyedTime.  Unfortunately, the returned
    strings include trailing '\n' characters that added empty lines to the output.
    This presents an issue as an empty line typically indicates the end of the AMI
    output.
    
    This change removes the extra (unexpected) '\n' characters.
    Allan-N authored Sep 20, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    f8a0fe3 View commit details

Commits on Sep 21, 2024

  1. v3.0.5 (#407)

    Allan-N authored Sep 21, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    34c8a64 View commit details
2 changes: 1 addition & 1 deletion apps/app_rpt.c
Original file line number Diff line number Diff line change
@@ -3861,7 +3861,7 @@ static inline int rxchannel_read(struct rpt *myrpt, const int lasttx)
if (blocksleft >= myrpt->p.monminblocks) {
myrpt->monstream =
ast_writefile(myfname, "wav49", "app_rpt Air Archive", O_CREAT | O_APPEND, 0,
0600);
0644);
}
}
}
2 changes: 1 addition & 1 deletion apps/app_rpt/app_rpt.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

#define VERSION_MAJOR 3
#define VERSION_MINOR 0
#define VERSION_PATCH 4
#define VERSION_PATCH 5

/* 99% of the DSP code in app_rpt exists in dsp.c as private functions. This code can mostly be
converted to use public dsp.h API.
43 changes: 19 additions & 24 deletions apps/app_rpt/rpt_bridging.c
Original file line number Diff line number Diff line change
@@ -417,29 +417,20 @@ static int *dahdi_confno(struct rpt *myrpt, enum rpt_conf_type type)
}

/*!
* \brief Get the conference number of a DAHDI channel
* \brief Get the channel number of a DAHDI channel
* \param chan DAHDI channel
* \retval -1 on failure, conference number on success
*/
static int dahdi_conf_fd_confno(struct ast_channel *chan)
{
struct dahdi_confinfo ci;
ci.chan = 0;
ci.confno = 0;
ci.confmode = 0;

/* This routine previously called DAHDI_CHANNO. After testing, we
* determined that DAHDI_CHANNO is actually returning the channel number,
* instead of the conference number. In some cases the channel number
* was same as the conference number. Since it was not accurate in
* all cases, it was switched to DAHDI_GETCONF.
*/
if (ioctl(ast_channel_fd(chan, 0), DAHDI_GETCONF, &ci)) {
ast_log(LOG_WARNING, "DAHDI_GETCONF failed: %s\n", strerror(errno));
static int dahdi_conf_get_channo(struct ast_channel *chan)
{
struct dahdi_confinfo ci = {0};

if (ioctl(ast_channel_fd(chan, 0), DAHDI_CHANNO, &ci.chan)) {
ast_log(LOG_WARNING, "DAHDI_CHANNO failed: %s\n", strerror(errno));
return -1;
}

return ci.confno;
return ci.chan;
}

int __rpt_conf_create(struct ast_channel *chan, struct rpt *myrpt, enum rpt_conf_type type, enum rpt_conf_flags flags, const char *file, int line)
@@ -494,7 +485,7 @@ int rpt_call_bridge_setup(struct rpt *myrpt, struct ast_channel *mychannel, stru
}

/* get its conference number */
res = dahdi_conf_fd_confno(mychannel);
res = dahdi_conf_get_channo(mychannel);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to get autopatch channel number\n");
ast_hangup(mychannel);
@@ -503,12 +494,16 @@ int rpt_call_bridge_setup(struct rpt *myrpt, struct ast_channel *mychannel, stru

/* put vox channel monitoring on the channel
*
* The conference flags were originally DAHDI_CONF_MONITOR. This
* setting caused dahdi_conf_add to return EINVAL. The flags
* RPT_CONF_CONF | RPT_CONF_LISTENER permits the vox channel to
* join the conference.
* This uses the internal DAHDI channel number to create the
* monitor conference. This code will hang here when trying to
* join the conference when the underlying version of DAHDI in use
* is missing a patch that allows the DAHDI_CONF_MONITOR option
* to monitor a pseudo channel. This patch prevents the hardware
* pre-echo routines from acting on a pseudo channel. It also
* prevents the DAHDI check conference routine from acting
* on a channel number being used as a conference.
*/
if (dahdi_conf_add(myrpt->voxchannel, res, RPT_CONF_CONF | RPT_CONF_LISTENER)) {
if (dahdi_conf_add(myrpt->voxchannel, res, DAHDI_CONF_MONITOR)) {
ast_hangup(mychannel);
return -1;
}
@@ -520,7 +515,7 @@ int rpt_mon_setup(struct rpt *myrpt)
int res;

if (!IS_PSEUDO(myrpt->txchannel) && myrpt->dahditxchannel == myrpt->txchannel) {
int confno = dahdi_conf_fd_confno(myrpt->txchannel); /* get tx channel's port number */
int confno = dahdi_conf_get_channo(myrpt->txchannel); /* get tx channel's port number */
if (confno < 0) {
return -1;
}
18 changes: 11 additions & 7 deletions apps/app_rpt/rpt_cli.c
Original file line number Diff line number Diff line change
@@ -857,32 +857,36 @@ static int rpt_do_page(int fd, int argc, const char *const *argv)
string_toupper(text);
snprintf(str, sizeof(str) - 1, "PAGE %s %s %s ", baud, capcode, text);
for (i = 6; i < argc; i++) {
if (i > 5)
if (i > 5) {
strncat(str, " ", sizeof(str) - 1);
}
strncat(str, argv[i], sizeof(str) - 1);
}
for (i = 0; i < nrpts; i++) {
if (!strcmp(nodename, rpt_vars[i].name)) {
struct rpt *myrpt = &rpt_vars[i];
/* ignore if not a USB channel */
/* BUGBUG XXX This looks wrong to me... won't it always be false? */
if (!strcasecmp(ast_channel_tech(myrpt->rxchannel)->type, "radio") &&
!strcasecmp(ast_channel_tech(myrpt->rxchannel)->type, "voter") &&
!strcasecmp(ast_channel_tech(myrpt->rxchannel)->type, "simpleusb")) {
/* ignore if not a channel that can accept the paging command */
if (strcasecmp(ast_channel_tech(myrpt->rxchannel)->type, "voter") &&
strcasecmp(ast_channel_tech(myrpt->rxchannel)->type, "simpleusb")) {
return RESULT_SUCCESS;
}
/* if we are playing telemetry, stop it now */
telem = myrpt->tele.next;
while (telem != &myrpt->tele) {
if (((telem->mode == ID) || (telem->mode == ID1) || (telem->mode == IDTALKOVER)) && (!telem->killed)) {
if (telem->chan)
if (telem->chan) {
ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV); /* Whoosh! */
}
telem->killed = 1;
myrpt->deferid = 1;
}
telem = telem->next;
}
gettimeofday(&myrpt->paging, NULL);
rpt_mutex_lock(&myrpt->blocklock);
ast_sendtext(myrpt->rxchannel, str);
rpt_mutex_unlock(&myrpt->blocklock);
break;
}
}
return RESULT_SUCCESS;
30 changes: 23 additions & 7 deletions apps/app_rpt/rpt_manager.c
Original file line number Diff line number Diff line change
@@ -18,6 +18,21 @@

extern struct rpt rpt_vars[MAXRPTS];

static char *ctime_no_newline(const time_t *clock)
{
static char buf[32];
const char *cp;
size_t len;

cp = ctime_r(clock, buf);
len = strnlen(buf, sizeof(buf));
if ((len > 0) && (buf[--len] == '\n')) {
buf[len] = '\0';
}

return cp;
}

void rpt_manager_trigger(struct rpt *myrpt, char *event, char *value)
{
manager_event(EVENT_FLAG_CALL, event,
@@ -26,8 +41,9 @@ void rpt_manager_trigger(struct rpt *myrpt, char *event, char *value)
"EventValue: %s\r\n"
"LastKeyedTime: %s\r\n"
"LastTxKeyedTime: %s\r\n",
myrpt->name, ast_channel_name(myrpt->rxchannel), value, ctime(&myrpt->lastkeyedtime),
ctime(&myrpt->lasttxkeyedtime)
myrpt->name, ast_channel_name(myrpt->rxchannel), value,
ctime_no_newline(&myrpt->lastkeyedtime),
ctime_no_newline(&myrpt->lasttxkeyedtime)
);
}

@@ -80,7 +96,7 @@ static int rpt_manager_do_sawstat(struct mansession *ses, const struct message *

l = rpt_vars[i].links.next;
while (l && (l != &rpt_vars[i].links)) {
if (l->name[0] == '0') { // Skip '0' nodes
if (l->name[0] == '0') { // Skip '0' nodes
l = l->next;
continue;
}
@@ -89,7 +105,7 @@ static int rpt_manager_do_sawstat(struct mansession *ses, const struct message *
(l->lastunkeytime) ? (int) (now - l->lastunkeytime) : -1);
l = l->next;
}
rpt_mutex_unlock(&rpt_vars[i].lock); // UNLOCK
rpt_mutex_unlock(&rpt_vars[i].lock); // UNLOCK
astman_append(ses, "\r\n");
return (0);
}
@@ -330,7 +346,8 @@ static int rpt_manager_do_xstat(struct mansession *ses, const struct message *m,
astman_append(ses, "iconns: %s\r\n", iconns);
astman_append(ses, "tot_state: %s\r\n", tot_state);
astman_append(ses, "ider_state: %s\r\n", ider_state);
astman_append(ses, "tel_mode: %s\r\n\r\n", tel_mode);
astman_append(ses, "tel_mode: %s\r\n", tel_mode);
astman_append(ses, "\r\n");

return 0;
}
@@ -617,13 +634,13 @@ static int rpt_manager_do_stats(struct mansession *s, const struct message *m, c
astman_append(s, "DtmfCommandsSinceSystemInitialization: %d\r\n", totalexecdcommands);
astman_append(s, "LastDtmfCommandExecuted: %s\r\n",
(lastdtmfcommand && strlen(lastdtmfcommand)) ? lastdtmfcommand : not_applicable);

hours = dailytxtime / 3600000;
dailytxtime %= 3600000;
minutes = dailytxtime / 60000;
dailytxtime %= 60000;
seconds = dailytxtime / 1000;
dailytxtime %= 1000;

astman_append(s, "TxTimeToday: %02d:%02d:%02d:%02d\r\n", hours, minutes, seconds, dailytxtime);

hours = (int) totaltxtime / 3600000;
@@ -632,7 +649,6 @@ static int rpt_manager_do_stats(struct mansession *s, const struct message *m, c
totaltxtime %= 60000;
seconds = (int) totaltxtime / 1000;
totaltxtime %= 1000;

astman_append(s, "TxTimeSinceSystemInitialization: %02d:%02d:%02d:%02d\r\n", hours, minutes, seconds,
(int) totaltxtime);

56 changes: 56 additions & 0 deletions channels/chan_simpleusb.c
Original file line number Diff line number Diff line change
@@ -314,6 +314,7 @@ struct chan_simpleusb_pvt {
struct timeval tonetime;
int toneflag;
int duplex3;
int clipledgpio; /* enables ADC Clip Detect feature to output on a specified GPIO# */

int32_t discfactor;
int32_t discounterl;
@@ -325,6 +326,8 @@ struct chan_simpleusb_pvt {
int32_t cur_gpios;
char *gpios[GPIO_PINCOUNT];
char *pps[32];

struct rxaudiostatistics rxaudiostats;

ast_mutex_t usblock;
};
@@ -344,6 +347,8 @@ static struct chan_simpleusb_pvt simpleusb_default = {
.rxondelay = 0,
.txoffdelay = 0,
.pager = PAGER_NONE,
.clipledgpio = 0,
.rxaudiostats.index = 0
};

/* DECLARE FUNCTION PROTOTYPES */
@@ -592,6 +597,15 @@ static int hidhdwconfig(struct chan_simpleusb_pvt *o)
o->hid_gpio_loc = 1; /* For ALL GPIO */
o->valid_gpios = 1; /* for GPIO 1 */
}
/* validate clipledgpio setting (Clip LED GPIO#) */
if (o->clipledgpio) {
if (o->clipledgpio >= GPIO_PINCOUNT || !(o->valid_gpios & (1 << (o->clipledgpio - 1)))) {
ast_log(LOG_ERROR, "Channel %s: clipledgpio = GPIO%d not supported\n", o->name, o->clipledgpio);
o->clipledgpio = 0;
} else {
o->hid_gpio_ctl |= 1 << (o->clipledgpio - 1); /* confirm Clip LED GPIO set to output mode */
}
}
o->hid_gpio_val = 0;
for (i = 0; i < GPIO_PINCOUNT; i++) {
/* skip if this one not specified */
@@ -2090,6 +2104,13 @@ static struct ast_frame *simpleusb_read(struct ast_channel *c)
if (f1->datalen - src >= l) {
/* enough to fill a frame */
memcpy(o->simpleusb_write_buf + o->simpleusb_write_dst, (char *) f1->data.ptr + src, l);

/* TBR - below is an attempt to match levels to the original CM108 IC which has
* been out of production for over 10 years. Scaling audio to 109.375% will
* result in clipping! Any adjustments for CM1xxx gain differences should be
* made in the mixer settings, not in the audio stream.
*/
#if 1
/* Adjust the audio level for CM119 A/B devices */
if (o->devtype != C108_PRODUCT_ID) {
register int v;
@@ -2107,6 +2128,8 @@ static struct ast_frame *simpleusb_read(struct ast_channel *c)
*sp++ = v;
}
}
#endif

sp = (short *) o->simpleusb_write_buf;
sp1 = outbuf;
doright = 1;
@@ -2267,6 +2290,21 @@ static struct ast_frame *simpleusb_read(struct ast_channel *c)
}
}

/* Check for ADC clipping and input audio statistics before any filtering is done.
* FRAME_SIZE define refers to 8Ksps mono which is 160 samples per 20mS USB frame.
* ast_radio_check_rx_audio() takes the read buffer as received (48K stereo),
* extracts the mono 48K channel, checks amplitude and distortion characteristics,
* and returns true if clipping was detected.
*/
if (ast_radio_check_rx_audio((short *) o->simpleusb_read_buf, &o->rxaudiostats, 12 * FRAME_SIZE)) {
if (o->clipledgpio) {
/* Set Clip LED GPIO pulsetimer if not already set */
if (!o->hid_gpio_pulsetimer[o->clipledgpio - 1]) {
o->hid_gpio_pulsetimer[o->clipledgpio - 1] = CLIP_LED_HOLD_TIME_MS;
}
}
}

/* Downsample received audio from 48000 stereo to 8000 mono */
sp = (short *) o->simpleusb_read_buf;
sp1 = (short *) (o->simpleusb_read_frame_buf + AST_FRIENDLY_OFFSET);
@@ -3273,6 +3311,7 @@ static void tune_write(struct chan_simpleusb_pvt *o)
* t - change rx on delay
* u - change tx off delay
* v - view cos, ctcss and ptt status
* y - receive audio statistics display
*
* \param fd Asterisk CLI fd
* \param o Private struct.
@@ -3467,6 +3506,22 @@ static void tune_menusupport(int fd, struct chan_simpleusb_pvt *o, const char *c
}
tune_rxtx_status(fd, o);
break;
case 'y': /* display receive audio statistics (interactive) */
case 'Y': /* display receive audio statistics (once only) */
if (!o->hasusb) {
ast_cli(fd, USB_UNASSIGNED_FMT, o->name, o->devstr);
break;
}
for (;;) {
ast_radio_print_rx_audio_stats(fd, &o->rxaudiostats);
if (cmd[0] == 'Y') {
break;
}
if (ast_radio_poll_input(fd, 1000)) {
break;
}
}
break;
default:
ast_cli(fd, "Invalid Command\n");
break;
@@ -3650,6 +3705,7 @@ static struct chan_simpleusb_pvt *store_config(const struct ast_config *cfg, con
CV_BOOL("deemphasis", o->deemphasis);
CV_BOOL("preemphasis", o->preemphasis);
CV_UINT("duplex3", o->duplex3);
CV_UINT("clipledgpio", o->clipledgpio);
CV_END;

for (i = 0; i < GPIO_PINCOUNT; i++) {
Loading