aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2017-08-27 10:49:19 +0200
committerAndreas Eversberg <jolly@eversberg.eu>2017-09-01 18:42:52 +0200
commit05c516ca16671bd34692ca220879be7c0d344d11 (patch)
tree92acec8fa5a52a9a8253697a3260eea28b7aaabf
parenteb0c12343389228d69d5e9a4faf779098debeba9 (diff)
SDR: Fixed stack overflow by allocating memory instead of local buffers
-rw-r--r--src/common/sdr.c117
1 files changed, 88 insertions, 29 deletions
diff --git a/src/common/sdr.c b/src/common/sdr.c
index ea873c1..d4c2e88 100644
--- a/src/common/sdr.c
+++ b/src/common/sdr.c
@@ -59,6 +59,11 @@ typedef struct sdr {
wave_rec_t wave_tx_rec;
wave_play_t wave_rx_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;
typedef struct sdr_thread {
@@ -66,6 +71,7 @@ typedef struct sdr_thread {
volatile int running, exit; /* flags to control exit of threads */
int buffer_size;
volatile float *buffer;
+ float *buffer2;
volatile int in, out; /* in and out pointers (atomic, so no locking required) */
int max_fill; /* measure maximum buffer 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_threads = 1;
}
+
if (sdr_threads) {
memset(&sdr_thread_read, 0, sizeof(sdr_thread_read));
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");
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;
memset(&sdr_thread_write, 0, sizeof(sdr_thread_write));
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");
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;
}
@@ -179,6 +196,33 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
sdr->amplitude = 1.0 / (double)channels;
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 */
if (paging_frequency) {
/* add extra paging channel */
@@ -372,25 +416,24 @@ static void *sdr_write_child(void __attribute__((__unused__)) *arg)
}
num = fill / 2;
if (num) {
- float buff[num * 2 * sdr_oversample];
#ifdef DEBUG_BUFFER
printf("Thread found %d samples in write buffer and forwards them to SDR.\n", num);
#endif
out = sdr_thread_write.out;
for (s = 0, ss = 0; s < num; s++) {
for (o = 0; o < sdr_oversample; o++) {
- buff[ss++] = sdr_thread_write.buffer[out];
- buff[ss++] = sdr_thread_write.buffer[out + 1];
+ sdr_thread_write.buffer2[ss++] = sdr_thread_write.buffer[out];
+ sdr_thread_write.buffer2[ss++] = sdr_thread_write.buffer[out + 1];
}
out = (out + 2) % sdr_thread_write.buffer_size;
}
#ifdef HAVE_UHD
if (sdr_use_uhd)
- uhd_send(buff, num * sdr_oversample);
+ uhd_send(sdr_thread_write.buffer2, num * sdr_oversample);
#endif
#ifdef HAVE_SOAPY
if (sdr_use_soapy)
- soapy_send(buff, num * sdr_oversample);
+ soapy_send(sdr_thread_write.buffer2, num * sdr_oversample);
#endif
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;
num = space / 2;
if (num) {
- float buff[num * 2];
#ifdef HAVE_UHD
if (sdr_use_uhd)
- count = uhd_receive(buff, num);
+ count = uhd_receive(sdr_thread_read.buffer2, num);
#endif
#ifdef HAVE_SOAPY
if (sdr_use_soapy)
- count = soapy_receive(buff, num);
+ count = soapy_receive(sdr_thread_read.buffer2, num);
#endif
if (count > 0) {
#ifdef DEBUG_BUFFER
@@ -431,8 +473,8 @@ static void *sdr_read_child(void __attribute__((__unused__)) *arg)
#endif
in = sdr_thread_read.in;
for (s = 0, ss = 0; s < count; s++) {
- sdr_thread_read.buffer[in++] = buff[ss++];
- sdr_thread_read.buffer[in++] = buff[ss++];
+ sdr_thread_read.buffer[in++] = sdr_thread_read.buffer2[ss++];
+ sdr_thread_read.buffer[in++] = sdr_thread_read.buffer2[ss++];
in %= sdr_thread_read.buffer_size;
}
sdr_thread_read.in = in;
@@ -523,8 +565,12 @@ void sdr_close(void *inst)
if (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)
free((void *)sdr_thread_write.buffer);
+ if (sdr_thread_write.buffer2)
+ free((void *)sdr_thread_write.buffer2);
#ifdef HAVE_UHD
if (sdr_use_uhd)
@@ -537,6 +583,11 @@ void sdr_close(void *inst)
#endif
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_tx_rec);
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)
{
sdr_t *sdr = (sdr_t *)inst;
- float buffer[num * 2], *buff = NULL;
+ float *buff = NULL;
int c, s, ss;
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) {
PDEBUG(DSDR, DEBUG_ERROR, "Invalid number of channels, please fix!\n");
abort();
@@ -571,8 +626,8 @@ int sdr_write(void *inst, sample_t **samples, uint8_t **power, int num, enum pag
/* process all channels */
if (channels) {
- memset(buffer, 0, sizeof(buffer));
- buff = buffer;
+ buff = sdr->modbuff;
+ memset(buff, 0, sizeof(*buff) * num * 2);
for (c = 0; c < channels; c++) {
/* switch to paging channel, if requested */
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) {
- 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++) {
- spl[0][s] = buff[ss++];
- spl[1][s] = buff[ss++];
+ spl_list[0][s] = buff[ss++];
+ spl_list[1][s] = buff[ss++];
}
wave_write(&sdr->wave_tx_rec, spl_list, num);
}
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);
for (s = 0, ss = 0; s < num; s++) {
- buff[ss++] = spl[0][s];
- buff[ss++] = spl[1][s];
+ buff[ss++] = spl_list[0][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)
{
sdr_t *sdr = (sdr_t *)inst;
- float buffer[num * 2], *buff = NULL;
- sample_t I[num], Q[num];
+ float *buff = NULL;
int count = 0;
int c, s, ss;
+ if (num > sdr_latspl) {
+ fprintf(stderr, "exceeding maximum size given by sdr_latspl, please fix!\n");
+ abort();
+ }
+
if (channels) {
- buff = buffer;
+ buff = sdr->modbuff;
} else {
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) {
- 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++) {
- spl[0][s] = buff[ss++];
- spl[1][s] = buff[ss++];
+ spl_list[0][s] = buff[ss++];
+ spl_list[1][s] = buff[ss++];
}
wave_write(&sdr->wave_rx_rec, spl_list, count);
}
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);
for (s = 0, ss = 0; s < count; s++) {
- buff[ss++] = spl[0][s];
- buff[ss++] = spl[1][s];
+ buff[ss++] = spl_list[0][s];
+ buff[ss++] = spl_list[1][s];
}
}
display_iq(buff, count);
@@ -714,7 +773,7 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels)
if (channels) {
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;