//
// Copyright 2013-2014 Ettus Research LLC
//
// 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, either 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 for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
//
#include
#include
#define NI_VENDOR_NUM 0x1093
#define VERSION_BUILD_SHIFT 0
#define VERSION_PHASE_SHIFT 14
#define VERSION_MAINT_SHIFT 16
#define VERSION_UPGRD_SHIFT 20
#define VERSION_MAJOR_SHIFT 24
#define VERSION_BUILD_MASK 0x00003FFF
#define VERSION_PHASE_MASK 0x0000C000
#define VERSION_MAINT_MASK 0x000F0000
#define VERSION_UPGRD_MASK 0x00F00000
#define VERSION_MAJOR_MASK 0xFF000000
#define GET_FIFO_MEMORY_TYPE(fifo_inst) (static_cast(0x0100 | static_cast(fifo_inst)))
#ifdef __clang__
#pragma GCC diagnostic push ignored "-Wmissing-field-initializers"
#elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#endif
namespace uhd { namespace niusrprio
{
//-------------------------------------------------------
// niriok_proxy
//-------------------------------------------------------
niriok_proxy::niriok_proxy(): _device_handle(nirio_driver_iface::INVALID_RIO_HANDLE)
{
}
niriok_proxy::~niriok_proxy()
{
close();
}
nirio_status niriok_proxy::open(const std::string& interface_path)
{
if (interface_path.empty()) return NiRio_Status_ResourceNotFound;
//close if already open.
close();
nirio_status status = NiRio_Status_Success;
nirio_status_chain(nirio_driver_iface::rio_open(
interface_path, _device_handle), status);
if (nirio_status_not_fatal(status)) {
nirio_status_chain(nirio_driver_iface::rio_ioctl(_device_handle,
nirio_driver_iface::NIRIO_IOCTL_POST_OPEN,
NULL, 0, NULL, 0), status);
nirio_driver_iface::nirio_ioctl_packet_t out(&_interface_num, sizeof(_interface_num), 0);
nirio_status_chain(nirio_driver_iface::rio_ioctl(_device_handle,
nirio_driver_iface::NIRIO_IOCTL_GET_IFACE_NUM,
NULL, 0,
&out, sizeof(out)), status);
if (nirio_status_fatal(status)) close();
}
return status;
}
void niriok_proxy::close(void)
{
if(nirio_driver_iface::rio_isopen(_device_handle))
{
nirio_driver_iface::rio_ioctl(
_device_handle, nirio_driver_iface::NIRIO_IOCTL_PRE_CLOSE, NULL, 0, NULL, 0);
nirio_driver_iface::rio_close(_device_handle);
}
}
nirio_status niriok_proxy::reset()
{
nirio_driver_iface::nirio_syncop_in_params_t in = {};
nirio_driver_iface::nirio_syncop_out_params_t out = {};
in.function = nirio_driver_iface::NIRIO_FUNC::RESET;
return sync_operation(&in, sizeof(in), &out, sizeof(out));
}
nirio_status niriok_proxy::get_cached_session(
uint32_t& session)
{
nirio_driver_iface::nirio_ioctl_packet_t out(&session, sizeof(session), 0);
return nirio_driver_iface::rio_ioctl(_device_handle,
nirio_driver_iface::NIRIO_IOCTL_GET_SESSION,
NULL, 0,
&out, sizeof(out));
}
nirio_status niriok_proxy::get_version(
nirio_version_t type,
uint32_t& major,
uint32_t& upgrade,
uint32_t& maintenance,
char& phase,
uint32_t& build)
{
nirio_device_attr_32_t version_attr = (type==CURRENT)?CURRENT_VERSION:OLDEST_COMPATIBLE_VERSION;
uint32_t raw_version = 0;
nirio_status status = get_attribute(version_attr, raw_version);
major = (raw_version & VERSION_MAJOR_MASK) >> VERSION_MAJOR_SHIFT;
upgrade = (raw_version & VERSION_UPGRD_MASK) >> VERSION_UPGRD_SHIFT;
maintenance = (raw_version & VERSION_MAINT_MASK) >> VERSION_MAINT_SHIFT;
build = (raw_version & VERSION_BUILD_MASK) >> VERSION_BUILD_SHIFT;
uint32_t phase_num = (raw_version & VERSION_PHASE_MASK) >> VERSION_PHASE_SHIFT;
switch (phase_num) {
case 0: phase = 'd'; break;
case 1: phase = 'a'; break;
case 2: phase = 'b'; break;
case 3: phase = 'f'; break;
}
return status;
}
nirio_status niriok_proxy::sync_operation(
const void *writeBuffer,
size_t writeBufferLength,
void *readBuffer,
size_t readBufferLength)
{
nirio_driver_iface::nirio_ioctl_packet_t out(readBuffer, readBufferLength, 0);
nirio_status ioctl_status = nirio_driver_iface::rio_ioctl(_device_handle,
nirio_driver_iface::NIRIO_IOCTL_SYNCOP,
writeBuffer, writeBufferLength,
&out, sizeof(out));
if (nirio_status_fatal(ioctl_status)) return ioctl_status;
return out.statusCode;
}
nirio_status niriok_proxy::get_attribute(
const nirio_device_attr_32_t attribute,
uint32_t& attrValue)
{
nirio_driver_iface::nirio_syncop_in_params_t in = {};
nirio_driver_iface::nirio_syncop_out_params_t out = {};
in.function = nirio_driver_iface::NIRIO_FUNC::GET32;
in.params.attribute32.attribute = attribute;
nirio_status status = sync_operation(&in, sizeof(in), &out, sizeof(out));
attrValue = out.params.attribute32.value;
return status;
}
nirio_status niriok_proxy::get_attribute(
const nirio_device_attr_str_t attribute,
char *buf,
const uint32_t bufLen,
uint32_t& stringLen)
{
nirio_driver_iface::nirio_syncop_in_params_t in = {};
nirio_driver_iface::nirio_syncop_out_params_t out = {};
nirio_driver_iface::init_syncop_out_params(out, buf, bufLen);
in.function = nirio_driver_iface::NIRIO_FUNC::GET_STRING;
in.params.attributeStr.attribute = attribute;
nirio_status status = sync_operation(&in, sizeof(in), &out, sizeof(out));
stringLen = out.params.stringLength;
return status;
}
nirio_status niriok_proxy::set_attribute(
const nirio_device_attr_32_t attribute,
const uint32_t value)
{
nirio_driver_iface::nirio_syncop_in_params_t in = {};
nirio_driver_iface::nirio_syncop_out_params_t out = {};
in.function = nirio_driver_iface::NIRIO_FUNC::SET32;
in.params.attribute32.attribute = attribute;
in.params.attribute32.value = value;
return sync_operation(&in, sizeof(in), &out, sizeof(out));
}
nirio_status niriok_proxy::set_attribute(
const nirio_device_attr_str_t attribute,
const char* const buffer)
{
nirio_driver_iface::nirio_syncop_in_params_t in = {};
nirio_driver_iface::init_syncop_in_params(in, buffer, strlen(buffer) + 1);
nirio_driver_iface::nirio_syncop_out_params_t out = {};
in.function = nirio_driver_iface::NIRIO_FUNC::SET_STRING;
in.params.attributeStr.attribute = attribute;
return sync_operation(&in, sizeof(in), &out, sizeof(out));
}
nirio_status niriok_proxy::peek(uint32_t offset, uint32_t& value)
{
if (offset % 4 != 0) return NiRio_Status_MisalignedAccess;
nirio_driver_iface::nirio_syncop_in_params_t in = {};
nirio_driver_iface::nirio_syncop_out_params_t out = {};
in.function = nirio_driver_iface::NIRIO_FUNC::IO;
in.subfunction = nirio_driver_iface::NIRIO_IO::PEEK32;
in.params.io.offset = offset;
nirio_status status = sync_operation(&in, sizeof(in), &out, sizeof(out));
value = out.params.io.value.value32;
return status;
}
nirio_status niriok_proxy::peek(uint32_t offset, uint64_t& value)
{
if (offset % 8 != 0) return NiRio_Status_MisalignedAccess;
nirio_driver_iface::nirio_syncop_in_params_t in = {};
nirio_driver_iface::nirio_syncop_out_params_t out = {};
in.function = nirio_driver_iface::NIRIO_FUNC::IO;
in.subfunction = nirio_driver_iface::NIRIO_IO::PEEK64;
in.params.io.offset = offset;
nirio_status status = sync_operation(&in, sizeof(in), &out, sizeof(out));
value = out.params.io.value.value64;
return status;
}
nirio_status niriok_proxy::poke(uint32_t offset, const uint32_t& value)
{
if (offset % 4 != 0) return NiRio_Status_MisalignedAccess;
nirio_driver_iface::nirio_syncop_in_params_t in = {};
nirio_driver_iface::nirio_syncop_out_params_t out = {};
in.function = nirio_driver_iface::NIRIO_FUNC::IO;
in.subfunction = nirio_driver_iface::NIRIO_IO::POKE32;
in.params.io.offset = offset;
in.params.io.value.value32 = value;
return sync_operation(&in, sizeof(in), &out, sizeof(out));
}
nirio_status niriok_proxy::poke(uint32_t offset, const uint64_t& value)
{
if (offset % 8 != 0) return NiRio_Status_MisalignedAccess;
nirio_driver_iface::nirio_syncop_in_params_t in = {};
nirio_driver_iface::nirio_syncop_out_params_t out = {};
in.function = nirio_driver_iface::NIRIO_FUNC::IO;
in.subfunction = nirio_driver_iface::NIRIO_IO::POKE64;
in.params.io.offset = offset;
in.params.io.value.value64 = value;
return sync_operation(&in, sizeof(in), &out, sizeof(out));
}
nirio_status niriok_proxy::map_fifo_memory(
uint32_t fifo_instance,
size_t size,
nirio_driver_iface::rio_mmap_t& map)
{
return nirio_driver_iface::rio_mmap(_device_handle,
GET_FIFO_MEMORY_TYPE(fifo_instance),
size, true, map);
}
nirio_status niriok_proxy::unmap_fifo_memory(
nirio_driver_iface::rio_mmap_t& map)
{
return nirio_driver_iface::rio_munmap(map);
}
nirio_status niriok_proxy::stop_all_fifos()
{
nirio_driver_iface::nirio_syncop_in_params_t in = {};
nirio_driver_iface::nirio_syncop_out_params_t out = {};
in.function = nirio_driver_iface::NIRIO_FUNC::FIFO_STOP_ALL;
return sync_operation(&in, sizeof(in), &out, sizeof(out));
}
}}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif