SDR: Fixed stack overflow by allocating memory instead of local buffers
This commit is contained in:
117
src/common/sdr.c
117
src/common/sdr.c
@@ -59,6 +59,11 @@ typedef struct sdr {
|
|||||||
wave_rec_t wave_tx_rec;
|
wave_rec_t wave_tx_rec;
|
||||||
wave_play_t wave_rx_play;
|
wave_play_t wave_rx_play;
|
||||||
wave_play_t wave_tx_play;
|
wave_play_t wave_tx_play;
|
||||||
|
float *modbuff; /* buffer for FM transmodulation */
|
||||||
|
sample_t *modbuff_I;
|
||||||
|
sample_t *modbuff_Q;
|
||||||
|
sample_t *wavespl0; /* sample buffer for wave generation */
|
||||||
|
sample_t *wavespl1;
|
||||||
} sdr_t;
|
} sdr_t;
|
||||||
|
|
||||||
typedef struct sdr_thread {
|
typedef struct sdr_thread {
|
||||||
@@ -66,6 +71,7 @@ typedef struct sdr_thread {
|
|||||||
volatile int running, exit; /* flags to control exit of threads */
|
volatile int running, exit; /* flags to control exit of threads */
|
||||||
int buffer_size;
|
int buffer_size;
|
||||||
volatile float *buffer;
|
volatile float *buffer;
|
||||||
|
float *buffer2;
|
||||||
volatile int in, out; /* in and out pointers (atomic, so no locking required) */
|
volatile int in, out; /* in and out pointers (atomic, so no locking required) */
|
||||||
int max_fill; /* measure maximum buffer fill */
|
int max_fill; /* measure maximum buffer fill */
|
||||||
double max_fill_timer; /* timer to display/reset maximum fill */
|
double max_fill_timer; /* timer to display/reset maximum fill */
|
||||||
@@ -140,6 +146,7 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
|
|||||||
sdr_oversample = sdr_samplerate / samplerate;
|
sdr_oversample = sdr_samplerate / samplerate;
|
||||||
sdr_threads = 1;
|
sdr_threads = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sdr_threads) {
|
if (sdr_threads) {
|
||||||
memset(&sdr_thread_read, 0, sizeof(sdr_thread_read));
|
memset(&sdr_thread_read, 0, sizeof(sdr_thread_read));
|
||||||
sdr_thread_read.buffer_size = sdr_latspl * 2 * sdr_oversample + 2;
|
sdr_thread_read.buffer_size = sdr_latspl * 2 * sdr_oversample + 2;
|
||||||
@@ -148,6 +155,11 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
|
|||||||
PDEBUG(DSDR, DEBUG_ERROR, "No mem!\n");
|
PDEBUG(DSDR, DEBUG_ERROR, "No mem!\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
sdr_thread_read.buffer2 = calloc(sdr_thread_read.buffer_size, sizeof(*sdr_thread_read.buffer2));
|
||||||
|
if (!sdr_thread_read.buffer2) {
|
||||||
|
PDEBUG(DSDR, DEBUG_ERROR, "No mem!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
sdr_thread_read.in = sdr_thread_read.out = 0;
|
sdr_thread_read.in = sdr_thread_read.out = 0;
|
||||||
memset(&sdr_thread_write, 0, sizeof(sdr_thread_write));
|
memset(&sdr_thread_write, 0, sizeof(sdr_thread_write));
|
||||||
sdr_thread_write.buffer_size = sdr_latspl * 2 + 2;
|
sdr_thread_write.buffer_size = sdr_latspl * 2 + 2;
|
||||||
@@ -156,6 +168,11 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
|
|||||||
PDEBUG(DSDR, DEBUG_ERROR, "No mem!\n");
|
PDEBUG(DSDR, DEBUG_ERROR, "No mem!\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
sdr_thread_write.buffer2 = calloc(sdr_thread_write.buffer_size * sdr_oversample, sizeof(*sdr_thread_write.buffer2));
|
||||||
|
if (!sdr_thread_write.buffer2) {
|
||||||
|
PDEBUG(DSDR, DEBUG_ERROR, "No mem!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
sdr_thread_write.in = sdr_thread_write.out = 0;
|
sdr_thread_write.in = sdr_thread_write.out = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,6 +196,33 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
|
|||||||
sdr->amplitude = 1.0 / (double)channels;
|
sdr->amplitude = 1.0 / (double)channels;
|
||||||
sdr->samplerate = samplerate;
|
sdr->samplerate = samplerate;
|
||||||
|
|
||||||
|
/* alloc fm modulation buffers */
|
||||||
|
sdr->modbuff = calloc(sdr_latspl * 2, sizeof(*sdr->modbuff));
|
||||||
|
if (!sdr->modbuff) {
|
||||||
|
PDEBUG(DSDR, DEBUG_ERROR, "NO MEM!\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
sdr->modbuff_I = calloc(sdr_latspl, sizeof(*sdr->modbuff_I));
|
||||||
|
if (!sdr->modbuff_I) {
|
||||||
|
PDEBUG(DSDR, DEBUG_ERROR, "NO MEM!\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
sdr->modbuff_Q = calloc(sdr_latspl, sizeof(*sdr->modbuff_Q));
|
||||||
|
if (!sdr->modbuff_Q) {
|
||||||
|
PDEBUG(DSDR, DEBUG_ERROR, "NO MEM!\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
sdr->wavespl0 = calloc(sdr_latspl, sizeof(*sdr->wavespl0));
|
||||||
|
if (!sdr->wavespl0) {
|
||||||
|
PDEBUG(DSDR, DEBUG_ERROR, "NO MEM!\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
sdr->wavespl1 = calloc(sdr_latspl, sizeof(*sdr->wavespl1));
|
||||||
|
if (!sdr->wavespl1) {
|
||||||
|
PDEBUG(DSDR, DEBUG_ERROR, "NO MEM!\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
/* special case where we use a paging frequency */
|
/* special case where we use a paging frequency */
|
||||||
if (paging_frequency) {
|
if (paging_frequency) {
|
||||||
/* add extra paging channel */
|
/* add extra paging channel */
|
||||||
@@ -372,25 +416,24 @@ static void *sdr_write_child(void __attribute__((__unused__)) *arg)
|
|||||||
}
|
}
|
||||||
num = fill / 2;
|
num = fill / 2;
|
||||||
if (num) {
|
if (num) {
|
||||||
float buff[num * 2 * sdr_oversample];
|
|
||||||
#ifdef DEBUG_BUFFER
|
#ifdef DEBUG_BUFFER
|
||||||
printf("Thread found %d samples in write buffer and forwards them to SDR.\n", num);
|
printf("Thread found %d samples in write buffer and forwards them to SDR.\n", num);
|
||||||
#endif
|
#endif
|
||||||
out = sdr_thread_write.out;
|
out = sdr_thread_write.out;
|
||||||
for (s = 0, ss = 0; s < num; s++) {
|
for (s = 0, ss = 0; s < num; s++) {
|
||||||
for (o = 0; o < sdr_oversample; o++) {
|
for (o = 0; o < sdr_oversample; o++) {
|
||||||
buff[ss++] = sdr_thread_write.buffer[out];
|
sdr_thread_write.buffer2[ss++] = sdr_thread_write.buffer[out];
|
||||||
buff[ss++] = sdr_thread_write.buffer[out + 1];
|
sdr_thread_write.buffer2[ss++] = sdr_thread_write.buffer[out + 1];
|
||||||
}
|
}
|
||||||
out = (out + 2) % sdr_thread_write.buffer_size;
|
out = (out + 2) % sdr_thread_write.buffer_size;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_UHD
|
#ifdef HAVE_UHD
|
||||||
if (sdr_use_uhd)
|
if (sdr_use_uhd)
|
||||||
uhd_send(buff, num * sdr_oversample);
|
uhd_send(sdr_thread_write.buffer2, num * sdr_oversample);
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_SOAPY
|
#ifdef HAVE_SOAPY
|
||||||
if (sdr_use_soapy)
|
if (sdr_use_soapy)
|
||||||
soapy_send(buff, num * sdr_oversample);
|
soapy_send(sdr_thread_write.buffer2, num * sdr_oversample);
|
||||||
#endif
|
#endif
|
||||||
sdr_thread_write.out = out;
|
sdr_thread_write.out = out;
|
||||||
}
|
}
|
||||||
@@ -416,14 +459,13 @@ static void *sdr_read_child(void __attribute__((__unused__)) *arg)
|
|||||||
space = (sdr_thread_read.out - sdr_thread_read.in - 2 + sdr_thread_read.buffer_size) % sdr_thread_read.buffer_size;
|
space = (sdr_thread_read.out - sdr_thread_read.in - 2 + sdr_thread_read.buffer_size) % sdr_thread_read.buffer_size;
|
||||||
num = space / 2;
|
num = space / 2;
|
||||||
if (num) {
|
if (num) {
|
||||||
float buff[num * 2];
|
|
||||||
#ifdef HAVE_UHD
|
#ifdef HAVE_UHD
|
||||||
if (sdr_use_uhd)
|
if (sdr_use_uhd)
|
||||||
count = uhd_receive(buff, num);
|
count = uhd_receive(sdr_thread_read.buffer2, num);
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_SOAPY
|
#ifdef HAVE_SOAPY
|
||||||
if (sdr_use_soapy)
|
if (sdr_use_soapy)
|
||||||
count = soapy_receive(buff, num);
|
count = soapy_receive(sdr_thread_read.buffer2, num);
|
||||||
#endif
|
#endif
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
#ifdef DEBUG_BUFFER
|
#ifdef DEBUG_BUFFER
|
||||||
@@ -431,8 +473,8 @@ static void *sdr_read_child(void __attribute__((__unused__)) *arg)
|
|||||||
#endif
|
#endif
|
||||||
in = sdr_thread_read.in;
|
in = sdr_thread_read.in;
|
||||||
for (s = 0, ss = 0; s < count; s++) {
|
for (s = 0, ss = 0; s < count; s++) {
|
||||||
sdr_thread_read.buffer[in++] = buff[ss++];
|
sdr_thread_read.buffer[in++] = sdr_thread_read.buffer2[ss++];
|
||||||
sdr_thread_read.buffer[in++] = buff[ss++];
|
sdr_thread_read.buffer[in++] = sdr_thread_read.buffer2[ss++];
|
||||||
in %= sdr_thread_read.buffer_size;
|
in %= sdr_thread_read.buffer_size;
|
||||||
}
|
}
|
||||||
sdr_thread_read.in = in;
|
sdr_thread_read.in = in;
|
||||||
@@ -523,8 +565,12 @@ void sdr_close(void *inst)
|
|||||||
|
|
||||||
if (sdr_thread_read.buffer)
|
if (sdr_thread_read.buffer)
|
||||||
free((void *)sdr_thread_read.buffer);
|
free((void *)sdr_thread_read.buffer);
|
||||||
|
if (sdr_thread_read.buffer2)
|
||||||
|
free((void *)sdr_thread_read.buffer2);
|
||||||
if (sdr_thread_write.buffer)
|
if (sdr_thread_write.buffer)
|
||||||
free((void *)sdr_thread_write.buffer);
|
free((void *)sdr_thread_write.buffer);
|
||||||
|
if (sdr_thread_write.buffer2)
|
||||||
|
free((void *)sdr_thread_write.buffer2);
|
||||||
|
|
||||||
#ifdef HAVE_UHD
|
#ifdef HAVE_UHD
|
||||||
if (sdr_use_uhd)
|
if (sdr_use_uhd)
|
||||||
@@ -537,6 +583,11 @@ void sdr_close(void *inst)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (sdr) {
|
if (sdr) {
|
||||||
|
free(sdr->modbuff);
|
||||||
|
free(sdr->modbuff_I);
|
||||||
|
free(sdr->modbuff_Q);
|
||||||
|
free(sdr->wavespl0);
|
||||||
|
free(sdr->wavespl1);
|
||||||
wave_destroy_record(&sdr->wave_rx_rec);
|
wave_destroy_record(&sdr->wave_rx_rec);
|
||||||
wave_destroy_record(&sdr->wave_tx_rec);
|
wave_destroy_record(&sdr->wave_tx_rec);
|
||||||
wave_destroy_playback(&sdr->wave_rx_play);
|
wave_destroy_playback(&sdr->wave_rx_play);
|
||||||
@@ -560,10 +611,14 @@ void sdr_close(void *inst)
|
|||||||
int sdr_write(void *inst, sample_t **samples, uint8_t **power, int num, enum paging_signal __attribute__((unused)) *paging_signal, int *on, int channels)
|
int sdr_write(void *inst, sample_t **samples, uint8_t **power, int num, enum paging_signal __attribute__((unused)) *paging_signal, int *on, int channels)
|
||||||
{
|
{
|
||||||
sdr_t *sdr = (sdr_t *)inst;
|
sdr_t *sdr = (sdr_t *)inst;
|
||||||
float buffer[num * 2], *buff = NULL;
|
float *buff = NULL;
|
||||||
int c, s, ss;
|
int c, s, ss;
|
||||||
int sent = 0;
|
int sent = 0;
|
||||||
|
|
||||||
|
if (num > sdr_latspl) {
|
||||||
|
fprintf(stderr, "exceeding maximum size given by sdr_latspl, please fix!\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
if (channels != sdr->channels && channels != 0) {
|
if (channels != sdr->channels && channels != 0) {
|
||||||
PDEBUG(DSDR, DEBUG_ERROR, "Invalid number of channels, please fix!\n");
|
PDEBUG(DSDR, DEBUG_ERROR, "Invalid number of channels, please fix!\n");
|
||||||
abort();
|
abort();
|
||||||
@@ -571,8 +626,8 @@ int sdr_write(void *inst, sample_t **samples, uint8_t **power, int num, enum pag
|
|||||||
|
|
||||||
/* process all channels */
|
/* process all channels */
|
||||||
if (channels) {
|
if (channels) {
|
||||||
memset(buffer, 0, sizeof(buffer));
|
buff = sdr->modbuff;
|
||||||
buff = buffer;
|
memset(buff, 0, sizeof(*buff) * num * 2);
|
||||||
for (c = 0; c < channels; c++) {
|
for (c = 0; c < channels; c++) {
|
||||||
/* switch to paging channel, if requested */
|
/* switch to paging channel, if requested */
|
||||||
if (on[c] && sdr->paging_channel)
|
if (on[c] && sdr->paging_channel)
|
||||||
@@ -585,19 +640,19 @@ int sdr_write(void *inst, sample_t **samples, uint8_t **power, int num, enum pag
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sdr->wave_tx_rec.fp) {
|
if (sdr->wave_tx_rec.fp) {
|
||||||
sample_t spl[2][num], *spl_list[2] = { spl[0], spl[1] };
|
sample_t *spl_list[2] = { sdr->wavespl0, sdr->wavespl1 };
|
||||||
for (s = 0, ss = 0; s < num; s++) {
|
for (s = 0, ss = 0; s < num; s++) {
|
||||||
spl[0][s] = buff[ss++];
|
spl_list[0][s] = buff[ss++];
|
||||||
spl[1][s] = buff[ss++];
|
spl_list[1][s] = buff[ss++];
|
||||||
}
|
}
|
||||||
wave_write(&sdr->wave_tx_rec, spl_list, num);
|
wave_write(&sdr->wave_tx_rec, spl_list, num);
|
||||||
}
|
}
|
||||||
if (sdr->wave_tx_play.fp) {
|
if (sdr->wave_tx_play.fp) {
|
||||||
sample_t spl[2][num], *spl_list[2] = { spl[0], spl[1] };
|
sample_t *spl_list[2] = { sdr->wavespl0, sdr->wavespl1 };
|
||||||
wave_read(&sdr->wave_tx_play, spl_list, num);
|
wave_read(&sdr->wave_tx_play, spl_list, num);
|
||||||
for (s = 0, ss = 0; s < num; s++) {
|
for (s = 0, ss = 0; s < num; s++) {
|
||||||
buff[ss++] = spl[0][s];
|
buff[ss++] = spl_list[0][s];
|
||||||
buff[ss++] = spl[1][s];
|
buff[ss++] = spl_list[1][s];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -640,13 +695,17 @@ int sdr_write(void *inst, sample_t **samples, uint8_t **power, int num, enum pag
|
|||||||
int sdr_read(void *inst, sample_t **samples, int num, int channels)
|
int sdr_read(void *inst, sample_t **samples, int num, int channels)
|
||||||
{
|
{
|
||||||
sdr_t *sdr = (sdr_t *)inst;
|
sdr_t *sdr = (sdr_t *)inst;
|
||||||
float buffer[num * 2], *buff = NULL;
|
float *buff = NULL;
|
||||||
sample_t I[num], Q[num];
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int c, s, ss;
|
int c, s, ss;
|
||||||
|
|
||||||
|
if (num > sdr_latspl) {
|
||||||
|
fprintf(stderr, "exceeding maximum size given by sdr_latspl, please fix!\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
if (channels) {
|
if (channels) {
|
||||||
buff = buffer;
|
buff = sdr->modbuff;
|
||||||
} else {
|
} else {
|
||||||
buff = (float *)samples;
|
buff = (float *)samples;
|
||||||
}
|
}
|
||||||
@@ -694,19 +753,19 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sdr->wave_rx_rec.fp) {
|
if (sdr->wave_rx_rec.fp) {
|
||||||
sample_t spl[2][count], *spl_list[2] = { spl[0], spl[1] };
|
sample_t *spl_list[2] = { sdr->wavespl0, sdr->wavespl1 };
|
||||||
for (s = 0, ss = 0; s < count; s++) {
|
for (s = 0, ss = 0; s < count; s++) {
|
||||||
spl[0][s] = buff[ss++];
|
spl_list[0][s] = buff[ss++];
|
||||||
spl[1][s] = buff[ss++];
|
spl_list[1][s] = buff[ss++];
|
||||||
}
|
}
|
||||||
wave_write(&sdr->wave_rx_rec, spl_list, count);
|
wave_write(&sdr->wave_rx_rec, spl_list, count);
|
||||||
}
|
}
|
||||||
if (sdr->wave_rx_play.fp) {
|
if (sdr->wave_rx_play.fp) {
|
||||||
sample_t spl[2][count], *spl_list[2] = { spl[0], spl[1] };
|
sample_t *spl_list[2] = { sdr->wavespl0, sdr->wavespl1 };
|
||||||
wave_read(&sdr->wave_rx_play, spl_list, count);
|
wave_read(&sdr->wave_rx_play, spl_list, count);
|
||||||
for (s = 0, ss = 0; s < count; s++) {
|
for (s = 0, ss = 0; s < count; s++) {
|
||||||
buff[ss++] = spl[0][s];
|
buff[ss++] = spl_list[0][s];
|
||||||
buff[ss++] = spl[1][s];
|
buff[ss++] = spl_list[1][s];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
display_iq(buff, count);
|
display_iq(buff, count);
|
||||||
@@ -714,7 +773,7 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels)
|
|||||||
|
|
||||||
if (channels) {
|
if (channels) {
|
||||||
for (c = 0; c < channels; c++)
|
for (c = 0; c < channels; c++)
|
||||||
fm_demodulate_complex(&sdr->chan[c].demod, samples[c], count, buff, I, Q);
|
fm_demodulate_complex(&sdr->chan[c].demod, samples[c], count, buff, sdr->modbuff_I, sdr->modbuff_Q);
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
Reference in New Issue
Block a user