Skip to content

Commit

Permalink
chan_simpleusb/chan_usbradio: Use monotonic clock (#346)
Browse files Browse the repository at this point in the history
This changes chan_simpleusb and chan_usbradio to use the monotonic clock.  This will address timing issues when NTP updates the internal clock.

This closes #344
  • Loading branch information
KB4MDD authored Jul 6, 2024
1 parent dd4ff81 commit 34681d3
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 27 deletions.
60 changes: 46 additions & 14 deletions channels/chan_simpleusb.c
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,38 @@ static struct ast_channel_tech simpleusb_tech = {
.setoption = simpleusb_setoption,
};

/*!
* \brief Get system monotonic
* This returns the CLOCK_MONOTONIC time
* \param second Pointer to time_t to receive the time.
*/
static void rpt_time(time_t *second)
{
struct timespec ts;

clock_gettime(CLOCK_MONOTONIC, &ts);

*second = ts.tv_sec;
}

/*!
* \brief Get system monotonic timeval
* This returns the CLOCK_MONOTONIC time as a timeval
* \retval timval structure with the current monotonic time.
*/
static struct timeval rpt_tvnow(void)
{
struct timeval tv;
struct timespec ts;

clock_gettime(CLOCK_MONOTONIC, &ts);

tv.tv_sec = ts.tv_sec;
tv.tv_usec = ts.tv_nsec / 1000;

return tv;
}

/*!
* \brief FIR Low pass filter.
* 2900 Hz passband with 0.5 db ripple, 6300 Hz stopband at 60db.
Expand Down Expand Up @@ -724,12 +756,12 @@ static void *pulserthread(void *arg)
ast_mutex_lock(&pp_lock);
ast_radio_ppwrite(haspp, ppfd, pbase, pport, pp_val);
ast_mutex_unlock(&pp_lock);
then = ast_tvnow();
then = rpt_tvnow();

while (!stoppulser) {
usleep(50000);
ast_mutex_lock(&pp_lock);
now = ast_tvnow();
now = rpt_tvnow();
j = ast_tvdiff_ms(now, then);
then = now;
/* make output inversion mask (for pulseage) */
Expand Down Expand Up @@ -872,7 +904,7 @@ static void *hidthread(void *arg)
* with the usb hid device
*/
while (!o->stophid) {
time(&o->lasthidtime);
rpt_time(&o->lasthidtime);
ast_mutex_lock(&usb_dev_lock);
o->hasusb = 0;
o->usbass = 0;
Expand All @@ -891,7 +923,7 @@ static void *hidthread(void *arg)
* If no device string is specified, attempt to assign the first
* found device.
*/
time(&o->lasthidtime);
rpt_time(&o->lasthidtime);

/* Automatically assign a devstr if one was not specified in the configuration. */
if (ast_strlen_zero(o->devstr)) {
Expand Down Expand Up @@ -997,7 +1029,7 @@ static void *hidthread(void *arg)
}
#endif
o->device_error = 0;
time(&o->lasthidtime);
rpt_time(&o->lasthidtime);
o->usbass = 1;
ast_mutex_unlock(&usb_dev_lock);
/* set the audio mixer values */
Expand Down Expand Up @@ -1083,15 +1115,15 @@ static void *hidthread(void *arg)
rfds[0].fd = o->pttkick[1];
rfds[0].events = POLLIN;

time(&o->lasthidtime);
rpt_time(&o->lasthidtime);
/* Main processing loop for GPIO
* This loop process every 50 milliseconds.
* The timer can be interupted by writing to
* the pttkick pipe.
*/
while ((!o->stophid) && o->hasusb) {

then = ast_tvnow();
then = rpt_tvnow();
/* poll the pttkick pipe - timeout after 50 milliseconds */
res = ast_poll(rfds, 1, 50);
if (res < 0) {
Expand Down Expand Up @@ -1173,7 +1205,7 @@ static void *hidthread(void *arg)
}
lasttxtmp = o->lasttx;
o->lasttx = txreq;
time(&o->lasthidtime);
rpt_time(&o->lasthidtime);
/* Get the GPIO information */
j = buf[o->hid_gpio_loc];
/* If this device is a CM108AH, map the "HOOK" bit (which used to
Expand Down Expand Up @@ -1291,7 +1323,7 @@ static void *hidthread(void *arg)
}
}
}
j = ast_tvdiff_ms(ast_tvnow(), then);
j = ast_tvdiff_ms(rpt_tvnow(), then);
/* make output inversion mask (for pulseage) */
o->hid_gpio_lastmask = o->hid_gpio_pulsemask;
o->hid_gpio_pulsemask = 0;
Expand Down Expand Up @@ -1364,7 +1396,7 @@ static void *hidthread(void *arg)
memcpy(bufsave, buf, sizeof(buf));
ast_radio_hid_set_outputs(usb_handle, buf);
}
time(&o->lasthidtime);
rpt_time(&o->lasthidtime);
ast_mutex_unlock(&o->usblock);
}
o->lasttx = 0;
Expand Down Expand Up @@ -1847,7 +1879,7 @@ static int simpleusb_call(struct ast_channel *c, const char *dest, int timeout)
struct chan_simpleusb_pvt *o = ast_channel_tech_pvt(c);

o->stophid = 0;
time(&o->lasthidtime);
rpt_time(&o->lasthidtime);
ast_pthread_create_background(&o->hidthread, NULL, hidthread, o);
ast_setstate(c, AST_STATE_UP);
return 0;
Expand Down Expand Up @@ -1963,7 +1995,7 @@ static struct ast_frame *simpleusb_read(struct ast_channel *c)

/* check to the if the hid thread is still processing */
if (o->lasthidtime) {
time(&now);
rpt_time(&now);
if ((now - o->lasthidtime) > 3) {
ast_log(LOG_ERROR, "Channel %s: HID process has died or is not responding.\n", o->name);
return NULL;
Expand Down Expand Up @@ -2340,7 +2372,7 @@ static struct ast_frame *simpleusb_read(struct ast_channel *c)
return (f1);
}
if (f1->frametype == AST_FRAME_DTMF_END) {
f1->len = ast_tvdiff_ms(ast_tvnow(), o->tonetime);
f1->len = ast_tvdiff_ms(rpt_tvnow(), o->tonetime);
if (option_verbose) {
ast_log(LOG_NOTICE, "Channel %s: Got DTMF char %c duration %ld ms\n", o->name, f1->subclass.integer, f1->len);
}
Expand All @@ -2350,7 +2382,7 @@ static struct ast_frame *simpleusb_read(struct ast_channel *c)
ast_frfree(f1);
f1 = NULL;
} else {
o->tonetime = ast_tvnow();
o->tonetime = rpt_tvnow();
o->toneflag = 1;
}
}
Expand Down
58 changes: 45 additions & 13 deletions channels/chan_usbradio.c
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,38 @@ static struct ast_channel_tech usbradio_tech = {
.setoption = usbradio_setoption,
};

/*!
* \brief Get system monotonic
* This returns the CLOCK_MONOTONIC time
* \param second Pointer to time_t to receive the time.
*/
static void rpt_time(time_t *second)
{
struct timespec ts;

clock_gettime(CLOCK_MONOTONIC, &ts);

*second = ts.tv_sec;
}

/*!
* \brief Get system monotonic timeval
* This returns the CLOCK_MONOTONIC time as a timeval
* \retval timval structure with the current monotonic time.
*/
static struct timeval rpt_tvnow(void)
{
struct timeval tv;
struct timespec ts;

clock_gettime(CLOCK_MONOTONIC, &ts);

tv.tv_sec = ts.tv_sec;
tv.tv_usec = ts.tv_nsec / 1000;

return tv;
}

/*!
* \brief Configure our private structure based on the
* found hardware type.
Expand Down Expand Up @@ -679,12 +711,12 @@ static void *pulserthread(void *arg)
ast_mutex_lock(&pp_lock);
ast_radio_ppwrite(haspp, ppfd, pbase, pport, pp_val);
ast_mutex_unlock(&pp_lock);
then = ast_tvnow();
then = rpt_tvnow();

while (!stoppulser) {
usleep(50000);
ast_mutex_lock(&pp_lock);
now = ast_tvnow();
now = rpt_tvnow();
j = ast_tvdiff_ms(now, then);
then = now;
/* make output inversion mask (for pulseage) */
Expand Down Expand Up @@ -836,7 +868,7 @@ static void *hidthread(void *arg)
* with the usb hid device
*/
while (!o->stophid) {
time(&o->lasthidtime);
rpt_time(&o->lasthidtime);
ast_mutex_lock(&usb_dev_lock);
o->hasusb = 0;
o->usbass = 0;
Expand All @@ -855,7 +887,7 @@ static void *hidthread(void *arg)
* If no device string is specified, attempt to assign the first
* found device.
*/
time(&o->lasthidtime);
rpt_time(&o->lasthidtime);

/* Automatically assign a devstr if one was not specified in the configuration. */
if (ast_strlen_zero(o->devstr)) {
Expand Down Expand Up @@ -961,7 +993,7 @@ static void *hidthread(void *arg)
}
#endif
o->device_error = 0;
time(&o->lasthidtime);
rpt_time(&o->lasthidtime);
o->usbass = 1;
ast_mutex_unlock(&usb_dev_lock);
/* set the audio mixer values */
Expand Down Expand Up @@ -1154,15 +1186,15 @@ static void *hidthread(void *arg)
rfds[0].fd = o->pttkick[1];
rfds[0].events = POLLIN;

time(&o->lasthidtime);
rpt_time(&o->lasthidtime);
/* Main processing loop for GPIO
* This loop process every 50 milliseconds.
* The timer can be interupted by writing to
* the pttkick pipe.
*/
while ((!o->stophid) && o->hasusb) {

then = ast_tvnow();
then = rpt_tvnow();
/* poll the pttkick pipe - timeout after 50 milliseconds */
res = ast_poll(rfds, 1, 50);
if (res < 0) {
Expand Down Expand Up @@ -1344,7 +1376,7 @@ static void *hidthread(void *arg)
}
}
}
j = ast_tvdiff_ms(ast_tvnow(), then);
j = ast_tvdiff_ms(rpt_tvnow(), then);
/* make output inversion mask (for pulseage) */
o->hid_gpio_lastmask = o->hid_gpio_pulsemask;
o->hid_gpio_pulsemask = 0;
Expand Down Expand Up @@ -1421,7 +1453,7 @@ static void *hidthread(void *arg)
memcpy(bufsave, buf, sizeof(buf));
ast_radio_hid_set_outputs(usb_handle, buf);
}
time(&o->lasthidtime);
rpt_time(&o->lasthidtime);
ast_mutex_unlock(&o->usblock);
}
lasttxtmp = o->pmrChan->txPttOut = 0;
Expand Down Expand Up @@ -1833,7 +1865,7 @@ static int usbradio_call(struct ast_channel *c, const char *dest, int timeout)
struct chan_usbradio_pvt *o = ast_channel_tech_pvt(c);

o->stophid = 0;
time(&o->lasthidtime);
rpt_time(&o->lasthidtime);
ast_pthread_create_background(&o->hidthread, NULL, hidthread, o);
ast_setstate(c, AST_STATE_UP);
return 0;
Expand Down Expand Up @@ -1937,7 +1969,7 @@ static struct ast_frame *usbradio_read(struct ast_channel *c)

/* check to the if the hid thread is still processing */
if (o->lasthidtime) {
time(&now);
rpt_time(&now);
if ((now - o->lasthidtime) > 3) {
ast_log(LOG_ERROR, "Channel %s: HID process has died or is not responding.\n", o->name);
return NULL;
Expand Down Expand Up @@ -2334,7 +2366,7 @@ static struct ast_frame *usbradio_read(struct ast_channel *c)
return (f1);
}
if (f1->frametype == AST_FRAME_DTMF_END) {
f1->len = ast_tvdiff_ms(ast_tvnow(), o->tonetime);
f1->len = ast_tvdiff_ms(rpt_tvnow(), o->tonetime);
if (option_verbose) {
ast_log(LOG_NOTICE, "Channel %s: Got DTMF char %c duration %ld ms\n", o->name, f1->subclass.integer, f1->len);
}
Expand All @@ -2344,7 +2376,7 @@ static struct ast_frame *usbradio_read(struct ast_channel *c)
ast_frfree(f1);
f1 = NULL;
} else {
o->tonetime = ast_tvnow();
o->tonetime = rpt_tvnow();
o->toneflag = 1;
}
}
Expand Down

0 comments on commit 34681d3

Please sign in to comment.