SoapySDR::Kwargs SDRThread::combineArgs(SoapySDR::Kwargs a, SoapySDR::Kwargs b) { SoapySDR::Kwargs c; SoapySDR::Kwargs::iterator i; for (i = a.begin(); i != a.end(); i++) { c[i->first] = i->second; } for (i = b.begin(); i != b.end(); i++) { c[i->first] = i->second; } return c; }
std::vector<SoapySDR::Kwargs> findNullDevice(const SoapySDR::Kwargs &args) { std::vector<SoapySDR::Kwargs> results; //require that the user specify type=null if (args.count("type") == 0) return results; if (args.at("type") != "null") return results; SoapySDR::Kwargs nullArgs; nullArgs["type"] = "null"; results.push_back(nullArgs); return results; }
static bladerf_devinfo kwargs_to_devinfo(const SoapySDR::Kwargs &args) { std::stringstream ss; if (args.count("backend") != 0) { ss << args.at("backend") << ":"; } else ss << "*:"; if (args.count("device") != 0) { ss << "device=" << args.at("device") << " "; } if (args.count("instance") != 0) { ss << "instance=" << args.at("instance") << " "; } if (args.count("serial") != 0) { ss << "serial=" << args.at("serial") << " "; } bladerf_devinfo info; bladerf_init_devinfo(&info); bladerf_get_devinfo_from_str(ss.str().c_str(), &info); return info; }
void SoapyRPCUnpacker::operator&(SoapySDR::Kwargs &value) { UNPACK_TYPE_HELPER(SOAPY_REMOTE_KWARGS); int size = 0; *this & size; value.clear(); for (size_t i = 0; i < size_t(size); i++) { std::string key, val; *this & key; *this & val; value[key] = val; } }
/*********************************************************************** * Discovery routine -- connect to server when key specified **********************************************************************/ static std::vector<SoapySDR::Kwargs> findRemote(const SoapySDR::Kwargs &args) { std::vector<SoapySDR::Kwargs> result; if (args.count(SOAPY_REMOTE_KWARG_STOP) != 0) return result; //no remote specified, use the discovery protocol if (args.count("remote") == 0) { //On non-windows platforms the endpoint instance can last the //duration of the process because it can be cleaned up safely. //Windows has issues cleaning up threads and sockets on exit. #ifndef _MSC_VER static #endif //_MSC_VER auto ssdpEndpoint = SoapySSDPEndpoint::getInstance(); //enable forces new search queries ssdpEndpoint->enablePeriodicSearch(true); //wait maximum timeout for replies std::this_thread::sleep_for(std::chrono::microseconds(SOAPY_REMOTE_SOCKET_TIMEOUT_US)); for (const auto &url : SoapySSDPEndpoint::getInstance()->getServerURLs()) { auto argsWithURL = args; argsWithURL["remote"] = url; const auto subResult = findRemote(argsWithURL); result.insert(result.end(), subResult.begin(), subResult.end()); } return result; } //otherwise connect to a specific url and enumerate auto url = SoapyURL(args.at("remote")); //default url parameters when not specified if (url.getScheme().empty()) url.setScheme("tcp"); if (url.getService().empty()) url.setService(SOAPY_REMOTE_DEFAULT_SERVICE); //try to connect to the remote server SoapySocketSession sess; SoapyRPCSocket s; int ret = s.connect(url.toString()); if (ret != 0) { SoapySDR::logf(SOAPY_SDR_ERROR, "SoapyRemote::find() -- connect(%s) FAIL: %s", url.toString().c_str(), s.lastErrorMsg()); return result; } //find transaction try { SoapyLogAcceptor logAcceptor(url.toString(), s); SoapyRPCPacker packer(s); packer & SOAPY_REMOTE_FIND; packer & translateArgs(args); packer(); SoapyRPCUnpacker unpacker(s); unpacker & result; //graceful disconnect SoapyRPCPacker packerHangup(s); packerHangup & SOAPY_REMOTE_HANGUP; packerHangup(); SoapyRPCUnpacker unpackerHangup(s); } catch (const std::exception &ex) { SoapySDR::logf(SOAPY_SDR_ERROR, "SoapyRemote::find() -- transact FAIL: %s", ex.what()); } //remove instances of the stop key from the result for (auto &resultArgs : result) { resultArgs.erase(SOAPY_REMOTE_KWARG_STOP); if (resultArgs.count("driver") != 0) { resultArgs["remote:driver"] = resultArgs.at("driver"); resultArgs.erase("driver"); } if (resultArgs.count("type") != 0) { resultArgs["remote:type"] = resultArgs.at("type"); resultArgs.erase("type"); } resultArgs["remote"] = url.toString(); } return result; }
std::vector<SDRDeviceInfo *> *SDREnumerator::enumerate_devices(std::string remoteAddr, bool noInit) { if (SDREnumerator::devs[remoteAddr].size()) { return &SDREnumerator::devs[remoteAddr]; } if (noInit) { return NULL; } if (!soapy_initialized) { std::cout << "SoapySDR init.." << std::endl; std::cout << "\tAPI Version: v" << SoapySDR::getAPIVersion() << std::endl; std::cout << "\tABI Version: v" << SoapySDR::getABIVersion() << std::endl; std::cout << "\tInstall root: " << SoapySDR::getRootPath() << std::endl; std::cout << "\tLoading modules... " << std::endl; std::string userModPath = wxGetApp().getModulePath(); if (userModPath != "") { wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Loading SoapySDR modules from " + userModPath + ".."); std::vector<std::string> localMods = SoapySDR::listModules(userModPath); for (std::vector<std::string>::iterator mods_i = localMods.begin(); mods_i != localMods.end(); mods_i++) { wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Initializing user specified SoapySDR module " + (*mods_i) + ".."); std::cout << "Initializing user specified SoapySDR module " << (*mods_i) << ".." << std::endl; SoapySDR::loadModule(*mods_i); } } else { #ifdef BUNDLE_SOAPY_MODS bool localModPref = wxGetApp().getUseLocalMod(); if (localModPref) { wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Loading SoapySDR modules.."); std::cout << "Checking local system SoapySDR modules.." << std::flush; SoapySDR::loadModules(); } wxFileName exePath = wxFileName(wxStandardPaths::Get().GetExecutablePath()); std::vector<std::string> localMods = SoapySDR::listModules(exePath.GetPath().ToStdString() + "/modules/"); for (std::vector<std::string>::iterator mods_i = localMods.begin(); mods_i != localMods.end(); mods_i++) { wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Initializing bundled SoapySDR module " + (*mods_i) + ".."); std::cout << "Loading bundled SoapySDR module " << (*mods_i) << ".." << std::endl; SoapySDR::loadModule(*mods_i); } if (!localModPref) { wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Loading SoapySDR modules.."); std::cout << "Checking system SoapySDR modules.." << std::flush; SoapySDR::loadModules(); } #else wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Loading SoapySDR modules.."); SoapySDR::loadModules(); #endif } if (SDREnumerator::factories.size()) { SDREnumerator::factories.erase(SDREnumerator::factories.begin(), SDREnumerator::factories.end()); } std::cout << "\tAvailable factories..."; SoapySDR::FindFunctions factories = SoapySDR::Registry::listFindFunctions(); for (SoapySDR::FindFunctions::const_iterator it = factories.begin(); it != factories.end(); ++it) { if (it != factories.begin()) { std::cout << ", "; } std::cout << it->first; if (it->first == "remote") { has_remote = true; } SDREnumerator::factories.push_back(it->first); } if (factories.empty()) { std::cout << "No factories found!" << std::endl; } if ((factories.size() == 1) && factories.find("null") != factories.end()) { std::cout << "Just 'null' factory found." << std::endl; wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_FAILED, std::string("No modules available.")); } std::cout << std::endl; soapy_initialized = true; } modules = SoapySDR::listModules(); std::vector<SoapySDR::Kwargs> results; SoapySDR::Kwargs enumArgs; bool isRemote = false; if (remoteAddr.length()) { std::cout << "Enumerating remote address: " << remoteAddr << std::endl; enumArgs["driver"] = "remote"; enumArgs["remote"] = remoteAddr; isRemote = true; results = SoapySDR::Device::enumerate(enumArgs); } else { results = SoapySDR::Device::enumerate(); } int manualsIdx = results.size(); std::vector<std::string> manualParams; std::vector<bool> manualResult; if (manuals.size()) { for (std::vector<SDRManualDef>::const_iterator m_i = manuals.begin(); m_i != manuals.end(); m_i++) { std::vector<SoapySDR::Kwargs> manual_result; std::string strDevArgs = "driver="+m_i->factory+","+m_i->params; manualParams.push_back(m_i->params); wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Enumerating manual device '") + strDevArgs + "'.."); manual_result = SoapySDR::Device::enumerate(strDevArgs); if (manual_result.size()) { for (std::vector<SoapySDR::Kwargs>::const_iterator i = manual_result.begin(); i != manual_result.end(); i++) { results.push_back(*i); manualResult.push_back(true); } } else { SoapySDR::Kwargs failedEnum; failedEnum = argsStrToKwargs(strDevArgs); failedEnum["label"] = "Not Found ("+m_i->factory+")"; results.push_back(failedEnum); manualResult.push_back(false); } } } if (isRemote) { wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Opening remote server ") + remoteAddr + ".."); } for (size_t i = 0; i < results.size(); i++) { SDRDeviceInfo *dev = new SDRDeviceInfo(); SoapySDR::Kwargs deviceArgs = results[i]; for (SoapySDR::Kwargs::const_iterator it = deviceArgs.begin(); it != deviceArgs.end(); ++it) { std::cout << " " << it->first << " = " << it->second << std::endl; if (it->first == "driver") { dev->setDriver(it->second); } else if (it->first == "label" || it->first == "device") { dev->setName(it->second); } } if (deviceArgs.count("remote")) { isRemote = true; } else { isRemote = false; } dev->setRemote(isRemote); dev->setManual(i>=manualsIdx); if (i>=manualsIdx) { dev->setManualParams(manualParams[i-manualsIdx]); } std::cout << "Make device " << i << std::endl; if (i<manualsIdx || manualResult[i-manualsIdx]) try { SoapySDR::Device *device = SoapySDR::Device::make(deviceArgs); SoapySDR::Kwargs info = device->getHardwareInfo(); for (SoapySDR::Kwargs::const_iterator it = info.begin(); it != info.end(); ++it) { std::cout << " " << it->first << "=" << it->second << std::endl; if (it->first == "hardware") { dev->setHardware(it->second); } } if (isRemote) { wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Querying remote " + remoteAddr + " device #" + std::to_string(i) + ": " + dev-> getName()); } else { wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Querying device #") + std::to_string(i) + ": " + dev->getName()); } SoapySDR::ArgInfoList settingsInfo = device->getSettingInfo(); DeviceConfig *cfg = wxGetApp().getConfig()->getDevice(dev->getDeviceId()); ConfigSettings devSettings = cfg->getSettings(); if (devSettings.size()) { for (ConfigSettings::const_iterator set_i = devSettings.begin(); set_i != devSettings.end(); set_i++) { deviceArgs[set_i->first] = set_i->second; } for (int j = 0; j < settingsInfo.size(); j++) { if (deviceArgs.find(settingsInfo[j].key) != deviceArgs.end()) { settingsInfo[j].value = deviceArgs[settingsInfo[j].key]; } } } dev->setDeviceArgs(deviceArgs); dev->setSettingsInfo(settingsInfo); int numChan = device->getNumChannels(SOAPY_SDR_RX); for (int i = 0; i < numChan; i++) { SDRDeviceChannel *chan = new SDRDeviceChannel(); SoapySDR::RangeList rfRange = device->getFrequencyRange(SOAPY_SDR_RX, i); double rfMin = rfRange[0].minimum(); double rfMax = rfRange[rfRange.size()-1].maximum(); chan->setChannel(i); chan->setFullDuplex(device->getFullDuplex(SOAPY_SDR_RX, i)); chan->setRx(true); chan->setTx(false); chan->getRFRange().setLow(rfMin); chan->getRFRange().setHigh(rfMax); std::vector<std::string> freqs = device->listFrequencies(SOAPY_SDR_RX,i); if (std::find(freqs.begin(), freqs.end(), "CORR") != freqs.end()) { chan->setCORR(true); } else { chan->setCORR(false); } if (device->hasDCOffsetMode(SOAPY_SDR_RX, i)) { chan->setHardwareDC(true); } else { chan->setHardwareDC(false); } std::vector<double> rates = device->listSampleRates(SOAPY_SDR_RX, i); for (std::vector<double>::iterator i = rates.begin(); i != rates.end(); i++) { chan->getSampleRates().push_back((long)(*i)); } ConfigSettings devStreamOpts = cfg->getStreamOpts(); if (devStreamOpts.size()) { dev->setStreamArgs(devStreamOpts); } SoapySDR::ArgInfoList optArgs = device->getStreamArgsInfo(SOAPY_SDR_RX, i); if (devStreamOpts.size()) { for (int j = 0, jMax = optArgs.size(); j < jMax; j++) { if (devStreamOpts.find(optArgs[j].key) != devStreamOpts.end()) { optArgs[j].value = devStreamOpts[optArgs[j].key]; } } } chan->setStreamArgsInfo(optArgs); std::vector<std::string> gainNames = device->listGains(SOAPY_SDR_RX, i); for (std::vector<std::string>::iterator gname = gainNames.begin(); gname!= gainNames.end(); gname++) { chan->addGain((*gname),device->getGainRange(SOAPY_SDR_RX, i, (*gname))); } dev->addChannel(chan); } SoapySDR::Device::unmake(device); dev->setAvailable(true); } catch (const std::exception &ex) { std::cerr << "Error making device: " << ex.what() << std::endl; wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Error querying device #") + std::to_string(i)); dev->setAvailable(false); } else { dev->setAvailable(false); } std::cout << std::endl; SDREnumerator::devs[remoteAddr].push_back(dev); } if (SDREnumerator::devs[remoteAddr].empty()) { wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("No devices found!")); } std::cout << std::endl; return &SDREnumerator::devs[remoteAddr]; }
/*********************************************************************** * Handler dispatcher implementation **********************************************************************/ bool SoapyClientHandler::handleOnce(SoapyRPCUnpacker &unpacker, SoapyRPCPacker &packer) { SoapyRemoteCalls call; unpacker & call; switch (call) { //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_FIND: //////////////////////////////////////////////////////////////////// { SoapySDR::Kwargs args; unpacker & args; packer & SoapySDR::Device::enumerate(args); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_MAKE: //////////////////////////////////////////////////////////////////// { SoapySDR::Kwargs args; unpacker & args; std::lock_guard<std::mutex> lock(factoryMutex); if (_dev == nullptr) _dev = SoapySDR::Device::make(args); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_UNMAKE: //////////////////////////////////////////////////////////////////// { std::lock_guard<std::mutex> lock(factoryMutex); if (_dev != nullptr) SoapySDR::Device::unmake(_dev); _dev = nullptr; packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_HANGUP: //////////////////////////////////////////////////////////////////// { packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_SERVER_ID: //////////////////////////////////////////////////////////////////// { packer & uniqueProcessId(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_START_LOG_FORWARDING: //////////////////////////////////////////////////////////////////// { if (_logForwarder == nullptr) _logForwarder = new SoapyLogForwarder(_sock); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_STOP_LOG_FORWARDING: //////////////////////////////////////////////////////////////////// { if (_logForwarder != nullptr) delete _logForwarder; _logForwarder = nullptr; packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_DRIVER_KEY: //////////////////////////////////////////////////////////////////// { packer & _dev->getDriverKey(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_HARDWARE_KEY: //////////////////////////////////////////////////////////////////// { packer & _dev->getHardwareKey(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_HARDWARE_INFO: //////////////////////////////////////////////////////////////////// { packer & _dev->getHardwareInfo(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_FRONTEND_MAPPING: //////////////////////////////////////////////////////////////////// { char direction = 0; std::string mapping; unpacker & direction; unpacker & mapping; _dev->setFrontendMapping(direction, mapping); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_FRONTEND_MAPPING: //////////////////////////////////////////////////////////////////// { char direction = 0; unpacker & direction; packer & _dev->getFrontendMapping(direction); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_NUM_CHANNELS: //////////////////////////////////////////////////////////////////// { char direction = 0; unpacker & direction; packer & int(_dev->getNumChannels(direction)); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_FULL_DUPLEX: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getFullDuplex(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SETUP_STREAM: //////////////////////////////////////////////////////////////////// { char direction = 0; std::string format; std::vector<size_t> channels; SoapySDR::Kwargs args; std::string clientBindPort; std::string statusBindPort; unpacker & direction; unpacker & format; unpacker & channels; unpacker & args; unpacker & clientBindPort; unpacker & statusBindPort; //parse args for buffer configuration size_t mtu = SOAPY_REMOTE_DEFAULT_ENDPOINT_MTU; const auto mtuIt = args.find(SOAPY_REMOTE_KWARG_MTU); if (mtuIt != args.end()) mtu = size_t(std::stod(mtuIt->second)); size_t window = SOAPY_REMOTE_DEFAULT_ENDPOINT_WINDOW; const auto windowIt = args.find(SOAPY_REMOTE_KWARG_WINDOW); if (windowIt != args.end()) window = size_t(std::stod(windowIt->second)); double priority = SOAPY_REMOTE_DEFAULT_THREAD_PRIORITY; const auto priorityIt = args.find(SOAPY_REMOTE_KWARG_PRIORITY); if (priorityIt != args.end()) priority = std::stod(priorityIt->second); //create stream auto stream = _dev->setupStream(direction, format, channels, args); //load data structure auto &data = _streamData[_nextStreamId]; data.streamId = _nextStreamId++; data.device = _dev; data.stream = stream; data.format = format; for (const auto chan : channels) data.chanMask |= (1 << chan); data.priority = priority; //extract socket node information std::string serverBindPort; std::string localNode, remoteNode; std::string scheme, node, service; splitURL(_sock.getsockname(), scheme, localNode, service); splitURL(_sock.getpeername(), scheme, remoteNode, service); //bind the stream socket to an automatic port const auto bindURL = combineURL("udp", localNode, "0"); int ret = data.streamSock.bind(bindURL); if (ret != 0) { const std::string errorMsg = data.streamSock.lastErrorMsg(); _streamData.erase(data.streamId); throw std::runtime_error("SoapyRemote::setupStream("+bindURL+") -- bind FAIL: " + errorMsg); } SoapySDR::logf(SOAPY_SDR_INFO, "Server side stream bound to %s", data.streamSock.getsockname().c_str()); splitURL(data.streamSock.getsockname(), scheme, node, serverBindPort); //connect the stream socket to the specified port auto connectURL = combineURL("udp", remoteNode, clientBindPort); ret = data.streamSock.connect(connectURL); if (ret != 0) { const std::string errorMsg = data.streamSock.lastErrorMsg(); _streamData.erase(data.streamId); throw std::runtime_error("SoapyRemote::setupStream("+connectURL+") -- connect FAIL: " + errorMsg); } SoapySDR::logf(SOAPY_SDR_INFO, "Server side stream connected to %s", data.streamSock.getpeername().c_str()); //connect the status socket to the specified port connectURL = combineURL("udp", remoteNode, statusBindPort); ret = data.statusSock.connect(connectURL); if (ret != 0) { const std::string errorMsg = data.statusSock.lastErrorMsg(); _streamData.erase(data.streamId); throw std::runtime_error("SoapyRemote::setupStream("+connectURL+") -- connect FAIL: " + errorMsg); } SoapySDR::logf(SOAPY_SDR_INFO, "Server side status connected to %s", data.statusSock.getpeername().c_str()); //create endpoint data.endpoint = new SoapyStreamEndpoint(data.streamSock, data.statusSock, direction == SOAPY_SDR_TX, channels.size(), formatToSize(format), mtu, window); //start worker thread, this is not backwards, //receive from device means using a send endpoint //transmit to device means using a recv endpoint if (direction == SOAPY_SDR_RX) data.startSendThread(); if (direction == SOAPY_SDR_TX) data.startRecvThread(); data.startStatThread(); packer & data.streamId; packer & serverBindPort; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_CLOSE_STREAM: //////////////////////////////////////////////////////////////////// { int streamId = 0; unpacker & streamId; //cleanup data and stop worker thread auto &data = _streamData.at(streamId); data.stopThreads(); _dev->closeStream(data.stream); _streamData.erase(streamId); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_ACTIVATE_STREAM: //////////////////////////////////////////////////////////////////// { int streamId = 0; int flags = 0; long long timeNs = 0; int numElems = 0; unpacker & streamId; unpacker & flags; unpacker & timeNs; unpacker & numElems; auto &data = _streamData.at(streamId); packer & _dev->activateStream(data.stream, flags, timeNs, size_t(numElems)); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_DEACTIVATE_STREAM: //////////////////////////////////////////////////////////////////// { int streamId = 0; int flags = 0; long long timeNs = 0; unpacker & streamId; unpacker & flags; unpacker & timeNs; auto &data = _streamData.at(streamId); packer & _dev->deactivateStream(data.stream, flags, timeNs); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_LIST_ANTENNAS: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->listAntennas(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_ANTENNA: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; std::string name; unpacker & direction; unpacker & channel; unpacker & name; _dev->setAntenna(direction, channel, name); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_ANTENNA: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getAntenna(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_HAS_DC_OFFSET_MODE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->hasDCOffsetMode(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_DC_OFFSET_MODE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; bool automatic = false; unpacker & direction; unpacker & channel; unpacker & automatic; _dev->setDCOffsetMode(direction, channel, automatic); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_DC_OFFSET_MODE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getDCOffsetMode(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_HAS_DC_OFFSET: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->hasDCOffset(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_DC_OFFSET: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; std::complex<double> offset; unpacker & direction; unpacker & channel; unpacker & offset; _dev->setDCOffset(direction, channel, offset); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_DC_OFFSET: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getDCOffset(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_HAS_IQ_BALANCE_MODE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->hasIQBalance(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_IQ_BALANCE_MODE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; std::complex<double> balance; unpacker & direction; unpacker & channel; unpacker & balance; _dev->setIQBalance(direction, channel, balance); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_IQ_BALANCE_MODE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getIQBalance(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_LIST_GAINS: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->listGains(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_GAIN_MODE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; bool automatic = false; unpacker & direction; unpacker & channel; unpacker & automatic; _dev->setGainMode(direction, channel, automatic); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_GAIN_MODE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getGainMode(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_GAIN: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; double value = 0; unpacker & direction; unpacker & channel; unpacker & value; _dev->setGain(direction, channel, value); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_GAIN_ELEMENT: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; std::string name; double value = 0; unpacker & direction; unpacker & channel; unpacker & name; unpacker & value; _dev->setGain(direction, channel, name, value); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_GAIN: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getGain(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_GAIN_ELEMENT: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; std::string name; unpacker & direction; unpacker & channel; unpacker & name; packer & _dev->getGain(direction, channel, name); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_GAIN_RANGE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getGainRange(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_GAIN_RANGE_ELEMENT: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; std::string name; unpacker & direction; unpacker & channel; unpacker & name; packer & _dev->getGainRange(direction, channel, name); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_FREQUENCY: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; double value = 0; SoapySDR::Kwargs args; unpacker & direction; unpacker & channel; unpacker & value; unpacker & args; _dev->setFrequency(direction, channel, value, args); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_FREQUENCY_COMPONENT: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; std::string name; double value = 0; SoapySDR::Kwargs args; unpacker & direction; unpacker & channel; unpacker & name; unpacker & value; unpacker & args; _dev->setFrequency(direction, channel, name, value, args); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_FREQUENCY: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getFrequency(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_FREQUENCY_COMPONENT: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; std::string name; unpacker & direction; unpacker & channel; unpacker & name; packer & _dev->getFrequency(direction, channel, name); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_LIST_FREQUENCIES: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->listFrequencies(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_FREQUENCY_RANGE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getFrequencyRange(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_FREQUENCY_RANGE_COMPONENT: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; std::string name; unpacker & direction; unpacker & channel; unpacker & name; packer & _dev->getFrequencyRange(direction, channel, name); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_SAMPLE_RATE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; double rate = 0; unpacker & direction; unpacker & channel; unpacker & rate; _dev->setSampleRate(direction, channel, rate); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_SAMPLE_RATE: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getSampleRate(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_LIST_SAMPLE_RATES: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->listSampleRates(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_BANDWIDTH: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; double bw = 0; unpacker & direction; unpacker & channel; unpacker & bw; _dev->setBandwidth(direction, channel, bw); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_BANDWIDTH: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->getBandwidth(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_LIST_BANDWIDTHS: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->listBandwidths(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_MASTER_CLOCK_RATE: //////////////////////////////////////////////////////////////////// { double rate = 0; unpacker & rate; _dev->setMasterClockRate(rate); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_MASTER_CLOCK_RATE: //////////////////////////////////////////////////////////////////// { packer & _dev->getMasterClockRate(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_LIST_CLOCK_SOURCES: //////////////////////////////////////////////////////////////////// { packer & _dev->listClockSources(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_CLOCK_SOURCE: //////////////////////////////////////////////////////////////////// { std::string source; unpacker & source; _dev->setClockSource(source); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_CLOCK_SOURCE: //////////////////////////////////////////////////////////////////// { packer & _dev->getClockSource(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_LIST_TIME_SOURCES: //////////////////////////////////////////////////////////////////// { packer & _dev->listTimeSources(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_TIME_SOURCE: //////////////////////////////////////////////////////////////////// { std::string source; unpacker & source; _dev->setTimeSource(source); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_TIME_SOURCE: //////////////////////////////////////////////////////////////////// { packer & _dev->getTimeSource(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_HAS_HARDWARE_TIME: //////////////////////////////////////////////////////////////////// { std::string what; unpacker & what; packer & _dev->hasHardwareTime(what); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_GET_HARDWARE_TIME: //////////////////////////////////////////////////////////////////// { std::string what; unpacker & what; packer & _dev->getHardwareTime(what); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_HARDWARE_TIME: //////////////////////////////////////////////////////////////////// { long long timeNs = 0; std::string what; unpacker & timeNs; unpacker & what; _dev->setHardwareTime(timeNs, what); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_SET_COMMAND_TIME: //////////////////////////////////////////////////////////////////// { long long timeNs = 0; std::string what; unpacker & timeNs; unpacker & what; _dev->setCommandTime(timeNs, what); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_LIST_SENSORS: //////////////////////////////////////////////////////////////////// { packer & _dev->listSensors(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_READ_SENSOR: //////////////////////////////////////////////////////////////////// { std::string name; unpacker & name; packer & _dev->readSensor(name); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_LIST_CHANNEL_SENSORS: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; unpacker & direction; unpacker & channel; packer & _dev->listSensors(direction, channel); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_READ_CHANNEL_SENSOR: //////////////////////////////////////////////////////////////////// { char direction = 0; int channel = 0; std::string name; unpacker & direction; unpacker & channel; unpacker & name; packer & _dev->readSensor(direction, channel, name); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_WRITE_REGISTER: //////////////////////////////////////////////////////////////////// { int addr = 0; int value = 0; unpacker & addr; unpacker & value; _dev->writeRegister(unsigned(addr), unsigned(value)); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_READ_REGISTER: //////////////////////////////////////////////////////////////////// { int addr = 0; unpacker & addr; packer & int(_dev->readRegister(unsigned(addr))); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_WRITE_SETTING: //////////////////////////////////////////////////////////////////// { std::string key; std::string value; unpacker & key; unpacker & value; _dev->writeSetting(key, value); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_READ_SETTING: //////////////////////////////////////////////////////////////////// { std::string key; unpacker & key; packer & _dev->readSetting(key); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_LIST_GPIO_BANKS: //////////////////////////////////////////////////////////////////// { packer & _dev->listGPIOBanks(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_WRITE_GPIO: //////////////////////////////////////////////////////////////////// { std::string bank; int value = 0; unpacker & bank; unpacker & value; _dev->writeGPIO(bank, unsigned(value)); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_WRITE_GPIO_MASKED: //////////////////////////////////////////////////////////////////// { std::string bank; int value = 0; int mask = 0; unpacker & bank; unpacker & value; unpacker & mask; _dev->writeGPIO(bank, unsigned(value), unsigned(mask)); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_READ_GPIO: //////////////////////////////////////////////////////////////////// { std::string bank; unpacker & bank; packer & int(_dev->readGPIO(bank)); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_WRITE_GPIO_DIR: //////////////////////////////////////////////////////////////////// { std::string bank; int dir = 0; unpacker & bank; unpacker & dir; _dev->writeGPIODir(bank, unsigned(dir)); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_WRITE_GPIO_DIR_MASKED: //////////////////////////////////////////////////////////////////// { std::string bank; int dir = 0; int mask = 0; unpacker & bank; unpacker & dir; unpacker & mask; _dev->writeGPIODir(bank, unsigned(dir), unsigned(mask)); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_READ_GPIO_DIR: //////////////////////////////////////////////////////////////////// { std::string bank; unpacker & bank; packer & int(_dev->readGPIODir(bank)); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_WRITE_I2C: //////////////////////////////////////////////////////////////////// { int addr = 0; std::string data; unpacker & addr; unpacker & data; _dev->writeI2C(addr, data); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_READ_I2C: //////////////////////////////////////////////////////////////////// { int addr = 0; int numBytes = 0; unpacker & addr; unpacker & numBytes; packer & _dev->readI2C(addr, unsigned(numBytes)); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_TRANSACT_SPI: //////////////////////////////////////////////////////////////////// { int addr = 0; int data = 0; int numBits = 0; unpacker & addr; unpacker & data; unpacker & numBits; packer & int(_dev->transactSPI(addr, unsigned(data), size_t(numBits))); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_LIST_UARTS: //////////////////////////////////////////////////////////////////// { packer & _dev->listUARTs(); } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_WRITE_UART: //////////////////////////////////////////////////////////////////// { std::string which; std::string data; unpacker & which; unpacker & data; _dev->writeUART(which, data); packer & SOAPY_REMOTE_VOID; } break; //////////////////////////////////////////////////////////////////// case SOAPY_REMOTE_READ_UART: //////////////////////////////////////////////////////////////////// { std::string which; int timeoutUs = 0; unpacker & which; unpacker & timeoutUs; packer & _dev->readUART(which, long(timeoutUs)); } break; default: throw std::runtime_error( "SoapyClientHandler::handleOnce("+std::to_string(int(call))+") unknown call"); } return call != SOAPY_REMOTE_HANGUP; }