diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..7592debf --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +open_collective: osmocom diff --git a/.gitignore b/.gitignore index 5ef05322..3e06be81 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,8 @@ config.log config.status config.guess configure +configure~ +compile depcomp missing ltmain.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index abc8f9b8..1ff6c9aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,46 +1,49 @@ -# Copyright 2012 OSMOCOM Project +# Copyright 2012-2020 Osmocom Project # # This file is part of rtl-sdr # -# GNU Radio is free software; you can redistribute it and/or modify +# 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, or (at your option) -# any later version. +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. # -# GNU Radio is distributed in the hope that it will be useful, +# 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. +# along with this program. If not, see . ######################################################################## # Project setup ######################################################################## -cmake_minimum_required(VERSION 2.6) -project(rtlsdr C) +cmake_minimum_required(VERSION 3.7.2) + +# workaround for https://gitlab.kitware.com/cmake/cmake/issues/16967 +if(${CMAKE_VERSION} VERSION_LESS "3.12.0") + project(rtlsdr) +else() + project(rtlsdr C) +endif() #select the release build type by default to get optimization flags if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release") message(STATUS "Build type not specified: defaulting to release.") endif(NOT CMAKE_BUILD_TYPE) -set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "") -list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) +list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/Modules) -if(NOT LIB_INSTALL_DIR) - set(LIB_INSTALL_DIR lib) -endif() +include(GNUInstallDirs) +include(GenerateExportHeader) +include(CMakePackageConfigHelpers) # Set the version information here -set(VERSION_INFO_MAJOR_VERSION 0) # increment major on api compatibility changes -set(VERSION_INFO_MINOR_VERSION 6) # increment minor on feature-level changes -set(VERSION_INFO_PATCH_VERSION git) # increment patch for bug fixes and docs +set(VERSION_INFO_MAJOR_VERSION 2) # increment major on api compatibility changes +set(VERSION_INFO_MINOR_VERSION 0) # increment minor on feature-level changes +set(VERSION_INFO_PATCH_VERSION 1) # increment patch for bug fixes and docs include(Version) # setup version info ######################################################################## @@ -63,40 +66,39 @@ endif() ######################################################################## # Find build dependencies ######################################################################## +find_package(Threads) find_package(PkgConfig) -find_package(LibUSB) -if(WIN32 AND NOT MINGW) - set(THREADS_USE_PTHREADS_WIN32 true) + +if(PKG_CONFIG_FOUND) + pkg_check_modules(LIBUSB libusb-1.0 IMPORTED_TARGET) + if(LIBUSB_LINK_LIBRARIES) + set(LIBUSB_LIBRARIES "${LIBUSB_LINK_LIBRARIES}") + endif() +else() + set(LIBUSB_LIBRARIES "" CACHE STRING "manual libusb path") + set(LIBUSB_INCLUDE_DIRS "" CACHE STRING "manual libusb includepath") +endif() + +if(MSVC) + set(THREADS_PTHREADS_LIBRARY "" CACHE STRING "manual pthread-win32 path") + set(THREADS_PTHREADS_INCLUDE_DIR "" CACHE STRING "manual pthread-win32 includepath") +else() + set(THREADS_PTHREADS_LIBRARY "" CACHE INTERNAL "manual pthread-win32 path") + set(THREADS_PTHREADS_INCLUDE_DIR "" CACHE INTERNAL "manual pthread-win32 includepath") endif() -find_package(Threads) -if(NOT LIBUSB_FOUND) +if(PKG_CONFIG_FOUND AND NOT LIBUSB_FOUND) message(FATAL_ERROR "LibUSB 1.0 required to compile rtl-sdr") endif() if(NOT THREADS_FOUND) message(FATAL_ERROR "pthreads(-win32) required to compile rtl-sdr") endif() -######################################################################## -# Setup the include and linker paths -######################################################################## -include_directories( - ${CMAKE_SOURCE_DIR}/include - ${LIBUSB_INCLUDE_DIR} - ${THREADS_PTHREADS_INCLUDE_DIR} -) - -#link_directories( -# ... -#) - -# Set component parameters -#set(INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include CACHE INTERNAL "" FORCE) ######################################################################## # Create uninstall target ######################################################################## configure_file( - ${CMAKE_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in + ${PROJECT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake @ONLY) @@ -126,16 +128,32 @@ else (DETACH_KERNEL_DRIVER) message (STATUS "Building with kernel driver detaching disabled, use -DDETACH_KERNEL_DRIVER=ON to enable") endif (DETACH_KERNEL_DRIVER) +option(ENABLE_ZEROCOPY "Enable usbfs zero-copy support" OFF) +if (ENABLE_ZEROCOPY) + message (STATUS "Building with usbfs zero-copy support enabled") + add_definitions(-DENABLE_ZEROCOPY=1) +else (ENABLE_ZEROCOPY) + message (STATUS "Building with usbfs zero-copy support disabled, use -DENABLE_ZEROCOPY=ON to enable") +endif (ENABLE_ZEROCOPY) + +######################################################################## +# Install public header files +######################################################################## +install(FILES + include/rtl-sdr.h + include/rtl-sdr_export.h + DESTINATION include +) + ######################################################################## # Add subdirectories ######################################################################## -add_subdirectory(include) add_subdirectory(src) ######################################################################## # Create Pkg Config File ######################################################################## -FOREACH(inc ${LIBUSB_INCLUDE_DIR}) +FOREACH(inc ${LIBUSB_INCLUDEDIR}) LIST(APPEND RTLSDR_PC_CFLAGS "-I${inc}") ENDFOREACH(inc) @@ -153,10 +171,10 @@ IF(CMAKE_CROSSCOMPILING) UNSET(RTLSDR_PC_LIBS) ENDIF(CMAKE_CROSSCOMPILING) -set(prefix ${CMAKE_INSTALL_PREFIX}) +set(prefix "${CMAKE_INSTALL_PREFIX}") set(exec_prefix \${prefix}) -set(libdir \${exec_prefix}/${LIB_INSTALL_DIR}) set(includedir \${prefix}/include) +set(libdir \${exec_prefix}/lib) CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/librtlsdr.pc.in @@ -165,9 +183,37 @@ CONFIGURE_FILE( INSTALL( FILES ${CMAKE_CURRENT_BINARY_DIR}/librtlsdr.pc - DESTINATION ${LIB_INSTALL_DIR}/pkgconfig + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig ) +######################################################################## +# Create CMake Config File +######################################################################## +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/rtlsdr/rtlsdrConfigVersion.cmake" + VERSION ${VERSION} + COMPATIBILITY AnyNewerVersion + ) + +configure_file(cmake/rtlsdrConfig.cmake + "${CMAKE_CURRENT_BINARY_DIR}/rtlsdr/rtlsdrConfig.cmake" + COPYONLY + ) + +set(ConfigPackageLocation lib/cmake/rtlsdr) +install(EXPORT RTLSDR-export + FILE rtlsdrTargets.cmake + NAMESPACE rtlsdr:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/rtlsdr/ + ) +install( + FILES + cmake/rtlsdrConfig.cmake + "${CMAKE_CURRENT_BINARY_DIR}/rtlsdr/rtlsdrConfigVersion.cmake" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/rtlsdr/ + COMPONENT Devel + ) + ######################################################################## # Print Summary ######################################################################## diff --git a/cmake/Modules/FindLibUSB.cmake b/cmake/Modules/FindLibUSB.cmake deleted file mode 100644 index c2c3f632..00000000 --- a/cmake/Modules/FindLibUSB.cmake +++ /dev/null @@ -1,55 +0,0 @@ -if(NOT LIBUSB_FOUND) - pkg_check_modules (LIBUSB_PKG libusb-1.0) - find_path(LIBUSB_INCLUDE_DIR NAMES libusb.h - PATHS - ${LIBUSB_PKG_INCLUDE_DIRS} - /usr/include/libusb-1.0 - /usr/include - /usr/local/include - ) - -#standard library name for libusb-1.0 -set(libusb1_library_names usb-1.0) - -#libusb-1.0 compatible library on freebsd -if((CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") OR (CMAKE_SYSTEM_NAME STREQUAL "kFreeBSD")) - list(APPEND libusb1_library_names usb) -endif() - - find_library(LIBUSB_LIBRARIES - NAMES ${libusb1_library_names} - PATHS - ${LIBUSB_PKG_LIBRARY_DIRS} - /usr/lib - /usr/local/lib - ) - -include(CheckFunctionExists) -if(LIBUSB_INCLUDE_DIRS) - set(CMAKE_REQUIRED_INCLUDES ${LIBUSB_INCLUDE_DIRS}) -endif() -if(LIBUSB_LIBRARIES) - set(CMAKE_REQUIRED_LIBRARIES ${LIBUSB_LIBRARIES}) -endif() - -CHECK_FUNCTION_EXISTS("libusb_handle_events_timeout_completed" HAVE_LIBUSB_HANDLE_EVENTS_TIMEOUT_COMPLETED) -if(HAVE_LIBUSB_HANDLE_EVENTS_TIMEOUT_COMPLETED) - add_definitions(-DHAVE_LIBUSB_HANDLE_EVENTS_TIMEOUT_COMPLETED=1) -endif(HAVE_LIBUSB_HANDLE_EVENTS_TIMEOUT_COMPLETED) - -CHECK_FUNCTION_EXISTS("libusb_error_name" HAVE_LIBUSB_ERROR_NAME) -if(HAVE_LIBUSB_ERROR_NAME) - add_definitions(-DHAVE_LIBUSB_ERROR_NAME=1) -endif(HAVE_LIBUSB_ERROR_NAME) - -if(LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES) - set(LIBUSB_FOUND TRUE CACHE INTERNAL "libusb-1.0 found") - message(STATUS "Found libusb-1.0: ${LIBUSB_INCLUDE_DIR}, ${LIBUSB_LIBRARIES}") -else(LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES) - set(LIBUSB_FOUND FALSE CACHE INTERNAL "libusb-1.0 found") - message(STATUS "libusb-1.0 not found.") -endif(LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES) - -mark_as_advanced(LIBUSB_INCLUDE_DIR LIBUSB_LIBRARIES) - -endif(NOT LIBUSB_FOUND) diff --git a/cmake/Modules/FindThreads.cmake b/cmake/Modules/FindThreads.cmake deleted file mode 100644 index 8028b158..00000000 --- a/cmake/Modules/FindThreads.cmake +++ /dev/null @@ -1,246 +0,0 @@ -# Updated FindThreads.cmake that supports pthread-win32 -# Downloaded from http://www.vtk.org/Bug/bug_view_advanced_page.php?bug_id=6399 - -# - This module determines the thread library of the system. -# -# The following variables are set -# CMAKE_THREAD_LIBS_INIT - the thread library -# CMAKE_USE_SPROC_INIT - are we using sproc? -# CMAKE_USE_WIN32_THREADS_INIT - using WIN32 threads? -# CMAKE_USE_PTHREADS_INIT - are we using pthreads -# CMAKE_HP_PTHREADS_INIT - are we using hp pthreads -# -# If use of pthreads-win32 is desired, the following variables -# can be set. -# -# THREADS_USE_PTHREADS_WIN32 - -# Setting this to true searches for the pthreads-win32 -# port (since CMake 2.8.0) -# -# THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME -# C = no exceptions (default) -# (NOTE: This is the default scheme on most POSIX thread -# implementations and what you should probably be using) -# CE = C++ Exception Handling -# SE = Structure Exception Handling (MSVC only) -# (NOTE: Changing this option from the default may affect -# the portability of your application. See pthreads-win32 -# documentation for more details.) -# -#====================================================== -# Example usage where threading library -# is provided by the system: -# -# find_package(Threads REQUIRED) -# add_executable(foo foo.cc) -# target_link_libraries(foo ${CMAKE_THREAD_LIBS_INIT}) -# -# Example usage if pthreads-win32 is desired on Windows -# or a system provided thread library: -# -# set(THREADS_USE_PTHREADS_WIN32 true) -# find_package(Threads REQUIRED) -# include_directories(${THREADS_PTHREADS_INCLUDE_DIR}) -# -# add_executable(foo foo.cc) -# target_link_libraries(foo ${CMAKE_THREAD_LIBS_INIT}) -# - -INCLUDE (CheckIncludeFiles) -INCLUDE (CheckLibraryExists) -SET(Threads_FOUND FALSE) - -IF(WIN32 AND NOT CYGWIN AND THREADS_USE_PTHREADS_WIN32) - SET(_Threads_ptwin32 true) -ENDIF() - -# Do we have sproc? -IF(CMAKE_SYSTEM MATCHES IRIX) - CHECK_INCLUDE_FILES("sys/types.h;sys/prctl.h" CMAKE_HAVE_SPROC_H) -ENDIF() - -IF(CMAKE_HAVE_SPROC_H) - # We have sproc - SET(CMAKE_USE_SPROC_INIT 1) - -ELSEIF(_Threads_ptwin32) - - IF(NOT DEFINED THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME) - # Assign the default scheme - SET(THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME "C") - ELSE() - # Validate the scheme specified by the user - IF(NOT THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "C" AND - NOT THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "CE" AND - NOT THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "SE") - MESSAGE(FATAL_ERROR "See documentation for FindPthreads.cmake, only C, CE, and SE modes are allowed") - ENDIF() - IF(NOT MSVC AND THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "SE") - MESSAGE(FATAL_ERROR "Structured Exception Handling is only allowed for MSVC") - ENDIF(NOT MSVC AND THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "SE") - ENDIF() - - FIND_PATH(THREADS_PTHREADS_INCLUDE_DIR pthread.h) - - # Determine the library filename - IF(MSVC) - SET(_Threads_pthreads_libname - pthreadV${THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME}2) - ELSEIF(MINGW) - SET(_Threads_pthreads_libname - pthreadG${THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME}2) - ELSE() - MESSAGE(FATAL_ERROR "This should never happen") - ENDIF() - - # Use the include path to help find the library if possible - SET(_Threads_lib_paths "") - IF(THREADS_PTHREADS_INCLUDE_DIR) - GET_FILENAME_COMPONENT(_Threads_root_dir - ${THREADS_PTHREADS_INCLUDE_DIR} PATH) - SET(_Threads_lib_paths ${_Threads_root_dir}/lib) - ENDIF() - FIND_LIBRARY(THREADS_PTHREADS_WIN32_LIBRARY - NAMES ${_Threads_pthreads_libname} - PATHS ${_Threads_lib_paths} - DOC "The Portable Threads Library for Win32" - NO_SYSTEM_PATH - ) - - IF(THREADS_PTHREADS_INCLUDE_DIR AND THREADS_PTHREADS_WIN32_LIBRARY) - MARK_AS_ADVANCED(THREADS_PTHREADS_INCLUDE_DIR) - SET(CMAKE_THREAD_LIBS_INIT ${THREADS_PTHREADS_WIN32_LIBRARY}) - SET(CMAKE_HAVE_THREADS_LIBRARY 1) - SET(Threads_FOUND TRUE) - ENDIF() - - MARK_AS_ADVANCED(THREADS_PTHREADS_WIN32_LIBRARY) - -ELSE() - # Do we have pthreads? - CHECK_INCLUDE_FILES("pthread.h" CMAKE_HAVE_PTHREAD_H) - IF(CMAKE_HAVE_PTHREAD_H) - - # - # We have pthread.h - # Let's check for the library now. - # - SET(CMAKE_HAVE_THREADS_LIBRARY) - IF(NOT THREADS_HAVE_PTHREAD_ARG) - - # Do we have -lpthreads - CHECK_LIBRARY_EXISTS(pthreads pthread_create "" CMAKE_HAVE_PTHREADS_CREATE) - IF(CMAKE_HAVE_PTHREADS_CREATE) - SET(CMAKE_THREAD_LIBS_INIT "-lpthreads") - SET(CMAKE_HAVE_THREADS_LIBRARY 1) - SET(Threads_FOUND TRUE) - ENDIF() - - # Ok, how about -lpthread - CHECK_LIBRARY_EXISTS(pthread pthread_create "" CMAKE_HAVE_PTHREAD_CREATE) - IF(CMAKE_HAVE_PTHREAD_CREATE) - SET(CMAKE_THREAD_LIBS_INIT "-lpthread") - SET(Threads_FOUND TRUE) - SET(CMAKE_HAVE_THREADS_LIBRARY 1) - ENDIF() - - IF(CMAKE_SYSTEM MATCHES "SunOS.*") - # On sun also check for -lthread - CHECK_LIBRARY_EXISTS(thread thr_create "" CMAKE_HAVE_THR_CREATE) - IF(CMAKE_HAVE_THR_CREATE) - SET(CMAKE_THREAD_LIBS_INIT "-lthread") - SET(CMAKE_HAVE_THREADS_LIBRARY 1) - SET(Threads_FOUND TRUE) - ENDIF() - ENDIF(CMAKE_SYSTEM MATCHES "SunOS.*") - - ENDIF(NOT THREADS_HAVE_PTHREAD_ARG) - - IF(NOT CMAKE_HAVE_THREADS_LIBRARY) - # If we did not found -lpthread, -lpthread, or -lthread, look for -pthread - IF("THREADS_HAVE_PTHREAD_ARG" MATCHES "^THREADS_HAVE_PTHREAD_ARG") - MESSAGE(STATUS "Check if compiler accepts -pthread") - TRY_RUN(THREADS_PTHREAD_ARG THREADS_HAVE_PTHREAD_ARG - ${CMAKE_BINARY_DIR} - ${CMAKE_ROOT}/Modules/CheckForPthreads.c - CMAKE_FLAGS -DLINK_LIBRARIES:STRING=-pthread - COMPILE_OUTPUT_VARIABLE OUTPUT) - - IF(THREADS_HAVE_PTHREAD_ARG) - IF(THREADS_PTHREAD_ARG MATCHES "^2$") - SET(Threads_FOUND TRUE) - MESSAGE(STATUS "Check if compiler accepts -pthread - yes") - ELSE() - MESSAGE(STATUS "Check if compiler accepts -pthread - no") - FILE(APPEND - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log - "Determining if compiler accepts -pthread returned ${THREADS_PTHREAD_ARG} instead of 2. The compiler had the following output:\n${OUTPUT}\n\n") - ENDIF() - ELSE() - MESSAGE(STATUS "Check if compiler accepts -pthread - no") - FILE(APPEND - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log - "Determining if compiler accepts -pthread failed with the following output:\n${OUTPUT}\n\n") - ENDIF() - - ENDIF("THREADS_HAVE_PTHREAD_ARG" MATCHES "^THREADS_HAVE_PTHREAD_ARG") - - IF(THREADS_HAVE_PTHREAD_ARG) - SET(Threads_FOUND TRUE) - SET(CMAKE_THREAD_LIBS_INIT "-pthread") - ENDIF() - - ENDIF(NOT CMAKE_HAVE_THREADS_LIBRARY) - ENDIF(CMAKE_HAVE_PTHREAD_H) -ENDIF() - -IF(CMAKE_THREAD_LIBS_INIT) - SET(CMAKE_USE_PTHREADS_INIT 1) - SET(Threads_FOUND TRUE) -ENDIF() - -IF(CMAKE_SYSTEM MATCHES "Windows" - AND NOT THREADS_USE_PTHREADS_WIN32) - SET(CMAKE_USE_WIN32_THREADS_INIT 1) - SET(Threads_FOUND TRUE) -ENDIF() - -IF(CMAKE_USE_PTHREADS_INIT) - IF(CMAKE_SYSTEM MATCHES "HP-UX-*") - # Use libcma if it exists and can be used. It provides more - # symbols than the plain pthread library. CMA threads - # have actually been deprecated: - # http://docs.hp.com/en/B3920-90091/ch12s03.html#d0e11395 - # http://docs.hp.com/en/947/d8.html - # but we need to maintain compatibility here. - # The CMAKE_HP_PTHREADS setting actually indicates whether CMA threads - # are available. - CHECK_LIBRARY_EXISTS(cma pthread_attr_create "" CMAKE_HAVE_HP_CMA) - IF(CMAKE_HAVE_HP_CMA) - SET(CMAKE_THREAD_LIBS_INIT "-lcma") - SET(CMAKE_HP_PTHREADS_INIT 1) - SET(Threads_FOUND TRUE) - ENDIF(CMAKE_HAVE_HP_CMA) - SET(CMAKE_USE_PTHREADS_INIT 1) - ENDIF() - - IF(CMAKE_SYSTEM MATCHES "OSF1-V*") - SET(CMAKE_USE_PTHREADS_INIT 0) - SET(CMAKE_THREAD_LIBS_INIT ) - ENDIF() - - IF(CMAKE_SYSTEM MATCHES "CYGWIN_NT*") - SET(CMAKE_USE_PTHREADS_INIT 1) - SET(Threads_FOUND TRUE) - SET(CMAKE_THREAD_LIBS_INIT ) - SET(CMAKE_USE_WIN32_THREADS_INIT 0) - ENDIF() -ENDIF(CMAKE_USE_PTHREADS_INIT) - -INCLUDE(FindPackageHandleStandardArgs) -IF(_Threads_ptwin32) - FIND_PACKAGE_HANDLE_STANDARD_ARGS(Threads DEFAULT_MSG - THREADS_PTHREADS_WIN32_LIBRARY THREADS_PTHREADS_INCLUDE_DIR) -ELSE() - FIND_PACKAGE_HANDLE_STANDARD_ARGS(Threads DEFAULT_MSG Threads_FOUND) -ENDIF() diff --git a/cmake/rtlsdrConfig.cmake b/cmake/rtlsdrConfig.cmake new file mode 100644 index 00000000..eeff2f3d --- /dev/null +++ b/cmake/rtlsdrConfig.cmake @@ -0,0 +1,8 @@ +include(FindPkgConfig) +pkg_check_modules(LIBUSB libusb-1.0 IMPORTED_TARGET) + +get_filename_component(RTLSDR_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) + +if(NOT TARGET rtlsdr::rtlsdr) + include("${RTLSDR_CMAKE_DIR}/rtlsdrTargets.cmake") +endif() diff --git a/configure.ac b/configure.ac index 5b948284..1afbfbd2 100644 --- a/configure.ac +++ b/configure.ac @@ -101,6 +101,12 @@ AC_ARG_ENABLE(driver-detach, CFLAGS="$CFLAGS -DDETACH_KERNEL_DRIVER" fi]) +AC_ARG_ENABLE(zerocopy, +[ --enable-zerocopy Enable usbfs zero-copy support (disabled by default)], +[if test x$enableval = xyes; then + CFLAGS="$CFLAGS -DENABLE_ZEROCOPY" +fi]) + dnl Generate the output AC_CONFIG_HEADER(config.h) diff --git a/contrib/jenkins.sh b/contrib/jenkins.sh index cb566f13..05384064 100755 --- a/contrib/jenkins.sh +++ b/contrib/jenkins.sh @@ -36,5 +36,6 @@ LD_LIBRARY_PATH="$inst/lib" \ DISTCHECK_CONFIGURE_FLAGS="--enable-werror" \ $MAKE distcheck \ || cat-testlogs.sh +$MAKE maintainer-clean osmo-clean-workspace.sh diff --git a/debian/changelog b/debian/changelog index 24d97e27..48afa2ee 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,95 @@ -rtl-sdr (0.6git) unstable; urgency=medium +rtl-sdr (2.0.2) unstable; urgency=medium + + [ Mikael Falkvidd ] + * Fix small typo in rtl_sdr man page + + [ Clayton Smith ] + * Use library paths from pkg-config + * Only use LIBUSB_LINK_LIBRARIES if it exists + + [ hayati ayguen ] + * improve CLI usage docs: '-d' also accepts serial + + [ Oliver Jowett ] + * r82xx: improve tuner precision + + [ Sultan Qasim Khan ] + * r82xx: avoid redundant register writes for speed + * r82xx: batch register writes for tuning + + [ Ethan Halsall ] + * fix: set fc0012 gain to low on init + * fix: round gain input to nearest value + + [ Harald Welte ] + * Add funding link to github mirror + + [ Steve Markgraf ] + * lib: set SOVERSION back to 0 + + -- Oliver Smith Tue, 23 Apr 2024 11:40:18 +0200 + +rtl-sdr (2.0.1) unstable; urgency=medium + + * debian/changelog: update for 2.0.0 and 2.0.1 + * gitignore: add files created by autotools + + -- Oliver Smith Fri, 03 Nov 2023 10:19:41 +0100 + +rtl-sdr (2.0.0) unstable; urgency=medium + + [ Derrick Pallas ] + * tuner_r82xx: fix short-write in r82xx_read + + [ Steve Markgraf ] + * Add rtl_biast as install target + + [ Eric Wild ] + * cmake: populate pkgconfig file with prefix + * fix windows build + + [ David Neiss ] + * rtl_tcp: Extracted some constants out of printf strings + + [ Oliver Smith ] + * rtl_tcp: put new DEFAULT_* constants in defines + + [ Doug Hammond ] + * rtl_fm: add a new option to select 2nd direct sampling mode + + [ Martin Hauke ] + * Fix minGW build + + [ jvde.github ] + * lib: force wait state after cancel of usb transfer + + [ Clayton Smith ] + * lib: Stop applying workaround for libusb < 1.0.9 + + [ Tobias Girstmair ] + * Fix signal handler from getting stuck in an endless loop + + [ rtlsdrblog ] + * add rtl-sdr blog v4 support + * fix rtl_tcp on macos + * fix rtl_tcp error on windows when hints not initialized to 0 + * add blog v4 upconverter gpio switch + * add -D direct sampling flag to rtl_tcp + * add direct sampling to rtl_sdr + + [ Steve Markgraf ] + * change version to 2.0.0 + + -- Oliver Smith Fri, 03 Nov 2023 10:15:31 +0100 + +rtl-sdr (0.6) unstable; urgency=medium + + * New upstream release + * with modernize-cmake patch + + -- A. Maitland Bottoms Sat, 06 Oct 2018 20:28:26 -0400 + +rtl-sdr (0.6~git) unstable; urgency=medium * New upstream release diff --git a/debian/compat b/debian/compat index ec635144..f599e28b 100644 --- a/debian/compat +++ b/debian/compat @@ -1 +1 @@ -9 +10 diff --git a/debian/control b/debian/control index c77877d2..50eb1fb8 100644 --- a/debian/control +++ b/debian/control @@ -3,10 +3,11 @@ Section: comm Priority: optional Maintainer: A. Maitland Bottoms Build-Depends: cmake, - debhelper (>= 9.0.0~), + debhelper (>= 10~), libusb-1.0-0-dev [linux-any], libusb-dev [hurd-i386], - libusb2-dev [kfreebsd-any] + libusb2-dev [kfreebsd-any], + pkg-config Standards-Version: 4.1.4 Homepage: http://sdr.osmocom.org/trac/wiki/rtl-sdr Vcs-Browser: https://salsa.debian.org/bottoms/pkg-rtl-sdr diff --git a/debian/librtlsdr-dev.acc b/debian/librtlsdr-dev.acc new file mode 100644 index 00000000..282f2cd7 --- /dev/null +++ b/debian/librtlsdr-dev.acc @@ -0,0 +1,27 @@ + + + + + -fPIC + -g + -O2 + -fstack-protector-strong + -Wformat + -Werror=format-security + -Wdate-time + -D_FORTIFY_SOURCE=2 + -fvisibility=hidden + -Wsign-compare + -Wall + -Wno-uninitialized + + + +debian/librtlsdr-dev/usr/include/ + + + +debian/librtlsdr0/usr/lib/ + + + diff --git a/debian/librtlsdr-dev.install b/debian/librtlsdr-dev.install index 76f28fa2..c5f05762 100644 --- a/debian/librtlsdr-dev.install +++ b/debian/librtlsdr-dev.install @@ -2,3 +2,4 @@ usr/include/* usr/lib/*/lib*.a usr/lib/*/lib*.so usr/lib/*/pkgconfig/* +usr/lib/*/cmake/* diff --git a/debian/librtlsdr0.udev b/debian/librtlsdr0.udev index b2f4054d..5709870a 100644 --- a/debian/librtlsdr0.udev +++ b/debian/librtlsdr0.udev @@ -13,130 +13,127 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -# +# MODE="0664", GROUP="plugdev" # original RTL2832U vid/pid (hama nano, for example) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2832", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2832", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # RTL2832U OEM vid/pid, e.g. ezcap EzTV668 (E4000), Newsky TV28T (E4000/R820T) etc. -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2838", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2838", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # DigitalNow Quad DVB-T PCI-E card (4x FC0012?) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0413", ATTRS{idProduct}=="6680", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0413", ATTRS{idProduct}=="6680", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Leadtek WinFast DTV Dongle mini D (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0413", ATTRS{idProduct}=="6f0f", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0413", ATTRS{idProduct}=="6f0f", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Genius TVGo DVB-T03 USB dongle (Ver. B) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0458", ATTRS{idProduct}=="707f", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0458", ATTRS{idProduct}=="707f", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec Cinergy T Stick Black (rev 1) (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00a9", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00a9", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec NOXON rev 1 (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b3", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b3", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec Deutschlandradio DAB Stick (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b4", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b4", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec NOXON DAB Stick - Radio Energy (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b5", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b5", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec Media Broadcast DAB Stick (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b7", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b7", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec BR DAB Stick (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b8", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b8", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec WDR DAB Stick (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b9", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b9", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec MuellerVerlag DAB Stick (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00c0", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00c0", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec Fraunhofer DAB Stick (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00c6", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00c6", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec Cinergy T Stick RC (Rev.3) (E4000) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00d3", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00d3", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec T Stick PLUS (E4000) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00d7", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00d7", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec NOXON rev 2 (E4000) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00e0", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00e0", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # PixelView PV-DT235U(RN) (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1554", ATTRS{idProduct}=="5020", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1554", ATTRS{idProduct}=="5020", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Astrometa DVB-T/DVB-T2 (R828D) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="15f4", ATTRS{idProduct}=="0131", MODE:="0666" - -# HanfTek DAB+FM+DVB-T -SUBSYSTEMS=="usb", ATTRS{idVendor}=="15f4", ATTRS{idProduct}=="0133", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="15f4", ATTRS{idProduct}=="0131", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Compro Videomate U620F (E4000) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="185b", ATTRS{idProduct}=="0620", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="185b", ATTRS{idProduct}=="0620", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Compro Videomate U650F (E4000) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="185b", ATTRS{idProduct}=="0650", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="185b", ATTRS{idProduct}=="0650", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Compro Videomate U680F (E4000) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="185b", ATTRS{idProduct}=="0680", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="185b", ATTRS{idProduct}=="0680", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # GIGABYTE GT-U7300 (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d393", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d393", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # DIKOM USB-DVBT HD -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d394", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d394", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Peak 102569AGPK (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d395", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d395", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # KWorld KW-UB450-T USB DVB-T Pico TV (TUA9001) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d397", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d397", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Zaapa ZT-MINDVBZP (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d398", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d398", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # SVEON STV20 DVB-T USB & FM (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d39d", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d39d", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Twintech UT-40 (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d3a4", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d3a4", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # ASUS U3100MINI_PLUS_V2 (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d3a8", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d3a8", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # SVEON STV27 DVB-T USB & FM (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d3af", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d3af", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # SVEON STV21 DVB-T USB & FM -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d3b0", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d3b0", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Dexatek DK DVB-T Dongle (Logilink VG0002A) (FC2580) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d19", ATTRS{idProduct}=="1101", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d19", ATTRS{idProduct}=="1101", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Dexatek DK DVB-T Dongle (MSI DigiVox mini II V3.0) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d19", ATTRS{idProduct}=="1102", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d19", ATTRS{idProduct}=="1102", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Dexatek DK 5217 DVB-T Dongle (FC2580) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d19", ATTRS{idProduct}=="1103", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d19", ATTRS{idProduct}=="1103", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # MSI DigiVox Micro HD (FC2580) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d19", ATTRS{idProduct}=="1104", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d19", ATTRS{idProduct}=="1104", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Sweex DVB-T USB (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="a803", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="a803", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # GTek T803 (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="b803", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="b803", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Lifeview LV5TDeluxe (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="c803", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="c803", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # MyGica TD312 (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="d286", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="d286", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # PROlectrix DV107669 (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="d803", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="d803", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" diff --git a/debian/rtl_sdr.1 b/debian/rtl_sdr.1 index 6b651e28..fba6f71a 100644 --- a/debian/rtl_sdr.1 +++ b/debian/rtl_sdr.1 @@ -26,7 +26,7 @@ This program captures information from a band of frequencies and outputs the data in a form useful to other software radio programs. .SH SYNOPSIS -.B rtl_adsb [-f freq] [OPTIONS] [output file] +.B rtl_sdr [-f freq] [OPTIONS] [output file] .SH OPTIONS .IP "-f frequency_to_tune_to [Hz]" .IP "-s samplerate (default: 2048000 Hz)" diff --git a/debian/rules b/debian/rules index 901ea73c..087f0dc8 100755 --- a/debian/rules +++ b/debian/rules @@ -3,10 +3,16 @@ DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) export DEB_HOST_MULTIARCH %: - dh $@ + dh $@ --buildsystem=cmake override_dh_auto_configure: debian/librtlsdr0.udev - dh_auto_configure -- -DLIB_INSTALL_DIR=lib/$(DEB_HOST_MULTIARCH) -DDETACH_KERNEL_DRIVER=ON + dh_auto_configure --buildsystem=cmake -- -DDETACH_KERNEL_DRIVER=ON \ + -DINSTALL_UDEV_RULES=ON \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo debian/librtlsdr0.udev: rtl-sdr.rules cp -p rtl-sdr.rules debian/librtlsdr0.udev + +override_dh_acc: + - dh_acc + - cat debian/librtlsdr-dev/usr/lib/x86_64-linux-gnu/dh-acc/librtlsdr-dev_*_report.html diff --git a/include/rtl-sdr.h b/include/rtl-sdr.h index 3ed13ae8..d64701ea 100644 --- a/include/rtl-sdr.h +++ b/include/rtl-sdr.h @@ -389,6 +389,17 @@ RTLSDR_API int rtlsdr_cancel_async(rtlsdr_dev_t *dev); */ RTLSDR_API int rtlsdr_set_bias_tee(rtlsdr_dev_t *dev, int on); +/*! + * Enable or disable the bias tee on the given GPIO pin. + * + * \param dev the device handle given by rtlsdr_open() + * \param gpio the gpio pin to configure as a Bias T control. + * \param on 1 for Bias T on. 0 for Bias T off. + * \return -1 if device is not initialized. 0 otherwise. + */ +RTLSDR_API int rtlsdr_set_bias_tee_gpio(rtlsdr_dev_t *dev, int gpio, int on); + + #ifdef __cplusplus } #endif diff --git a/include/rtlsdr_i2c.h b/include/rtlsdr_i2c.h index 76766893..b6838960 100644 --- a/include/rtlsdr_i2c.h +++ b/include/rtlsdr_i2c.h @@ -1,6 +1,8 @@ #ifndef __I2C_H #define __I2C_H +int rtlsdr_check_dongle_model(void *dev, char *manufact_check, char *product_check); +int rtlsdr_set_bias_tee_gpio(void *dev, int gpio, int on); uint32_t rtlsdr_get_tuner_clock(void *dev); int rtlsdr_i2c_write_fn(void *dev, uint8_t addr, uint8_t *buf, int len); int rtlsdr_i2c_read_fn(void *dev, uint8_t addr, uint8_t *buf, int len); diff --git a/librtlsdr.pc.in b/librtlsdr.pc.in index 5e55049a..e46519a5 100644 --- a/librtlsdr.pc.in +++ b/librtlsdr.pc.in @@ -6,6 +6,6 @@ includedir=@includedir@ Name: RTL-SDR Library Description: C Utility Library Version: @VERSION@ -Cflags: -I${includedir}/ @RTLSDR_PC_CFLAGS@ -Libs: -L${libdir} -lrtlsdr -lusb-1.0 -Libs.private: @RTLSDR_PC_LIBS@ +Cflags: -I${includedir}/ +Libs: -L${libdir} -lrtlsdr +Libs.private: -lusb-1.0 @RTLSDR_PC_LIBS@ diff --git a/rtl-sdr.rules b/rtl-sdr.rules index b2f4054d..83fca700 100644 --- a/rtl-sdr.rules +++ b/rtl-sdr.rules @@ -16,127 +16,127 @@ # # original RTL2832U vid/pid (hama nano, for example) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2832", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2832", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # RTL2832U OEM vid/pid, e.g. ezcap EzTV668 (E4000), Newsky TV28T (E4000/R820T) etc. -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2838", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2838", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # DigitalNow Quad DVB-T PCI-E card (4x FC0012?) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0413", ATTRS{idProduct}=="6680", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0413", ATTRS{idProduct}=="6680", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Leadtek WinFast DTV Dongle mini D (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0413", ATTRS{idProduct}=="6f0f", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0413", ATTRS{idProduct}=="6f0f", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Genius TVGo DVB-T03 USB dongle (Ver. B) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0458", ATTRS{idProduct}=="707f", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0458", ATTRS{idProduct}=="707f", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec Cinergy T Stick Black (rev 1) (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00a9", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00a9", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec NOXON rev 1 (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b3", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b3", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec Deutschlandradio DAB Stick (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b4", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b4", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec NOXON DAB Stick - Radio Energy (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b5", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b5", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec Media Broadcast DAB Stick (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b7", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b7", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec BR DAB Stick (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b8", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b8", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec WDR DAB Stick (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b9", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b9", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec MuellerVerlag DAB Stick (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00c0", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00c0", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec Fraunhofer DAB Stick (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00c6", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00c6", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec Cinergy T Stick RC (Rev.3) (E4000) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00d3", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00d3", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec T Stick PLUS (E4000) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00d7", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00d7", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Terratec NOXON rev 2 (E4000) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00e0", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00e0", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # PixelView PV-DT235U(RN) (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1554", ATTRS{idProduct}=="5020", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1554", ATTRS{idProduct}=="5020", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Astrometa DVB-T/DVB-T2 (R828D) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="15f4", ATTRS{idProduct}=="0131", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="15f4", ATTRS{idProduct}=="0131", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # HanfTek DAB+FM+DVB-T -SUBSYSTEMS=="usb", ATTRS{idVendor}=="15f4", ATTRS{idProduct}=="0133", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="15f4", ATTRS{idProduct}=="0133", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Compro Videomate U620F (E4000) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="185b", ATTRS{idProduct}=="0620", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="185b", ATTRS{idProduct}=="0620", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Compro Videomate U650F (E4000) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="185b", ATTRS{idProduct}=="0650", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="185b", ATTRS{idProduct}=="0650", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Compro Videomate U680F (E4000) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="185b", ATTRS{idProduct}=="0680", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="185b", ATTRS{idProduct}=="0680", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # GIGABYTE GT-U7300 (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d393", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d393", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # DIKOM USB-DVBT HD -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d394", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d394", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Peak 102569AGPK (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d395", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d395", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # KWorld KW-UB450-T USB DVB-T Pico TV (TUA9001) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d397", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d397", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Zaapa ZT-MINDVBZP (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d398", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d398", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # SVEON STV20 DVB-T USB & FM (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d39d", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d39d", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Twintech UT-40 (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d3a4", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d3a4", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # ASUS U3100MINI_PLUS_V2 (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d3a8", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d3a8", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # SVEON STV27 DVB-T USB & FM (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d3af", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d3af", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # SVEON STV21 DVB-T USB & FM -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d3b0", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d3b0", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Dexatek DK DVB-T Dongle (Logilink VG0002A) (FC2580) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d19", ATTRS{idProduct}=="1101", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d19", ATTRS{idProduct}=="1101", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Dexatek DK DVB-T Dongle (MSI DigiVox mini II V3.0) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d19", ATTRS{idProduct}=="1102", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d19", ATTRS{idProduct}=="1102", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Dexatek DK 5217 DVB-T Dongle (FC2580) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d19", ATTRS{idProduct}=="1103", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d19", ATTRS{idProduct}=="1103", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # MSI DigiVox Micro HD (FC2580) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d19", ATTRS{idProduct}=="1104", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d19", ATTRS{idProduct}=="1104", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Sweex DVB-T USB (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="a803", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="a803", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # GTek T803 (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="b803", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="b803", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # Lifeview LV5TDeluxe (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="c803", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="c803", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # MyGica TD312 (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="d286", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="d286", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" # PROlectrix DV107669 (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="d803", MODE:="0666" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="d803", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 07d64abe..a2bcb3dc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,34 +1,56 @@ -# Copyright 2012 OSMOCOM Project +# Copyright 2012-2020 Osmocom Project # # This file is part of rtl-sdr # -# GNU Radio is free software; you can redistribute it and/or modify +# 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, or (at your option) -# any later version. +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. # -# GNU Radio is distributed in the hope that it will be useful, +# 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. +# along with this program. If not, see . -MACRO(RTLSDR_APPEND_SRCS) - LIST(APPEND rtlsdr_srcs ${ARGV}) -ENDMACRO(RTLSDR_APPEND_SRCS) +######################################################################## +# Setup shared library variant +######################################################################## +add_library(rtlsdr SHARED librtlsdr.c + tuner_e4k.c tuner_fc0012.c tuner_fc0013.c tuner_fc2580.c tuner_r82xx.c) +target_link_libraries(rtlsdr ${LIBUSB_LIBRARIES} ${THREADS_PTHREADS_LIBRARY}) +target_include_directories(rtlsdr PUBLIC + $ + $ # /include + ${LIBUSB_INCLUDE_DIRS} + ${THREADS_PTHREADS_INCLUDE_DIR} + ) +set_target_properties(rtlsdr PROPERTIES DEFINE_SYMBOL "rtlsdr_EXPORTS") +set_target_properties(rtlsdr PROPERTIES OUTPUT_NAME rtlsdr) +set_target_properties(rtlsdr PROPERTIES SOVERSION 0) +set_target_properties(rtlsdr PROPERTIES VERSION ${LIBVER}) +generate_export_header(rtlsdr) -RTLSDR_APPEND_SRCS( - librtlsdr.c - tuner_e4k.c - tuner_fc0012.c - tuner_fc0013.c - tuner_fc2580.c - tuner_r82xx.c -) +######################################################################## +# Setup static library variant +######################################################################## +add_library(rtlsdr_static STATIC librtlsdr.c + tuner_e4k.c tuner_fc0012.c tuner_fc0013.c tuner_fc2580.c tuner_r82xx.c) +target_link_libraries(rtlsdr ${LIBUSB_LIBRARIES} ${THREADS_PTHREADS_LIBRARY}) +target_include_directories(rtlsdr_static PUBLIC + $ + $ # /include + ${LIBUSB_INCLUDE_DIRS} + ${THREADS_PTHREADS_INCLUDE_DIR} + ) +set_property(TARGET rtlsdr_static APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" ) +if(NOT WIN32) +# Force same library filename for static and shared variants of the library +set_target_properties(rtlsdr_static PROPERTIES OUTPUT_NAME rtlsdr) +endif() +generate_export_header(rtlsdr_static) ######################################################################## # Set up Windows DLL resource files @@ -40,44 +62,24 @@ IF(MSVC) ${CMAKE_CURRENT_SOURCE_DIR}/rtlsdr.rc.in ${CMAKE_CURRENT_BINARY_DIR}/rtlsdr.rc @ONLY) - - RTLSDR_APPEND_SRCS(${CMAKE_CURRENT_BINARY_DIR}/rtlsdr.rc) + target_sources(rtlsdr PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/rtlsdr.rc) + target_sources(rtlsdr_static PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/rtlsdr.rc) ENDIF(MSVC) -######################################################################## -# Setup shared library variant -######################################################################## -add_library(rtlsdr_shared SHARED ${rtlsdr_srcs}) -target_link_libraries(rtlsdr_shared ${LIBUSB_LIBRARIES}) -set_target_properties(rtlsdr_shared PROPERTIES DEFINE_SYMBOL "rtlsdr_EXPORTS") -set_target_properties(rtlsdr_shared PROPERTIES OUTPUT_NAME rtlsdr) -set_target_properties(rtlsdr_shared PROPERTIES SOVERSION ${MAJOR_VERSION}) -set_target_properties(rtlsdr_shared PROPERTIES VERSION ${LIBVER}) - -######################################################################## -# Setup static library variant -######################################################################## -add_library(rtlsdr_static STATIC ${rtlsdr_srcs}) -target_link_libraries(rtlsdr_static ${LIBUSB_LIBRARIES}) -set_property(TARGET rtlsdr_static APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" ) -if(NOT WIN32) -# Force same library filename for static and shared variants of the library -set_target_properties(rtlsdr_static PROPERTIES OUTPUT_NAME rtlsdr) -endif() - ######################################################################## # Setup libraries used in executables ######################################################################## add_library(convenience_static STATIC convenience/convenience.c ) - +target_include_directories(convenience_static + PRIVATE ${CMAKE_SOURCE_DIR}/include) if(WIN32) add_library(libgetopt_static STATIC getopt/getopt.c ) target_link_libraries(convenience_static - rtlsdr_shared + rtlsdr ) endif() @@ -91,33 +93,38 @@ add_executable(rtl_fm rtl_fm.c) add_executable(rtl_eeprom rtl_eeprom.c) add_executable(rtl_adsb rtl_adsb.c) add_executable(rtl_power rtl_power.c) -set(INSTALL_TARGETS rtlsdr_shared rtlsdr_static rtl_sdr rtl_tcp rtl_test rtl_fm rtl_eeprom rtl_adsb rtl_power) +add_executable(rtl_biast rtl_biast.c) +set(INSTALL_TARGETS rtlsdr rtlsdr_static rtl_sdr rtl_tcp rtl_test rtl_fm rtl_eeprom rtl_adsb rtl_power rtl_biast) -target_link_libraries(rtl_sdr rtlsdr_shared convenience_static +target_link_libraries(rtl_sdr rtlsdr convenience_static ${LIBUSB_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ) -target_link_libraries(rtl_tcp rtlsdr_shared convenience_static +target_link_libraries(rtl_tcp rtlsdr convenience_static ${LIBUSB_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ) -target_link_libraries(rtl_test rtlsdr_shared convenience_static +target_link_libraries(rtl_test rtlsdr convenience_static ${LIBUSB_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ) -target_link_libraries(rtl_fm rtlsdr_shared convenience_static +target_link_libraries(rtl_fm rtlsdr convenience_static ${LIBUSB_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ) -target_link_libraries(rtl_eeprom rtlsdr_shared convenience_static +target_link_libraries(rtl_eeprom rtlsdr convenience_static ${LIBUSB_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ) -target_link_libraries(rtl_adsb rtlsdr_shared convenience_static +target_link_libraries(rtl_adsb rtlsdr convenience_static ${LIBUSB_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ) -target_link_libraries(rtl_power rtlsdr_shared convenience_static +target_link_libraries(rtl_power rtlsdr convenience_static + ${LIBUSB_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} +) +target_link_libraries(rtl_biast rtlsdr convenience_static ${LIBUSB_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ) @@ -125,7 +132,7 @@ if(UNIX) target_link_libraries(rtl_fm m) target_link_libraries(rtl_adsb m) target_link_libraries(rtl_power m) -if(APPLE) +if(APPLE OR CMAKE_SYSTEM MATCHES "OpenBSD") target_link_libraries(rtl_test m) else() target_link_libraries(rtl_test m rt) @@ -140,6 +147,7 @@ target_link_libraries(rtl_fm libgetopt_static) target_link_libraries(rtl_eeprom libgetopt_static) target_link_libraries(rtl_adsb libgetopt_static) target_link_libraries(rtl_power libgetopt_static) +target_link_libraries(rtl_biast libgetopt_static) set_property(TARGET rtl_sdr APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" ) set_property(TARGET rtl_tcp APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" ) set_property(TARGET rtl_test APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" ) @@ -147,12 +155,17 @@ set_property(TARGET rtl_fm APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" ) set_property(TARGET rtl_eeprom APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" ) set_property(TARGET rtl_adsb APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" ) set_property(TARGET rtl_power APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" ) +set_property(TARGET rtl_biast APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" ) endif() ######################################################################## # Install built library files & utilities ######################################################################## -install(TARGETS ${INSTALL_TARGETS} - LIBRARY DESTINATION ${LIB_INSTALL_DIR} # .so/.dylib file - ARCHIVE DESTINATION ${LIB_INSTALL_DIR} # .lib file - RUNTIME DESTINATION bin # .dll file -) +install(TARGETS rtlsdr EXPORT RTLSDR-export + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # .so/.dylib file + ) +install(TARGETS rtlsdr_static EXPORT RTLSDR-export + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # .so/.dylib file + ) +install(TARGETS rtl_sdr rtl_tcp rtl_test rtl_fm rtl_eeprom rtl_adsb rtl_power rtl_biast + DESTINATION ${CMAKE_INSTALL_BINDIR} + ) diff --git a/src/librtlsdr.c b/src/librtlsdr.c index 89ec9030..ee135569 100644 --- a/src/librtlsdr.c +++ b/src/librtlsdr.c @@ -39,12 +39,6 @@ #define LIBUSB_CALL #endif -/* libusb < 1.0.9 doesn't have libusb_handle_events_timeout_completed */ -#ifndef HAVE_LIBUSB_HANDLE_EVENTS_TIMEOUT_COMPLETED -#define libusb_handle_events_timeout_completed(ctx, tv, c) \ - libusb_handle_events_timeout(ctx, tv) -#endif - /* two raised to the power of n */ #define TWO_POW(n) ((double)(1ULL<<(n))) @@ -125,6 +119,8 @@ struct rtlsdr_dev { int dev_lost; int driver_active; unsigned int xfer_errors; + char manufact[256]; + char product[256]; }; void rtlsdr_set_gpio_bit(rtlsdr_dev_t *dev, uint8_t gpio, int val); @@ -1436,6 +1432,16 @@ int rtlsdr_get_index_by_serial(const char *serial) return -3; } +/* Returns true if the manufact_check and product_check strings match what is in the dongles EEPROM */ +int rtlsdr_check_dongle_model(void *dev, char *manufact_check, char *product_check) +{ + if ((strcmp(((rtlsdr_dev_t *)dev)->manufact, manufact_check) == 0&& strcmp(((rtlsdr_dev_t *)dev)->product, product_check) == 0)) + return 1; + + return 0; +} + + int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index) { int r; @@ -1534,6 +1540,9 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index) rtlsdr_init_baseband(dev); dev->dev_lost = 0; + /* Get device manufacturer and product id */ + r = rtlsdr_get_usb_strings(dev, dev->manufact, dev->product, NULL); + /* Probe tuners */ rtlsdr_set_i2c_repeater(dev, 1); @@ -1561,6 +1570,10 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index) reg = rtlsdr_i2c_read_reg(dev, R828D_I2C_ADDR, R82XX_CHECK_ADDR); if (reg == R82XX_CHECK_VAL) { fprintf(stderr, "Found Rafael Micro R828D tuner\n"); + + if (rtlsdr_check_dongle_model(dev, "RTLSDRBlog", "Blog V4")) + fprintf(stderr, "RTL-SDR Blog V4 Detected\n"); + dev->tuner_type = RTLSDR_TUNER_R828D; goto found; } @@ -1594,7 +1607,10 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index) switch (dev->tuner_type) { case RTLSDR_TUNER_R828D: - dev->tun_xtal = R828D_XTAL_FREQ; + /* If NOT an RTL-SDR Blog V4, set typical R828D 16 MHz freq. Otherwise, keep at 28.8 MHz. */ + if (!(rtlsdr_check_dongle_model(dev, "RTLSDRBlog", "Blog V4"))) { + dev->tun_xtal = R828D_XTAL_FREQ; + } /* fall-through */ case RTLSDR_TUNER_R820T: /* disable Zero-IF mode */ @@ -1628,6 +1644,9 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index) return 0; err: if (dev) { + if (dev->devh) + libusb_close(dev->devh); + if (dev->ctx) libusb_exit(dev->ctx); @@ -1748,7 +1767,7 @@ static int _rtlsdr_alloc_async_buffers(rtlsdr_dev_t *dev) dev->xfer_buf = malloc(dev->xfer_buf_num * sizeof(unsigned char *)); memset(dev->xfer_buf, 0, dev->xfer_buf_num * sizeof(unsigned char *)); -#if defined (__linux__) && LIBUSB_API_VERSION >= 0x01000105 +#if defined(ENABLE_ZEROCOPY) && defined (__linux__) && LIBUSB_API_VERSION >= 0x01000105 fprintf(stderr, "Allocating %d zero-copy buffers\n", dev->xfer_buf_num); dev->use_zerocopy = 1; @@ -1927,6 +1946,9 @@ int rtlsdr_read_async(rtlsdr_dev_t *dev, rtlsdr_read_async_cb_t cb, void *ctx, /* handle events after canceling * to allow transfer status to * propagate */ +#ifdef _WIN32 + Sleep(1); +#endif libusb_handle_events_timeout_completed(dev->ctx, &zerotv, NULL); if (r < 0) @@ -2006,13 +2028,18 @@ int rtlsdr_i2c_read_fn(void *dev, uint8_t addr, uint8_t *buf, int len) return -1; } -int rtlsdr_set_bias_tee(rtlsdr_dev_t *dev, int on) +int rtlsdr_set_bias_tee_gpio(rtlsdr_dev_t *dev, int gpio, int on) { if (!dev) return -1; - rtlsdr_set_gpio_output(dev, 0); - rtlsdr_set_gpio_bit(dev, 0, on); + rtlsdr_set_gpio_output(dev, gpio); + rtlsdr_set_gpio_bit(dev, gpio, on); return 0; } + +int rtlsdr_set_bias_tee(rtlsdr_dev_t *dev, int on) +{ + return rtlsdr_set_bias_tee_gpio(dev, 0, on); +} diff --git a/src/rtl_adsb.c b/src/rtl_adsb.c index 7aea8ddc..76832406 100644 --- a/src/rtl_adsb.c +++ b/src/rtl_adsb.c @@ -89,7 +89,7 @@ void usage(void) fprintf(stderr, "rtl_adsb, a simple ADS-B decoder\n\n" "Use:\trtl_adsb [-R] [-g gain] [-p ppm] [output file]\n" - "\t[-d device_index (default: 0)]\n" + "\t[-d device_index or serial (default: 0)]\n" "\t[-V verbove output (default: off)]\n" "\t[-S show short frames (default: off)]\n" "\t[-Q quality (0: no sanity checks, 0.5: half bit, 1: one bit (default), 2: two bits)]\n" @@ -123,6 +123,7 @@ sighandler(int signum) #else static void sighandler(int signum) { + signal(SIGPIPE, SIG_IGN); fprintf(stderr, "Signal caught, exiting!\n"); do_exit = 1; rtlsdr_cancel_async(dev); diff --git a/src/rtl_biast.c b/src/rtl_biast.c new file mode 100644 index 00000000..185e838f --- /dev/null +++ b/src/rtl_biast.c @@ -0,0 +1,101 @@ +/* + * rtl-sdr, turns your Realtek RTL2832 based DVB dongle into a SDR receiver + * rtl_biast, tool to set bias tee gpio output + * Copyright (C) 2012 by Steve Markgraf + * + * 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 2 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 +#include + +#ifndef _WIN32 +#include +#else +#include +#include "getopt/getopt.h" +#endif + +#include "rtl-sdr.h" +#include "convenience/convenience.h" + +static rtlsdr_dev_t *dev = NULL; + +void usage(void) +{ + fprintf(stderr, + "rtl_biast, a tool for turning the RTL-SDR.com \n" + "bias tee or any GPIO ON and OFF. Example to turn on the \n" + "bias tee: rtl_biast -d 0 -b 1\n" + "Any GPIO: rtl_biast -d 0 -g 1 -b 1\n\n" + "Usage:\n" + "\t[-d device_index (default: 0)]\n" + "\t[-b bias_on (default: 0)]\n" + "\t[-g GPIO select (default: 0)]\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + int i, r, opt; + int dev_index = 0; + int dev_given = 0; + uint32_t bias_on = 0; + uint32_t gpio_pin = 0; + int device_count; + + while ((opt = getopt(argc, argv, "d:b:g:h?")) != -1) { + switch (opt) { + case 'd': + dev_index = verbose_device_search(optarg); + dev_given = 1; + break; + case 'b': + bias_on = atoi(optarg); + break; + case 'g': + gpio_pin = atoi(optarg); + break; + default: + usage(); + break; + } + } + + if (!dev_given) { + dev_index = verbose_device_search("0"); + } + + if (dev_index < 0) { + exit(1); + } + + r = rtlsdr_open(&dev, dev_index); + rtlsdr_set_bias_tee_gpio(dev, gpio_pin, bias_on); + +exit: + /* + * Note - rtlsdr_close() in this tree does not clear the bias tee + * GPIO line, so it leaves the bias tee enabled if a client program + * doesn't explictly disable it. + * + * If that behaviour changes then another rtlsdr_close() will be + * needed that takes some extension flags, and one of them should + * be to either explicitly close the biast or leave it alone. + */ + rtlsdr_close(dev); + + return r >= 0 ? r : -r; +} diff --git a/src/rtl_eeprom.c b/src/rtl_eeprom.c index f562d735..24be9001 100644 --- a/src/rtl_eeprom.c +++ b/src/rtl_eeprom.c @@ -370,14 +370,14 @@ int main(int argc, char **argv) } if (manuf_str) - strncpy((char*)&conf.manufacturer, manuf_str, MAX_STR_SIZE); + strncpy((char*)&conf.manufacturer, manuf_str, MAX_STR_SIZE - 1); if (product_str) - strncpy((char*)&conf.product, product_str, MAX_STR_SIZE); + strncpy((char*)&conf.product, product_str, MAX_STR_SIZE - 1); if (serial_str) { conf.have_serial = 1; - strncpy((char*)&conf.serial, serial_str, MAX_STR_SIZE); + strncpy((char*)&conf.serial, serial_str, MAX_STR_SIZE - 1); } if (ir_endpoint != 0) diff --git a/src/rtl_fm.c b/src/rtl_fm.c index b163979c..0929744b 100644 --- a/src/rtl_fm.c +++ b/src/rtl_fm.c @@ -192,7 +192,7 @@ void usage(void) "\t wbfm == -M fm -s 170k -o 4 -A fast -r 32k -l 0 -E deemp\n" "\t raw mode outputs 2x16 bit IQ pairs\n" "\t[-s sample_rate (default: 24k)]\n" - "\t[-d device_index (default: 0)]\n" + "\t[-d device_index or serial (default: 0)]\n" "\t[-T enable bias-T on GPIO PIN 0 (works for rtl-sdr.com v3 dongles)]\n" "\t[-g tuner_gain (default: automatic)]\n" "\t[-l squelch_level (default: 0/off)]\n" @@ -201,11 +201,12 @@ void usage(void) "\t[-p ppm_error (default: 0)]\n" "\t[-E enable_option (default: none)]\n" "\t use multiple -E to enable multiple options\n" - "\t edge: enable lower edge tuning\n" - "\t dc: enable dc blocking filter\n" - "\t deemp: enable de-emphasis filter\n" - "\t direct: enable direct sampling\n" - "\t offset: enable offset tuning\n" + "\t edge: enable lower edge tuning\n" + "\t dc: enable dc blocking filter\n" + "\t deemp: enable de-emphasis filter\n" + "\t direct: enable direct sampling 1 (usually I)\n" + "\t direct2: enable direct sampling 2 (usually Q)\n" + "\t offset: enable offset tuning\n" "\tfilename ('-' means stdout)\n" "\t omitting the filename also uses stdout\n\n" "Experimental options:\n" @@ -245,6 +246,7 @@ sighandler(int signum) #else static void sighandler(int signum) { + signal(SIGPIPE, SIG_IGN); fprintf(stderr, "Signal caught, exiting!\n"); do_exit = 1; rtlsdr_cancel_async(dongle.dev); @@ -892,7 +894,7 @@ static void *controller_thread_fn(void *arg) /* set up primary channel */ optimal_settings(s->freqs[0], demod.rate_in); if (dongle.direct_sampling) { - verbose_direct_sampling(dongle.dev, 1);} + verbose_direct_sampling(dongle.dev, dongle.direct_sampling);} if (dongle.offset_tuning) { verbose_offset_tuning(dongle.dev);} @@ -926,8 +928,21 @@ void frequency_range(struct controller_state *s, char *arg) int i; start = arg; stop = strchr(start, ':') + 1; + if (stop == (char *)1) { // no stop or step given + s->freqs[s->freq_len] = (uint32_t) atofs(start); + s->freq_len++; + return; + } stop[-1] = '\0'; step = strchr(stop, ':') + 1; + if (step == (char *)1) { // no step given + s->freqs[s->freq_len] = (uint32_t) atofs(start); + s->freq_len++; + s->freqs[s->freq_len] = (uint32_t) atofs(stop); + s->freq_len++; + stop[-1] = ':'; + return; + } step[-1] = '\0'; for(i=(int)atofs(start); i<=(int)atofs(stop); i+=(int)atofs(step)) { @@ -1106,6 +1121,8 @@ int main(int argc, char **argv) demod.deemph = 1;} if (strcmp("direct", optarg) == 0) { dongle.direct_sampling = 1;} + if (strcmp("direct2", optarg) == 0) { + dongle.direct_sampling = 2;} if (strcmp("offset", optarg) == 0) { dongle.offset_tuning = 1;} break; diff --git a/src/rtl_power.c b/src/rtl_power.c index 625d818e..f78561fb 100644 --- a/src/rtl_power.c +++ b/src/rtl_power.c @@ -130,7 +130,7 @@ void usage(void) "\t[-e exit_timer (default: off/0)]\n" //"\t[-s avg/iir smoothing (default: avg)]\n" //"\t[-t threads (default: 1)]\n" - "\t[-d device_index (default: 0)]\n" + "\t[-d device_index or serial (default: 0)]\n" "\t[-g tuner_gain (default: automatic)]\n" "\t[-p ppm_error (default: 0)]\n" "\t[-T enable bias-T on GPIO PIN 0 (works for rtl-sdr.com v3 dongles)]\n" @@ -195,6 +195,7 @@ sighandler(int signum) #else static void sighandler(int signum) { + signal(SIGPIPE, SIG_IGN); do_exit++; multi_bail(); } @@ -437,8 +438,16 @@ void frequency_range(char *arg, double crop) /* hacky string parsing */ start = arg; stop = strchr(start, ':') + 1; + if (stop == (char *)1) { + fprintf(stderr, "Bad frequency range specification: %s\n", arg); + exit(1); + } stop[-1] = '\0'; step = strchr(stop, ':') + 1; + if (step == (char *)1) { + fprintf(stderr, "Bad frequency range specification: %s\n", arg); + exit(1); + } step[-1] = '\0'; lower = (int)atofs(start); upper = (int)atofs(stop); diff --git a/src/rtl_sdr.c b/src/rtl_sdr.c index e6537cad..4e10bc18 100644 --- a/src/rtl_sdr.c +++ b/src/rtl_sdr.c @@ -49,12 +49,13 @@ void usage(void) "rtl_sdr, an I/Q recorder for RTL2832 based DVB-T receivers\n\n" "Usage:\t -f frequency_to_tune_to [Hz]\n" "\t[-s samplerate (default: 2048000 Hz)]\n" - "\t[-d device_index (default: 0)]\n" + "\t[-d device_index or serial (default: 0)]\n" "\t[-g gain (default: 0 for auto)]\n" "\t[-p ppm_error (default: 0)]\n" "\t[-b output_block_size (default: 16 * 16384)]\n" "\t[-n number of samples to read (default: 0, infinite)]\n" "\t[-S force sync output (default: async)]\n" + "\t[-D enable direct sampling (default: off)]\n" "\tfilename (a '-' dumps samples to stdout)\n\n"); exit(1); } @@ -74,6 +75,7 @@ sighandler(int signum) #else static void sighandler(int signum) { + signal(SIGPIPE, SIG_IGN); fprintf(stderr, "Signal caught, exiting!\n"); do_exit = 1; rtlsdr_cancel_async(dev); @@ -112,6 +114,7 @@ int main(int argc, char **argv) int r, opt; int gain = 0; int ppm_error = 0; + int direct_sampling = 0; int sync_mode = 0; FILE *file; uint8_t *buffer; @@ -121,7 +124,7 @@ int main(int argc, char **argv) uint32_t samp_rate = DEFAULT_SAMPLE_RATE; uint32_t out_block_size = DEFAULT_BUF_LENGTH; - while ((opt = getopt(argc, argv, "d:f:g:s:b:n:p:S")) != -1) { + while ((opt = getopt(argc, argv, "d:f:g:s:b:n:p:SD")) != -1) { switch (opt) { case 'd': dev_index = verbose_device_search(optarg); @@ -148,6 +151,9 @@ int main(int argc, char **argv) case 'S': sync_mode = 1; break; + case 'D': + direct_sampling = 1; + break; default: usage(); break; @@ -197,6 +203,11 @@ int main(int argc, char **argv) #else SetConsoleCtrlHandler( (PHANDLER_ROUTINE) sighandler, TRUE ); #endif + + /* Set direct sampling */ + if (direct_sampling) + verbose_direct_sampling(dev, 2); + /* Set the sample rate */ verbose_set_sample_rate(dev, samp_rate); diff --git a/src/rtl_tcp.c b/src/rtl_tcp.c index da6057be..b730bf43 100644 --- a/src/rtl_tcp.c +++ b/src/rtl_tcp.c @@ -30,10 +30,12 @@ #include #include #include +#include #include #include #else #include +#include #include "getopt/getopt.h" #endif @@ -54,6 +56,10 @@ typedef int socklen_t; #define SOCKET_ERROR -1 #endif +#define DEFAULT_PORT_STR "1234" +#define DEFAULT_SAMPLE_RATE_HZ 2048000 +#define DEFAULT_MAX_NUM_BUFFERS 500 + static SOCKET s; static pthread_t tcp_worker_thread; @@ -81,23 +87,25 @@ static rtlsdr_dev_t *dev = NULL; static int enable_biastee = 0; static int global_numq = 0; static struct llist *ll_buffers = 0; -static int llbuf_num = 500; +static int llbuf_num = DEFAULT_MAX_NUM_BUFFERS; static volatile int do_exit = 0; + void usage(void) { - printf("rtl_tcp, an I/Q spectrum server for RTL2832 based DVB-T receivers\n\n" - "Usage:\t[-a listen address]\n" - "\t[-p listen port (default: 1234)]\n" - "\t[-f frequency to tune to [Hz]]\n" - "\t[-g gain (default: 0 for auto)]\n" - "\t[-s samplerate in Hz (default: 2048000 Hz)]\n" - "\t[-b number of buffers (default: 15, set by library)]\n" - "\t[-n max number of linked list buffers to keep (default: 500)]\n" - "\t[-d device index (default: 0)]\n" - "\t[-P ppm_error (default: 0)]\n" - "\t[-T enable bias-T on GPIO PIN 0 (works for rtl-sdr.com v3 dongles)]\n"); + printf("rtl_tcp, an I/Q spectrum server for RTL2832 based DVB-T receivers\n\n"); + printf("Usage:\t[-a listen address]\n"); + printf("\t[-p listen port (default: %s)]\n", DEFAULT_PORT_STR); + printf("\t[-f frequency to tune to [Hz]]\n"); + printf("\t[-g gain (default: 0 for auto)]\n"); + printf("\t[-s samplerate in Hz (default: %d Hz)]\n", DEFAULT_SAMPLE_RATE_HZ); + printf("\t[-b number of buffers (default: 15, set by library)]\n"); + printf("\t[-n max number of linked list buffers to keep (default: %d)]\n", DEFAULT_MAX_NUM_BUFFERS); + printf("\t[-d device index or serial (default: 0)]\n"); + printf("\t[-P ppm_error (default: 0)]\n"); + printf("\t[-T enable bias-T on GPIO PIN 0 (works for rtl-sdr.com v3 dongles)]\n"); + printf("\t[-D enable direct sampling (default: off)]\n"); exit(1); } @@ -137,6 +145,7 @@ sighandler(int signum) #else static void sighandler(int signum) { + signal(SIGPIPE, SIG_IGN); fprintf(stderr, "Signal caught, exiting!\n"); rtlsdr_cancel_async(dev); do_exit = 1; @@ -371,21 +380,30 @@ static void *command_worker(void *arg) int main(int argc, char **argv) { int r, opt, i; - char* addr = "127.0.0.1"; - int port = 1234; - uint32_t frequency = 100000000, samp_rate = 2048000; - struct sockaddr_in local, remote; + char *addr = "127.0.0.1"; + const char *port = DEFAULT_PORT_STR; + uint32_t frequency = 100000000, samp_rate = DEFAULT_SAMPLE_RATE_HZ; + struct sockaddr_storage local, remote; + struct addrinfo *ai; + struct addrinfo *aiHead; + struct addrinfo hints = { 0 }; + char hostinfo[NI_MAXHOST]; + char portinfo[NI_MAXSERV]; + char remhostinfo[NI_MAXHOST]; + char remportinfo[NI_MAXSERV]; + int aiErr; uint32_t buf_num = 0; int dev_index = 0; int dev_given = 0; int gain = 0; int ppm_error = 0; + int direct_sampling = 0; struct llist *curelem,*prev; pthread_attr_t attr; void *status; struct timeval tv = {1,0}; struct linger ling = {1,0}; - SOCKET listensocket; + SOCKET listensocket = 0; socklen_t rlen; fd_set readfds; u_long blockmode = 1; @@ -397,7 +415,7 @@ int main(int argc, char **argv) struct sigaction sigact, sigign; #endif - while ((opt = getopt(argc, argv, "a:p:f:g:s:b:n:d:P:T")) != -1) { + while ((opt = getopt(argc, argv, "a:p:f:g:s:b:n:d:P:TD")) != -1) { switch (opt) { case 'd': dev_index = verbose_device_search(optarg); @@ -413,10 +431,10 @@ int main(int argc, char **argv) samp_rate = (uint32_t)atofs(optarg); break; case 'a': - addr = optarg; + addr = strdup(optarg); break; case 'p': - port = atoi(optarg); + port = strdup(optarg); break; case 'b': buf_num = atoi(optarg); @@ -430,6 +448,9 @@ int main(int argc, char **argv) case 'T': enable_biastee = 1; break; + case 'D': + direct_sampling = 1; + break; default: usage(); break; @@ -466,6 +487,10 @@ int main(int argc, char **argv) SetConsoleCtrlHandler( (PHANDLER_ROUTINE) sighandler, TRUE ); #endif + /* Set direct sampling */ + if (direct_sampling) + verbose_direct_sampling(dev, 2); + /* Set the tuner error */ verbose_ppm_set(dev, ppm_error); @@ -515,16 +540,42 @@ int main(int argc, char **argv) pthread_cond_init(&cond, NULL); pthread_cond_init(&exit_cond, NULL); - memset(&local,0,sizeof(local)); - local.sin_family = AF_INET; - local.sin_port = htons(port); - local.sin_addr.s_addr = inet_addr(addr); + hints.ai_flags = AI_PASSIVE; /* Server mode. */ + hints.ai_family = PF_UNSPEC; /* IPv4 or IPv6. */ + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + if ((aiErr = getaddrinfo(addr, + port, + &hints, + &aiHead )) != 0) + { + fprintf(stderr, "local address %s ERROR - %s.\n", + addr, gai_strerror(aiErr)); + return(-1); + } + memcpy(&local, aiHead->ai_addr, aiHead->ai_addrlen); + + for (ai = aiHead; ai != NULL; ai = ai->ai_next) { + aiErr = getnameinfo((struct sockaddr *)ai->ai_addr, ai->ai_addrlen, + hostinfo, NI_MAXHOST, + portinfo, NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST); + if (aiErr) + fprintf( stderr, "getnameinfo ERROR - %s.\n",hostinfo); - listensocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - r = 1; - setsockopt(listensocket, SOL_SOCKET, SO_REUSEADDR, (char *)&r, sizeof(int)); - setsockopt(listensocket, SOL_SOCKET, SO_LINGER, (char *)&ling, sizeof(ling)); - bind(listensocket,(struct sockaddr *)&local,sizeof(local)); + listensocket = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (listensocket < 0) + continue; + + r = 1; + setsockopt(listensocket, SOL_SOCKET, SO_REUSEADDR, (char *)&r, sizeof(int)); + setsockopt(listensocket, SOL_SOCKET, SO_LINGER, (char *)&ling, sizeof(ling)); + + if (bind(listensocket, (struct sockaddr *)&local, aiHead->ai_addrlen)) + fprintf(stderr, "rtl_tcp bind error: %s", strerror(errno)); + else + break; + } #ifdef _WIN32 ioctlsocket(listensocket, FIONBIO, &blockmode); @@ -535,11 +586,11 @@ int main(int argc, char **argv) while(1) { printf("listening...\n"); - printf("Use the device argument 'rtl_tcp=%s:%d' in OsmoSDR " + printf("Use the device argument 'rtl_tcp=%s:%s' in OsmoSDR " "(gr-osmosdr) source\n" "to receive samples in GRC and control " "rtl_tcp parameters (frequency, gain, ...).\n", - addr, port); + hostinfo, portinfo); listen(listensocket,1); while(1) { @@ -559,7 +610,10 @@ int main(int argc, char **argv) setsockopt(s, SOL_SOCKET, SO_LINGER, (char *)&ling, sizeof(ling)); - printf("client accepted!\n"); + getnameinfo((struct sockaddr *)&remote, rlen, + remhostinfo, NI_MAXHOST, + remportinfo, NI_MAXSERV, NI_NUMERICSERV); + printf("client accepted! %s %s\n", remhostinfo, remportinfo); memset(&dongle_info, 0, sizeof(dongle_info)); memcpy(&dongle_info.magic, "RTL0", 4); diff --git a/src/rtl_test.c b/src/rtl_test.c index 9b440974..03edff1f 100644 --- a/src/rtl_test.c +++ b/src/rtl_test.c @@ -90,7 +90,7 @@ void usage(void) "rtl_test, a benchmark tool for RTL2832 based DVB-T receivers\n\n" "Usage:\n" "\t[-s samplerate (default: 2048000 Hz)]\n" - "\t[-d device_index (default: 0)]\n" + "\t[-d device_index or serial (default: 0)]\n" "\t[-t enable Elonics E4000 tuner benchmark]\n" #ifndef _WIN32 "\t[-p[seconds] enable PPM error measurement (default: 10 seconds)]\n" @@ -115,6 +115,7 @@ sighandler(int signum) #else static void sighandler(int signum) { + signal(SIGPIPE, SIG_IGN); fprintf(stderr, "Signal caught, exiting!\n"); do_exit = 1; rtlsdr_cancel_async(dev); diff --git a/src/rtlsdr.rc.in b/src/rtlsdr.rc.in index bf603c36..0861ecbb 100644 --- a/src/rtlsdr.rc.in +++ b/src/rtlsdr.rc.in @@ -1,5 +1,5 @@ -#include +#include VS_VERSION_INFO VERSIONINFO FILEVERSION 0,0,0,0 diff --git a/src/tuner_fc0012.c b/src/tuner_fc0012.c index 768cf1c4..b6cf871b 100644 --- a/src/tuner_fc0012.c +++ b/src/tuner_fc0012.c @@ -114,7 +114,7 @@ int fc0012_init(void *dev) 0x00, /* reg. 0x10: may also be 0x0d */ 0x00, /* reg. 0x11 */ 0x1f, /* reg. 0x12: Set to maximum gain */ - 0x08, /* reg. 0x13: Set to Middle Gain: 0x08, + 0x00, /* reg. 0x13: Set to Low Gain: 0x00, Low Gain: 0x00, High Gain: 0x10, enable IX2: 0x80 */ 0x00, /* reg. 0x14 */ 0x04, /* reg. 0x15: Enable LNA COMPS */ @@ -321,23 +321,11 @@ int fc0012_set_gain(void *dev, int gain) /* mask bits off */ tmp &= 0xe0; - switch (gain) { - case -99: /* -9.9 dB */ - tmp |= 0x02; - break; - case -40: /* -4 dB */ - break; - case 71: - tmp |= 0x08; /* 7.1 dB */ - break; - case 179: - tmp |= 0x17; /* 17.9 dB */ - break; - case 192: - default: - tmp |= 0x10; /* 19.2 dB */ - break; - } + if (gain < -40) tmp |= 0x02; /* -9.9 dB */ + else if (gain < 71) tmp |= 0x00; /* -4.0 dB */ + else if (gain < 179) tmp |= 0x08; /* 7.1 dB */ + else if (gain < 192) tmp |= 0x17; /* 17.9 dB */ + else tmp |= 0x10; /* 19.2 dB */ ret = fc0012_writereg(dev, 0x13, tmp); diff --git a/src/tuner_fc0013.c b/src/tuner_fc0013.c index 78b696ee..5984dfb2 100644 --- a/src/tuner_fc0013.c +++ b/src/tuner_fc0013.c @@ -248,11 +248,11 @@ int fc0013_set_params(void *dev, uint32_t freq, uint32_t bandwidth) if (ret) goto exit; - /* disable UHF & enable GPS */ + /* enable UHF & disable GPS */ ret = fc0013_readreg(dev, 0x14, &tmp); if (ret) goto exit; - ret = fc0013_writereg(dev, 0x14, (tmp & 0x1f) | 0x20); + ret = fc0013_writereg(dev, 0x14, (tmp & 0x1f) | 0x40); if (ret) goto exit; } diff --git a/src/tuner_r82xx.c b/src/tuner_r82xx.c index fe52bd99..6de6b24f 100644 --- a/src/tuner_r82xx.c +++ b/src/tuner_r82xx.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "rtlsdr_i2c.h" #include "tuner_r82xx.h" @@ -33,6 +34,10 @@ #define MHZ(x) ((x)*1000*1000) #define KHZ(x) ((x)*1000) +#define HF 1 +#define VHF 2 +#define UHF 3 + /* * Static constants */ @@ -239,6 +244,7 @@ static void shadow_store(struct r82xx_priv *priv, uint8_t reg, const uint8_t *va if (r < 0) { len += r; + val -= r; r = 0; } if (len <= 0) @@ -249,11 +255,29 @@ static void shadow_store(struct r82xx_priv *priv, uint8_t reg, const uint8_t *va memcpy(&priv->regs[r], val, len); } +static bool shadow_equal(struct r82xx_priv *priv, uint8_t reg, const uint8_t *val, + int len) +{ + int r = reg - REG_SHADOW_START; + + if (r < 0 || len < 0 || len > NUM_REGS - r) + return false; + + if (memcmp(&priv->regs[r], val, len) == 0) + return true; + + return false; +} + static int r82xx_write(struct r82xx_priv *priv, uint8_t reg, const uint8_t *val, unsigned int len) { int rc, size, pos = 0; + /* Avoid setting registers unnecessarily since it's slow */ + if (shadow_equal(priv, reg, val, len)) + return 0; + /* Store the shadow registers */ shadow_store(priv, reg, val, len); @@ -330,8 +354,14 @@ static int r82xx_read(struct r82xx_priv *priv, uint8_t reg, uint8_t *val, int le priv->buf[0] = reg; rc = rtlsdr_i2c_write_fn(priv->rtl_dev, priv->cfg->i2c_addr, priv->buf, 1); - if (rc < 1) - return rc; + + if (rc != 1) { + fprintf(stderr, "%s: i2c wr failed=%d reg=%02x len=%d\n", + __FUNCTION__, rc, reg, 1); + if (rc < 0) + return rc; + return -1; + } rc = rtlsdr_i2c_read_fn(priv->rtl_dev, priv->cfg->i2c_addr, p, len); @@ -414,17 +444,21 @@ static int r82xx_set_mux(struct r82xx_priv *priv, uint32_t freq) return rc; } +static inline uint8_t mask_reg8(uint8_t reg, uint8_t val, uint8_t mask) +{ + return (reg & ~mask) | (val & mask); +} + static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq) { int rc, i; unsigned sleep_time = 10000; uint64_t vco_freq; - uint32_t vco_fra; /* VCO contribution by SDM (kHz) */ - uint32_t vco_min = 1770000; - uint32_t vco_max = vco_min * 2; - uint32_t freq_khz, pll_ref, pll_ref_khz; - uint16_t n_sdm = 2; - uint16_t sdm = 0; + uint64_t vco_div; + uint32_t vco_min = 1770000; /* kHz */ + uint32_t vco_max = vco_min * 2; /* kHz */ + uint32_t freq_khz, pll_ref; + uint32_t sdm = 0; uint8_t mix_div = 2; uint8_t div_buf = 0; uint8_t div_num = 0; @@ -432,25 +466,24 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq) uint8_t refdiv2 = 0; uint8_t ni, si, nint, vco_fine_tune, val; uint8_t data[5]; + uint8_t regs[7]; /* Frequency in kHz */ freq_khz = (freq + 500) / 1000; pll_ref = priv->cfg->xtal; - pll_ref_khz = (priv->cfg->xtal + 500) / 1000; - - rc = r82xx_write_reg_mask(priv, 0x10, refdiv2, 0x10); - if (rc < 0) - return rc; /* set pll autotune = 128kHz */ rc = r82xx_write_reg_mask(priv, 0x1a, 0x00, 0x0c); if (rc < 0) return rc; + /* regs 0x10 to 0x16 */ + memcpy(regs, &priv->regs[0x10 - REG_SHADOW_START], 7); + + regs[0] = mask_reg8(regs[0], refdiv2, 0x10); + /* set VCO current = 100 */ - rc = r82xx_write_reg_mask(priv, 0x12, 0x80, 0xe0); - if (rc < 0) - return rc; + regs[2] = mask_reg8(regs[2], 0x80, 0xe0); /* Calculate divider */ while (mix_div <= 64) { @@ -480,13 +513,27 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq) else if (vco_fine_tune < vco_power_ref) div_num = div_num + 1; - rc = r82xx_write_reg_mask(priv, 0x10, div_num << 5, 0xe0); - if (rc < 0) - return rc; + regs[0] = mask_reg8(regs[0], div_num << 5, 0xe0); vco_freq = (uint64_t)freq * (uint64_t)mix_div; - nint = vco_freq / (2 * pll_ref); - vco_fra = (vco_freq - 2 * pll_ref * nint) / 1000; + + /* We want to approximate: + * vco_freq / (2 * pll_ref) + * + * in the form: + * nint + sdm/65536 + * + * where nint,sdm are integers and 0 < nint, 0 <= sdm < 65536 + * + * Scaling to fixed point and rounding: + * + * vco_div = 65536*(nint + sdm/65536) = int( 0.5 + 65536 * vco_freq / (2 * pll_ref) ) + * vco_div = 65536*nint + sdm = int( (pll_ref + 65536 * vco_freq) / (2 * pll_ref) ) + */ + + vco_div = (pll_ref + 65536 * vco_freq) / (2 * pll_ref); + nint = (uint32_t) (vco_div / 65536); + sdm = (uint32_t) (vco_div % 65536); if (nint > ((128 / vco_power_ref) - 1)) { fprintf(stderr, "[R82XX] No valid PLL values for %u Hz!\n", freq); @@ -496,35 +543,20 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq) ni = (nint - 13) / 4; si = nint - 4 * ni - 13; - rc = r82xx_write_reg(priv, 0x14, ni + (si << 6)); - if (rc < 0) - return rc; + regs[4] = ni + (si << 6); /* pw_sdm */ - if (!vco_fra) + if (sdm == 0) val = 0x08; else val = 0x00; - rc = r82xx_write_reg_mask(priv, 0x12, val, 0x08); - if (rc < 0) - return rc; + regs[2] = mask_reg8(regs[2], val, 0x08); - /* sdm calculator */ - while (vco_fra > 1) { - if (vco_fra > (2 * pll_ref_khz / n_sdm)) { - sdm = sdm + 32768 / (n_sdm / 2); - vco_fra = vco_fra - 2 * pll_ref_khz / n_sdm; - if (n_sdm >= 0x8000) - break; - } - n_sdm <<= 1; - } + regs[5] = sdm & 0xff; + regs[6] = sdm >> 8; - rc = r82xx_write_reg(priv, 0x16, sdm >> 8); - if (rc < 0) - return rc; - rc = r82xx_write_reg(priv, 0x15, sdm & 0xff); + rc = r82xx_write(priv, 0x10, regs, 7); if (rc < 0) return rc; @@ -1092,8 +1124,23 @@ int r82xx_set_bandwidth(struct r82xx_priv *priv, int bw, uint32_t rate) int r82xx_set_freq(struct r82xx_priv *priv, uint32_t freq) { int rc = -1; - uint32_t lo_freq = freq + priv->int_freq; + int is_rtlsdr_blog_v4; + uint32_t upconvert_freq; + uint32_t lo_freq; uint8_t air_cable1_in; + uint8_t open_d; + uint8_t band; + uint8_t cable_2_in; + uint8_t cable_1_in; + uint8_t air_in; + + is_rtlsdr_blog_v4 = rtlsdr_check_dongle_model(priv->rtl_dev, "RTLSDRBlog", "Blog V4"); + + /* if it's an RTL-SDR Blog V4, automatically upconvert by 28.8 MHz if we tune to HF + * so that we don't need to manually set any upconvert offset in the SDR software */ + upconvert_freq = is_rtlsdr_blog_v4 ? ((freq < MHZ(28.8)) ? (freq + MHZ(28.8)) : freq) : freq; + + lo_freq = upconvert_freq + priv->int_freq; rc = r82xx_set_mux(priv, lo_freq); if (rc < 0) @@ -1103,16 +1150,66 @@ int r82xx_set_freq(struct r82xx_priv *priv, uint32_t freq) if (rc < 0 || !priv->has_lock) goto err; - /* switch between 'Cable1' and 'Air-In' inputs on sticks with - * R828D tuner. We switch at 345 MHz, because that's where the - * noise-floor has about the same level with identical LNA - * settings. The original driver used 320 MHz. */ - air_cable1_in = (freq > MHZ(345)) ? 0x00 : 0x60; + if (is_rtlsdr_blog_v4) { + /* determine if notch filters should be on or off notches are turned OFF + * when tuned within the notch band and ON when tuned outside the notch band. + */ + open_d = (freq <= MHZ(2.2) || (freq >= MHZ(85) && freq <= MHZ(112)) || (freq >= MHZ(172) && freq <= MHZ(242))) ? 0x00 : 0x08; + rc = r82xx_write_reg_mask(priv, 0x17, open_d, 0x08); + + if (rc < 0) + return rc; + + /* select tuner band based on frequency and only switch if there is a band change + *(to avoid excessive register writes when tuning rapidly) + */ + band = (freq <= MHZ(28.8)) ? HF : ((freq > MHZ(28.8) && freq < MHZ(250)) ? VHF : UHF); - if ((priv->cfg->rafael_chip == CHIP_R828D) && - (air_cable1_in != priv->input)) { - priv->input = air_cable1_in; - rc = r82xx_write_reg_mask(priv, 0x05, air_cable1_in, 0x60); + /* switch between tuner inputs on the RTL-SDR Blog V4 */ + if (band != priv->input) { + priv->input = band; + + /* activate cable 2 (HF input) */ + cable_2_in = (band == HF) ? 0x08 : 0x00; + rc = r82xx_write_reg_mask(priv, 0x06, cable_2_in, 0x08); + + if (rc < 0) + goto err; + + /* Control upconverter GPIO switch on newer batches */ + rc = rtlsdr_set_bias_tee_gpio(priv->rtl_dev, 5, !cable_2_in); + + if (rc < 0) + goto err; + + /* activate cable 1 (VHF input) */ + cable_1_in = (band == VHF) ? 0x40 : 0x00; + rc = r82xx_write_reg_mask(priv, 0x05, cable_1_in, 0x40); + + if (rc < 0) + goto err; + + /* activate air_in (UHF input) */ + air_in = (band == UHF) ? 0x00 : 0x20; + rc = r82xx_write_reg_mask(priv, 0x05, air_in, 0x20); + + if (rc < 0) + goto err; + } + } + else /* Standard R828D dongle*/ + { + /* switch between 'Cable1' and 'Air-In' inputs on sticks with + * R828D tuner. We switch at 345 MHz, because that's where the + * noise-floor has about the same level with identical LNA + * settings. The original driver used 320 MHz. */ + air_cable1_in = (freq > MHZ(345)) ? 0x00 : 0x60; + + if ((priv->cfg->rafael_chip == CHIP_R828D) && + (air_cable1_in != priv->input)) { + priv->input = air_cable1_in; + rc = r82xx_write_reg_mask(priv, 0x05, air_cable1_in, 0x60); + } } err: @@ -1242,6 +1339,7 @@ int r82xx_init(struct r82xx_priv *priv) priv->xtal_cap_sel = XTAL_HIGH_CAP_0P; /* Initialize registers */ + memset(priv->regs, 0, NUM_REGS); rc = r82xx_write(priv, 0x05, r82xx_init_array, sizeof(r82xx_init_array));