Files
sdrangel/plugins/samplesource/androidsdrdriverinput/androidsdrdriverinputtcphandler.cpp
T
Robin Getz c2b30d4fa8 tree wide: Fix message ownership and reporting for unhandled queue messages
MessageQueue::pop() transfers ownership of the popped message to the
caller, but many handleInputMessages() implementations only deleted
the message when handleMessage() returned true. When a message was not
handled, ownership had already been transferred from the queue and the
message was leaked.

This was identified while investigating an ASAN leak in the audio
subsystem.

Update the applicable handleInputMessages() implementations to always
delete messages after handleMessage() returns. Unhandled messages are
also logged with the component and message identifier so unexpected
message routing is visible during debugging.

This change:
- Ensures every message popped from a queue has its ownership resolved.
- Prevents leaks when handleMessage() returns false.
- Makes unhandled messages visible instead of silently discarding them.
- Preserves the existing message handling logic and does not require
  components to handle message types that are legitimately irrelevant
  to them.

The changes are intentionally mechanical and limited to the common
message queue ownership and diagnostic pattern.

Signed-off-by: Robin Getz <rgetz503@gmail.com>
2026-09-25 23:49:05 -04:00

764 lines
26 KiB
C++

///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022-2023 Jon Beniston, M7RCE <jon@beniston.com> //
// Copyright (C) 2022 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
// Copyright (C) 2022 Jiří Pinkava <jiri.pinkava@rossum.ai> //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QUdpSocket>
#include <QDebug>
#include "device/deviceapi.h"
#include "androidsdrdriverinputtcphandler.h"
#include "androidsdrdriverinput.h"
#include "../../channelrx/remotetcpsink/remotetcpprotocol.h"
MESSAGE_CLASS_DEFINITION(AndroidSDRDriverInputTCPHandler::MsgReportRemoteDevice, Message)
MESSAGE_CLASS_DEFINITION(AndroidSDRDriverInputTCPHandler::MsgReportConnection, Message)
MESSAGE_CLASS_DEFINITION(AndroidSDRDriverInputTCPHandler::MsgConfigureTcpHandler, Message)
AndroidSDRDriverInputTCPHandler::AndroidSDRDriverInputTCPHandler(SampleSinkFifo *sampleFifo, DeviceAPI *deviceAPI) :
m_deviceAPI(deviceAPI),
m_running(false),
m_dataSocket(nullptr),
m_tcpBuf(nullptr),
m_sampleFifo(sampleFifo),
m_messageQueueToGUI(0),
m_fillBuffer(true),
m_reconnectTimer(this),
m_rsp0(false),
m_converterBuffer(nullptr),
m_converterBufferNbSamples(0),
m_settings()
{
m_tcpBuf = new char[m_sampleFifo->size()*2*4];
connect(&m_reconnectTimer, SIGNAL(timeout()), this, SLOT(reconnect()));
m_reconnectTimer.setSingleShot(true);
}
AndroidSDRDriverInputTCPHandler::~AndroidSDRDriverInputTCPHandler()
{
delete[] m_tcpBuf;
if (m_converterBuffer) {
delete[] m_converterBuffer;
}
cleanup();
}
void AndroidSDRDriverInputTCPHandler::reset()
{
QMutexLocker mutexLocker(&m_mutex);
m_inputMessageQueue.clear();
}
void AndroidSDRDriverInputTCPHandler::start()
{
QMutexLocker mutexLocker(&m_mutex);
qDebug("AndroidSDRDriverInputTCPHandler::start");
if (m_running) {
return;
}
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
connect(thread(), SIGNAL(started()), this, SLOT(started()));
connect(thread(), SIGNAL(finished()), this, SLOT(finished()));
m_running = true;
}
void AndroidSDRDriverInputTCPHandler::stop()
{
QMutexLocker mutexLocker(&m_mutex);
qDebug("AndroidSDRDriverInputTCPHandler::stop");
disconnect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
}
void AndroidSDRDriverInputTCPHandler::started()
{
QMutexLocker mutexLocker(&m_mutex);
disconnect(thread(), SIGNAL(started()), this, SLOT(started()));
}
void AndroidSDRDriverInputTCPHandler::finished()
{
QMutexLocker mutexLocker(&m_mutex);
disconnectFromHost();
disconnect(thread(), SIGNAL(finished()), this, SLOT(finished()));
m_running = false;
}
void AndroidSDRDriverInputTCPHandler::connectToHost(const QString& address, quint16 port)
{
qDebug("AndroidSDRDriverInputTCPHandler::connectToHost: connect to %s:%d", address.toStdString().c_str(), port);
m_dataSocket = new QTcpSocket(this);
m_fillBuffer = true;
m_readMetaData = false;
connect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(dataReadyRead()));
connect(m_dataSocket, SIGNAL(connected()), this, SLOT(connected()));
connect(m_dataSocket, SIGNAL(disconnected()), this, SLOT(disconnected()));
connect(m_dataSocket, &QAbstractSocket::errorOccurred, this, &AndroidSDRDriverInputTCPHandler::errorOccurred);
m_dataSocket->connectToHost(address, port);
}
void AndroidSDRDriverInputTCPHandler::disconnectFromHost()
{
if (m_dataSocket)
{
qDebug() << "AndroidSDRDriverInputTCPHandler::disconnectFromHost";
disconnect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(dataReadyRead()));
disconnect(m_dataSocket, SIGNAL(connected()), this, SLOT(connected()));
disconnect(m_dataSocket, SIGNAL(disconnected()), this, SLOT(disconnected()));
disconnect(m_dataSocket, &QAbstractSocket::errorOccurred, this, &AndroidSDRDriverInputTCPHandler::errorOccurred);
m_dataSocket->disconnectFromHost();
cleanup();
}
}
void AndroidSDRDriverInputTCPHandler::cleanup()
{
if (m_dataSocket)
{
m_dataSocket->deleteLater();
m_dataSocket = nullptr;
}
}
// Clear input buffer when settings change that invalidate the data in it
// E.g. sample rate or bit depth
void AndroidSDRDriverInputTCPHandler::clearBuffer()
{
if (m_dataSocket)
{
m_dataSocket->flush();
m_dataSocket->readAll();
m_fillBuffer = true;
}
}
void AndroidSDRDriverInputTCPHandler::setSampleRate(int sampleRate)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setSampleRate;
RemoteTCPProtocol::encodeUInt32(&request[1], sampleRate);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setCenterFrequency(quint64 frequency)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setCenterFrequency;
RemoteTCPProtocol::encodeUInt32(&request[1], frequency);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setTunerAGC(bool agc)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setTunerGainMode;
RemoteTCPProtocol::encodeUInt32(&request[1], agc);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setTunerGain(int gain)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setTunerGain;
RemoteTCPProtocol::encodeUInt32(&request[1], gain);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setFreqCorrection(int correction)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setFrequencyCorrection;
RemoteTCPProtocol::encodeUInt32(&request[1], correction);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setIFGain(quint16 stage, quint16 gain)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setTunerIFGain;
RemoteTCPProtocol::encodeUInt32(&request[1], (stage << 16) | gain);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setAGC(bool agc)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setAGCMode;
RemoteTCPProtocol::encodeUInt32(&request[1], agc);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setDirectSampling(bool enabled)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setDirectSampling;
RemoteTCPProtocol::encodeUInt32(&request[1], enabled);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setDCOffsetRemoval(bool enabled)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setDCOffsetRemoval;
RemoteTCPProtocol::encodeUInt32(&request[1], enabled);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setIQCorrection(bool enabled)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setIQCorrection;
RemoteTCPProtocol::encodeUInt32(&request[1], enabled);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setBiasTee(bool enabled)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setBiasTee;
RemoteTCPProtocol::encodeUInt32(&request[1], enabled);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setBandwidth(int bandwidth)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setTunerBandwidth;
RemoteTCPProtocol::encodeUInt32(&request[1], bandwidth);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setDecimation(int dec)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setDecimation;
RemoteTCPProtocol::encodeUInt32(&request[1], dec);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setChannelSampleRate(int sampleRate)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setChannelSampleRate;
RemoteTCPProtocol::encodeUInt32(&request[1], sampleRate);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setSampleBitDepth(int sampleBits)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setSampleBitDepth;
RemoteTCPProtocol::encodeUInt32(&request[1], sampleBits);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setAndroidGainByPercentage(int gain)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::androidGainByPercentage;
RemoteTCPProtocol::encodeUInt32(&request[1], gain);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setAndroidEnable16BitSigned(bool enable)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::androidEnable16BitSigned;
RemoteTCPProtocol::encodeUInt32(&request[1], enable);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::rspSetAGC(bool agc)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::rspSetAGC;
RemoteTCPProtocol::encodeUInt32(&request[1], agc);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::rspSetIfGainR(int gain)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::rspSetIfGainR;
RemoteTCPProtocol::encodeUInt32(&request[1], gain);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::rspSetLNAState(int state)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::rspSetLNAState;
RemoteTCPProtocol::encodeUInt32(&request[1], state);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::applySettings(const AndroidSDRDriverInputSettings& settings, const QList<QString>& settingsKeys, bool force)
{
qDebug() << "AndroidSDRDriverInputTCPHandler::applySettings: "
<< "force: " << force
<< settings.getDebugString(settingsKeys, force);
QMutexLocker mutexLocker(&m_mutex);
if (settingsKeys.contains("centerFrequency") || force) {
setCenterFrequency(settings.m_centerFrequency);
}
if (settingsKeys.contains("loPpmCorrection") || force) {
setFreqCorrection(settings.m_loPpmCorrection);
}
if (settingsKeys.contains("dcBlock") || force) {
setDCOffsetRemoval(settings.m_dcBlock);
}
if (settingsKeys.contains("iqCorrection") || force) {
setIQCorrection(settings.m_iqCorrection);
}
if (settingsKeys.contains("biasTee") || force) {
setBiasTee(settings.m_biasTee);
}
if (settingsKeys.contains("directSampling") || force) {
setDirectSampling(settings.m_directSampling);
}
if (settingsKeys.contains("devSampleRate") || force) {
setSampleRate(settings.m_devSampleRate);
}
if (settingsKeys.contains("agc") || force)
{
if (m_rsp0) {
rspSetAGC(settings.m_agc);
} else {
setAGC(settings.m_agc);
}
}
if (force)
{
if (!m_rsp0) {
setTunerAGC(1); // The SDRangel RTLSDR driver always has tuner gain as manual
}
}
if (settingsKeys.contains("gain[0]") || force)
{
if (m_rsp0) {
rspSetLNAState(settings.m_gain[0] / 10);
} else {
setTunerGain(settings.m_gain[0]);
}
}
for (int i = 1; i < 2; i++)
{
if (settingsKeys.contains(QString("gain[%1]").arg(i)) || force)
{
if (m_rsp0 && (i == 1)) {
rspSetIfGainR(settings.m_gain[i] / -10);
} else {
setIFGain(i, settings.m_gain[i]);
}
}
}
if (settingsKeys.contains("rfBW") || force) {
setBandwidth(settings.m_rfBW);
}
if (settingsKeys.contains("sampleBits") || force)
{
if (m_rsp0) {
setAndroidEnable16BitSigned(settings.m_sampleBits == 16);
} else {
setSampleBitDepth(settings.m_sampleBits);
}
clearBuffer();
}
// Don't use force, as disconnect can cause rtl_tcp to quit
if (settingsKeys.contains("dataPort") || (m_dataSocket == nullptr))
{
disconnectFromHost();
connectToHost("127.0.0.1", settings.m_dataPort);
}
if (force) {
m_settings = settings;
} else {
m_settings.applySettings(settingsKeys, settings);
}
}
void AndroidSDRDriverInputTCPHandler::connected()
{
QMutexLocker mutexLocker(&m_mutex);
qDebug() << "AndroidSDRDriverInputTCPHandler::connected";
// Force settings to be sent to remote device
applySettings(m_settings, QList<QString>(), true);
if (m_messageQueueToGUI)
{
MsgReportConnection *msg = MsgReportConnection::create(true);
m_messageQueueToGUI->push(msg);
}
}
void AndroidSDRDriverInputTCPHandler::reconnect()
{
QMutexLocker mutexLocker(&m_mutex);
if (!m_dataSocket) {
connectToHost("127.0.0.1", m_settings.m_dataPort);
}
}
void AndroidSDRDriverInputTCPHandler::disconnected()
{
QMutexLocker mutexLocker(&m_mutex);
qDebug() << "AndroidSDRDriverInputTCPHandler::disconnected";
cleanup();
if (m_messageQueueToGUI)
{
MsgReportConnection *msg = MsgReportConnection::create(false);
m_messageQueueToGUI->push(msg);
}
// Try to reconnect
m_reconnectTimer.start(500);
}
void AndroidSDRDriverInputTCPHandler::errorOccurred(QAbstractSocket::SocketError socketError)
{
qDebug() << "AndroidSDRDriverInputTCPHandler::errorOccurred: " << socketError;
cleanup();
if (m_messageQueueToGUI)
{
MsgReportConnection *msg = MsgReportConnection::create(false);
m_messageQueueToGUI->push(msg);
}
// Try to reconnect
m_reconnectTimer.start(500);
}
void AndroidSDRDriverInputTCPHandler::dataReadyRead()
{
QMutexLocker mutexLocker(&m_mutex);
if (!m_readMetaData)
{
quint8 metaData[RemoteTCPProtocol::m_rtl0MetaDataSize];
if (m_dataSocket->bytesAvailable() >= (qint64)sizeof(metaData))
{
qint64 bytesRead = m_dataSocket->read((char *)&metaData[0], 4);
if (bytesRead == 4)
{
// Read first 4 bytes which indicate which protocol is in use.
char protochars[5];
memcpy(protochars, metaData, 4);
protochars[4] = '\0';
QString protocol(protochars);
qDebug() << "RemoteTCPInputTCPHandler::dataReadyRead: Protocol: " << QByteArray((char *)metaData, 4).toHex() << " - " << protocol;
if (protocol == "RTL0")
{
m_rsp0 = false;
bytesRead = m_dataSocket->read((char *)&metaData[4], RemoteTCPProtocol::m_rtl0MetaDataSize-4);
RemoteTCPProtocol::Device tuner = (RemoteTCPProtocol::Device)RemoteTCPProtocol::extractUInt32(&metaData[4]);
if (m_messageQueueToGUI) {
m_messageQueueToGUI->push(MsgReportRemoteDevice::create(tuner, protocol));
}
// Set default gain to something reasonable
if (m_settings.m_gain[0] == 0)
{
AndroidSDRDriverInputSettings& settings = m_settings;
if (tuner == RemoteTCPProtocol::RTLSDR_E4000) {
settings.m_gain[0] = 290.0;
} else {
settings.m_gain[0] = 297.0;
}
QList<QString> settingsKeys{"gain[0]"};
if (m_messageQueueToInput) {
m_messageQueueToInput->push(AndroidSDRDriverInput::MsgConfigureAndroidSDRDriverInput::create(settings, settingsKeys));
}
if (m_messageQueueToGUI) {
m_messageQueueToGUI->push(AndroidSDRDriverInput::MsgConfigureAndroidSDRDriverInput::create(settings, settingsKeys));
}
}
}
else if (protocol == "MIR0")
{
// Android RTLplay driver uses MIR0 protocol, but tuner type is 0 so no way of knowing what device is used
m_rsp0 = true;
bytesRead = m_dataSocket->read((char *)&metaData[4], RemoteTCPProtocol::m_rtl0MetaDataSize-4);
if (m_messageQueueToGUI) {
m_messageQueueToGUI->push(MsgReportRemoteDevice::create(RemoteTCPProtocol::SDRPLAY_V3_RSPDUO, protocol));
}
// Switch to 16-bit
// If we don't do this straight away, it doesn't seem reliable
setAndroidEnable16BitSigned(true);
if (m_settings.m_sampleBits != 16)
{
AndroidSDRDriverInputSettings& settings = m_settings;
settings.m_sampleBits = 16;
QList<QString> settingsKeys{"sampleBits"};
if (m_messageQueueToInput) {
m_messageQueueToInput->push(AndroidSDRDriverInput::MsgConfigureAndroidSDRDriverInput::create(settings, settingsKeys));
}
if (m_messageQueueToGUI) {
m_messageQueueToGUI->push(AndroidSDRDriverInput::MsgConfigureAndroidSDRDriverInput::create(settings, settingsKeys));
}
}
// Set default gains to something reasonable
if ((m_settings.m_gain[0] == 0) && (m_settings.m_gain[1] == 0))
{
AndroidSDRDriverInputSettings& settings = m_settings;
settings.m_gain[0] = 40;
settings.m_gain[1] = -400;
QList<QString> settingsKeys{"gain[0]", "gain[1]"};
if (m_messageQueueToInput) {
m_messageQueueToInput->push(AndroidSDRDriverInput::MsgConfigureAndroidSDRDriverInput::create(settings, settingsKeys));
}
if (m_messageQueueToGUI) {
m_messageQueueToGUI->push(AndroidSDRDriverInput::MsgConfigureAndroidSDRDriverInput::create(settings, settingsKeys));
}
}
}
else
{
qDebug() << "AndroidSDRDriverInputTCPHandler::dataReadyRead: Unknown protocol: " << QByteArray((char *)metaData, 4).toHex() << " - " << protocol;
}
}
else
{
qDebug() << "AndroidSDRDriverInputTCPHandler::dataReadyRead: Failed to read protocol ID";
}
m_readMetaData = true;
}
else
{
qDebug() << "AndroidSDRDriverInputTCPHandler::dataReadyRead: Not enough metadata";
}
}
else
{
int bytesPerSample = m_settings.m_sampleBits / 8;
unsigned int remaining = m_sampleFifo->size() - m_sampleFifo->fill();
int requiredSamples = (int)std::min((unsigned int)(m_dataSocket->bytesAvailable()/(2*bytesPerSample)), remaining);
if (requiredSamples >= 0)
{
m_dataSocket->read(&m_tcpBuf[0], requiredSamples*2*bytesPerSample);
convert(requiredSamples);
}
}
}
// The following code assumes host is little endian
void AndroidSDRDriverInputTCPHandler::convert(int nbSamples)
{
if (nbSamples > (int) m_converterBufferNbSamples)
{
if (m_converterBuffer) {
delete[] m_converterBuffer;
}
m_converterBuffer = new int32_t[nbSamples*2];
}
if ((m_settings.m_sampleBits == 32) && (SDR_RX_SAMP_SZ == 24))
{
m_sampleFifo->write(reinterpret_cast<quint8*>(m_tcpBuf), nbSamples*sizeof(Sample));
}
else if ((m_settings.m_sampleBits == 8) && (SDR_RX_SAMP_SZ == 16))
{
quint8 *in = (quint8 *)m_tcpBuf;
qint16 *out = (qint16 *)m_converterBuffer;
for (int is = 0; is < nbSamples*2; is++) {
out[is] = (((qint16)in[is]) - 128) << 8;
}
m_sampleFifo->write(reinterpret_cast<quint8*>(out), nbSamples*sizeof(Sample));
}
else if ((m_settings.m_sampleBits == 8) && (SDR_RX_SAMP_SZ == 24))
{
quint8 *in = (quint8 *)m_tcpBuf;
qint32 *out = (qint32 *)m_converterBuffer;
for (int is = 0; is < nbSamples*2; is++) {
out[is] = (((qint32)in[is]) - 128) << 16;
}
m_sampleFifo->write(reinterpret_cast<quint8*>(out), nbSamples*sizeof(Sample));
}
else if ((m_settings.m_sampleBits == 24) && (SDR_RX_SAMP_SZ == 24))
{
quint8 *in = (quint8 *)m_tcpBuf;
qint32 *out = (qint32 *)m_converterBuffer;
for (int is = 0; is < nbSamples*2; is++) {
out[is] = (((in[3*is+2] << 16) | (in[3*is+1] << 8) | in[3*is]) << 8) >> 8;
}
m_sampleFifo->write(reinterpret_cast<quint8*>(out), nbSamples*sizeof(Sample));
}
else if ((m_settings.m_sampleBits == 24) && (SDR_RX_SAMP_SZ == 16))
{
quint8 *in = (quint8 *)m_tcpBuf;
qint16 *out = (qint16 *)m_converterBuffer;
for (int is = 0; is < nbSamples*2; is++) {
out[is] = (in[3*is+2] << 8) | in[3*is+1];
}
m_sampleFifo->write(reinterpret_cast<quint8*>(out), nbSamples*sizeof(Sample));
}
else if ((m_settings.m_sampleBits == 16) && (SDR_RX_SAMP_SZ == 24))
{
qint16 *in = (qint16 *)m_tcpBuf;
qint32 *out = (qint32 *)m_converterBuffer;
for (int is = 0; is < nbSamples*2; is++) {
if (m_rsp0) {
out[is] = in[is] << 12;
} else {
out[is] = in[is] << 8;
}
}
m_sampleFifo->write(reinterpret_cast<quint8*>(out), nbSamples*sizeof(Sample));
}
else if ((m_settings.m_sampleBits == 32) && (SDR_RX_SAMP_SZ == 16))
{
qint32 *in = (qint32 *)m_tcpBuf;
qint16 *out = (qint16 *)m_converterBuffer;
for (int is = 0; is < nbSamples*2; is++) {
out[is] = in[is] >> 8;
}
m_sampleFifo->write(reinterpret_cast<quint8*>(out), nbSamples*sizeof(Sample));
}
else // invalid size
{
qWarning("AndroidSDRDriverInputTCPHandler::convert: unexpected sample size in stream: %d bits", (int) m_settings.m_sampleBits);
}
}
void AndroidSDRDriverInputTCPHandler::handleInputMessages()
{
Message* message;
while ((message = m_inputMessageQueue.pop()))
{
if (!handleMessage(*message)) {
qDebug("%s: unhandled message: %s", Q_FUNC_INFO, message->getIdentifier());
}
delete message;
}
}
bool AndroidSDRDriverInputTCPHandler::handleMessage(const Message& cmd)
{
if (MsgConfigureTcpHandler::match(cmd))
{
qDebug() << "AndroidSDRDriverInputTCPHandler::handleMessage: MsgConfigureTcpHandler";
MsgConfigureTcpHandler& notif = (MsgConfigureTcpHandler&) cmd;
applySettings(notif.getSettings(), notif.getSettingsKeys(), notif.getForce());
return true;
}
else
{
return false;
}
}