Add software

This commit is contained in:
RocketGod
2022-09-22 09:26:57 -07:00
parent fee0ab05fd
commit 957ea3d712
4511 changed files with 1943182 additions and 0 deletions

View File

@ -0,0 +1,23 @@
#top dir cmake project for libhackrf + tools
cmake_minimum_required(VERSION 2.8)
project (HackRF C)
set(CMAKE_C_FLAGS "$ENV{CFLAGS}" CACHE STRING "C Flags")
add_subdirectory(libhackrf)
add_subdirectory(hackrf-tools)
########################################################################
# Create uninstall target
########################################################################
configure_file(
${PROJECT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
@ONLY)
add_custom_target(uninstall
${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
)

View File

@ -0,0 +1,94 @@
This repository contains host software (Linux/Windows) for HackRF, a project to
produce a low cost, open source software radio platform.
## How to build the host software on Linux:
### Prerequisites for Linux (Debian/Ubuntu):
`sudo apt-get install build-essential cmake libusb-1.0-0-dev pkg-config libfftw3-dev`
### Build host software on Linux:
```
mkdir host/build
cd host/build
cmake ..
make
sudo make install
sudo ldconfig
```
By default this will attempt to install an udev rule to `/etc/udev/rules.d` to
provide the `usb` or `plugdev` group access to HackRF. If your setup requires
the udev rule to be installed elsewhere you can modify the path with
`-DUDEV_RULES_PATH=/path/to/udev`.
Note: The udev rule is not installed by default for PyBOMBS installs as
they do not ususally get installed with root privileges.
## Clean CMake temporary files/dirs:
```
cd host/build
rm -rf *
```
## How to build host software on Windows:
### Prerequisites for Cygwin, MinGW, or Visual Studio:
* cmake-2.8.12.1 or later from http://www.cmake.org/cmake/resources/software.html
* libusbx-1.0.18 or later from http://sourceforge.net/projects/libusbx/files/latest/download?source=files
* fftw-3.3.5 or later from http://www.fftw.org/install/windows.html
* Install Windows driver for HackRF hardware or use Zadig see http://sourceforge.net/projects/libwdi/files/zadig
- If you want to use Zadig select HackRF USB device and just install/replace it with WinUSB driver.
>**Note for Windows build:**
You shall always execute hackrf-tools from Windows command shell and not from Cygwin or MinGW shell because on Cygwin/MinGW
Ctrl C is not managed correctly and especially for hackrf_transfer the Ctrl C(abort) will not stop correctly and will corrupt the file.
### For Cygwin:
```
mkdir host/build
cd host/build
cmake ../ -G "Unix Makefiles" -DCMAKE_LEGACY_CYGWIN_WIN32=1 -DLIBUSB_INCLUDE_DIR=/usr/local/include/libusb-1.0/
make
make install
```
### For MinGW:
```
mkdir host/build
cd host/build
cmake ../ -G "MSYS Makefiles" -DLIBUSB_INCLUDE_DIR=/usr/local/include/libusb-1.0/
make
make install
```
### For Visual Studio 2015 x64
Create library definition for MSVC to link to
`C:\fftw-3.3.5-dll64> lib /machine:x64 /def:libfftw3f-3.def`
```
c:\hackrf\host\build> cmake ../ -G "Visual Studio 14 2015 Win64" \
-DLIBUSB_INCLUDE_DIR=c:\libusb-1.0.21\libusb \
-DLIBUSB_LIBRARIES=c:\libusb-1.0.21\MS64\dll\lib\libusb-1.0.lib \
-DTHREADS_PTHREADS_INCLUDE_DIR=c:\pthreads-w32-2-9-1-release\Pre-built.2\include \
-DTHREADS_PTHREADS_WIN32_LIBRARY=c:\pthreads-w32-2-9-1-release\Pre-built.2\lib\x64\pthreadVC2.lib \
-DFFTW_INCLUDES=C:\fftw-3.3.5-dll64 \
-DFFTW_LIBRARIES=C:\fftw-3.3.5-dll64\libfftw3f-3.lib
```
CMake will produce a solution file named `HackRF.sln` and a series of
project files which can be built with msbuild as follows:
`c:\hackrf\host\build> msbuild HackRF.sln`
## How to build host the software on FreeBSD
You can use the binary package:
`# pkg install hackrf`
You can build and install from ports:
```
# cd /usr/ports/comms/hackrf
# make install
```
principal author: Michael Ossmann <mike@ossmann.com>
http://greatscottgadgets.com/hackrf/

View File

@ -0,0 +1,32 @@
# http://www.vtk.org/Wiki/CMake_FAQ#Can_I_do_.22make_uninstall.22_with_CMake.3F
IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
STRING(REGEX REPLACE "\n" ";" files "${files}")
FOREACH(file ${files})
MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
IF(EXISTS "$ENV{DESTDIR}${file}")
EXEC_PROGRAM(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
IF(NOT "${rm_retval}" STREQUAL 0)
MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
ENDIF(NOT "${rm_retval}" STREQUAL 0)
ELSEIF(IS_SYMLINK "$ENV{DESTDIR}${file}")
EXEC_PROGRAM(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
IF(NOT "${rm_retval}" STREQUAL 0)
MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
ENDIF(NOT "${rm_retval}" STREQUAL 0)
ELSE(EXISTS "$ENV{DESTDIR}${file}")
MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
ENDIF(EXISTS "$ENV{DESTDIR}${file}")
ENDFOREACH(file)

View File

@ -0,0 +1,30 @@
# - Find FFTW
# Find the native FFTW includes and library
#
# FFTW_INCLUDES - where to find fftw3.h
# FFTW_LIBRARIES - List of libraries when using FFTW.
# FFTW_FOUND - True if FFTW found.
if (FFTW_INCLUDES)
# Already in cache, be silent
set (FFTW_FIND_QUIETLY TRUE)
endif (FFTW_INCLUDES)
find_path (FFTW_INCLUDES fftw3.h)
IF (WIN32)
include_directories(${FFTW_INCLUDES})
find_library (FFTW_LIBRARIES NAMES ${FFTW_LIBRARIES})
ELSE(WIN32)
find_library (FFTW_LIBRARIES NAMES fftw3f)
ENDIF(WIN32)
# handle the QUIETLY and REQUIRED arguments and set FFTW_FOUND to TRUE if
# all listed variables are TRUE
include (FindPackageHandleStandardArgs)
find_package_handle_standard_args (FFTW DEFAULT_MSG FFTW_LIBRARIES FFTW_INCLUDES)
mark_as_advanced (FFTW_LIBRARIES FFTW_INCLUDES)

View File

@ -0,0 +1,55 @@
# - Try to find the libhackrf library
# Once done this defines
#
# LIBHACKRF_FOUND - system has libhackrf
# LIBHACKRF_INCLUDE_DIR - the libhackrf include directory
# LIBHACKRF_LIBRARIES - Link these to use libhackrf
# Copyright (c) 2013 Benjamin Vernoux
#
if (LIBHACKRF_INCLUDE_DIR AND LIBHACKRF_LIBRARIES)
# in cache already
set(LIBHACKRF_FOUND TRUE)
else (LIBHACKRF_INCLUDE_DIR AND LIBHACKRF_LIBRARIES)
IF (NOT WIN32)
# use pkg-config to get the directories and then use these values
# in the FIND_PATH() and FIND_LIBRARY() calls
find_package(PkgConfig)
pkg_check_modules(PC_LIBHACKRF QUIET libhackrf)
ENDIF(NOT WIN32)
FIND_PATH(LIBHACKRF_INCLUDE_DIR
NAMES hackrf.h
HINTS $ENV{LIBHACKRF_DIR}/include ${PC_LIBHACKRF_INCLUDEDIR}
PATHS /usr/local/include/libhackrf /usr/include/libhackrf /usr/local/include
/usr/include ${CMAKE_SOURCE_DIR}/../libhackrf/src
/opt/local/include/libhackrf
${LIBHACKRF_INCLUDE_DIR}
)
set(libhackrf_library_names hackrf)
FIND_LIBRARY(LIBHACKRF_LIBRARIES
NAMES ${libhackrf_library_names}
HINTS $ENV{LIBHACKRF_DIR}/lib ${PC_LIBHACKRF_LIBDIR}
PATHS /usr/local/lib /usr/lib /opt/local/lib ${PC_LIBHACKRF_LIBDIR} ${PC_LIBHACKRF_LIBRARY_DIRS} ${CMAKE_SOURCE_DIR}/../libhackrf/src
)
if(LIBHACKRF_INCLUDE_DIR)
set(CMAKE_REQUIRED_INCLUDES ${LIBHACKRF_INCLUDE_DIR})
endif()
if(LIBHACKRF_LIBRARIES)
set(CMAKE_REQUIRED_LIBRARIES ${LIBHACKRF_LIBRARIES})
endif()
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBHACKRF DEFAULT_MSG LIBHACKRF_LIBRARIES LIBHACKRF_INCLUDE_DIR)
MARK_AS_ADVANCED(LIBHACKRF_INCLUDE_DIR LIBHACKRF_LIBRARIES)
endif (LIBHACKRF_INCLUDE_DIR AND LIBHACKRF_LIBRARIES)

View File

@ -0,0 +1,246 @@
# 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()

View File

@ -0,0 +1,43 @@
# - Try to find the freetype library
# Once done this defines
#
# LIBUSB_FOUND - system has libusb
# LIBUSB_INCLUDE_DIR - the libusb include directory
# LIBUSB_LIBRARIES - Link these to use libusb
# Copyright (c) 2006, 2008 Laurent Montel, <montel@kde.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
if (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES)
# in cache already
set(LIBUSB_FOUND TRUE)
else (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES)
IF (NOT WIN32)
# use pkg-config to get the directories and then use these values
# in the FIND_PATH() and FIND_LIBRARY() calls
find_package(PkgConfig)
pkg_check_modules(PC_LIBUSB libusb-1.0)
ENDIF(NOT WIN32)
set(LIBUSB_LIBRARY_NAME usb-1.0)
IF(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
set(LIBUSB_LIBRARY_NAME usb)
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
FIND_PATH(LIBUSB_INCLUDE_DIR libusb.h
PATHS ${PC_LIBUSB_INCLUDEDIR} ${PC_LIBUSB_INCLUDE_DIRS})
FIND_LIBRARY(LIBUSB_LIBRARIES NAMES ${LIBUSB_LIBRARY_NAME}
PATHS ${PC_LIBUSB_LIBDIR} ${PC_LIBUSB_LIBRARY_DIRS})
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBUSB DEFAULT_MSG LIBUSB_LIBRARIES LIBUSB_INCLUDE_DIR)
MARK_AS_ADVANCED(LIBUSB_INCLUDE_DIR LIBUSB_LIBRARIES)
endif (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES)

View File

@ -0,0 +1,26 @@
#set(RELEASE "")
if(NOT DEFINED RELEASE)
execute_process(
COMMAND git log -n 1 --format=%h
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE GIT_EXIT_VALUE
ERROR_QUIET
OUTPUT_VARIABLE GIT_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if (GIT_EXIT_VALUE)
set(RELEASE "unknown")
else (GIT_EXIT_VALUE)
execute_process(
COMMAND git status -s --untracked-files=no
OUTPUT_VARIABLE DIRTY
)
if ( NOT "${DIRTY}" STREQUAL "" )
set(DIRTY_FLAG "*")
else()
set(DIRTY_FLAG "")
endif()
set(RELEASE "git-${GIT_VERSION}${DIRTY_FLAG}")
endif (GIT_EXIT_VALUE)
endif()

View File

@ -0,0 +1,61 @@
# Copyright 2012 Jared Boone
# Copyright 2013 Benjamin Vernoux
#
# This file is part of HackRF.
#
# 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, 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; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
# Based heavily upon the libftdi cmake setup.
cmake_minimum_required(VERSION 2.8)
project(hackrf-tools C)
set(PACKAGE hackrf-tools)
include(${PROJECT_SOURCE_DIR}/../cmake/set_release.cmake)
add_definitions(-DTOOL_RELEASE="${RELEASE}")
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../cmake/modules)
if(MSVC)
include_directories(getopt)
add_definitions(/D _CRT_SECURE_NO_WARNINGS)
else()
add_definitions(-Wall)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu90")
endif()
if(NOT libhackrf_SOURCE_DIR)
find_package(LIBHACKRF REQUIRED)
include_directories(${LIBHACKRF_INCLUDE_DIR})
else()
include_directories(${libhackrf_SOURCE_DIR}/src)
endif()
add_subdirectory(src)
########################################################################
# Create uninstall target
########################################################################
if(NOT HackRF_SOURCE_DIR)
configure_file(
${PROJECT_SOURCE_DIR}/../cmake/cmake_uninstall.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
@ONLY)
add_custom_target(uninstall
${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
)
endif()

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,180 @@
/* Declarations for getopt.
Copyright (C) 1989-1994, 1996-1999, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _GETOPT_H
#ifndef __need_getopt
# define _GETOPT_H 1
#endif
/* If __GNU_LIBRARY__ is not already defined, either we are being used
standalone, or this is the first header included in the source file.
If we are being used with glibc, we need to include <features.h>, but
that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
not defined, include <ctype.h>, which will pull in <features.h> for us
if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
doesn't flood the namespace with stuff the way some other headers do.) */
#if !defined __GNU_LIBRARY__
# include <ctype.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns -1, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
#ifndef __need_getopt
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
# if (defined __STDC__ && __STDC__) || defined __cplusplus
const char *name;
# else
char *name;
# endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
# define no_argument 0
# define required_argument 1
# define optional_argument 2
#endif /* need getopt */
/* Get definitions and prototypes for functions to process the
arguments in ARGV (ARGC of them, minus the program name) for
options given in OPTS.
Return the option character from OPTS just read. Return -1 when
there are no more options. For unrecognized options, or options
missing arguments, `optopt' is set to the option letter, and '?' is
returned.
The OPTS string is a list of characters which are recognized option
letters, optionally followed by colons, specifying that that letter
takes an argument, to be placed in `optarg'.
If a letter in OPTS is followed by two colons, its argument is
optional. This behavior is specific to the GNU `getopt'.
The argument `--' causes premature termination of argument
scanning, explicitly telling `getopt' that there are no more
options.
If OPTS begins with `--', then non-option arguments are treated as
arguments to the option '\0'. This behavior is specific to the GNU
`getopt'. */
#if (defined __STDC__ && __STDC__) || defined __cplusplus
# ifdef __GNU_LIBRARY__
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int __argc, char *const *__argv, const char *__shortopts);
# else /* not __GNU_LIBRARY__ */
extern int getopt ();
# endif /* __GNU_LIBRARY__ */
# ifndef __need_getopt
extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts,
const struct option *__longopts, int *__longind);
extern int getopt_long_only (int __argc, char *const *__argv,
const char *__shortopts,
const struct option *__longopts, int *__longind);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int __argc, char *const *__argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only);
# endif
#else /* not __STDC__ */
extern int getopt ();
# ifndef __need_getopt
extern int getopt_long ();
extern int getopt_long_only ();
extern int _getopt_internal ();
# endif
#endif /* __STDC__ */
#ifdef __cplusplus
}
#endif
/* Make sure we later can get all the definitions and declarations. */
#undef __need_getopt
#endif /* getopt.h */

View File

@ -0,0 +1,66 @@
# Copyright 2012 Jared Boone
# Copyright 2013 Benjamin Vernoux
#
# This file is part of HackRF.
#
# 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, 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; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
# Based heavily upon the libftdi cmake setup.
set(INSTALL_DEFAULT_BINDIR "bin" CACHE STRING "Appended to CMAKE_INSTALL_PREFIX")
find_package(FFTW REQUIRED)
include_directories(${FFTW_INCLUDES})
get_filename_component(FFTW_LIBRARY_DIRS ${FFTW_LIBRARIES} DIRECTORY)
link_directories(${FFTW_LIBRARY_DIRS})
SET(TOOLS
hackrf_transfer
hackrf_spiflash
hackrf_cpldjtag
hackrf_info
hackrf_debug
hackrf_clock
hackrf_sweep
hackrf_operacake
)
if(MSVC)
add_library(libgetopt_static STATIC
../getopt/getopt.c
)
LIST(APPEND TOOLS_LINK_LIBS ${FFTW_LIBRARIES})
else()
LIST(APPEND TOOLS_LINK_LIBS m fftw3f)
endif()
if(NOT libhackrf_SOURCE_DIR)
include_directories(${LIBHACKRF_INCLUDE_DIR})
LIST(APPEND TOOLS_LINK_LIBS ${LIBHACKRF_LIBRARIES})
else()
LIST(APPEND TOOLS_LINK_LIBS hackrf)
endif()
if(MSVC)
LIST(APPEND TOOLS_LINK_LIBS libgetopt_static)
endif()
foreach(tool ${TOOLS})
add_executable(${tool} ${tool}.c)
target_link_libraries(${tool} ${TOOLS_LINK_LIBS})
install(TARGETS ${tool} RUNTIME DESTINATION ${INSTALL_DEFAULT_BINDIR})
endforeach(tool)

View File

@ -0,0 +1,337 @@
/*
* Copyright 2017 Dominic Spill <dominicgs@gmail.com>
*
* This file is part of HackRF.
*
* 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, 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; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include <hackrf.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#ifndef bool
typedef int bool;
#define true 1
#define false 0
#endif
#define CLOCK_UNDEFINED 0xFF
#define REGISTER_INVALID 32767
int parse_int(char* s, uint8_t* const value) {
uint_fast8_t base = 10;
char* s_end;
long long_value;
if( strlen(s) > 2 ) {
if( s[0] == '0' ) {
if( (s[1] == 'x') || (s[1] == 'X') ) {
base = 16;
s += 2;
} else if( (s[1] == 'b') || (s[1] == 'B') ) {
base = 2;
s += 2;
}
}
}
s_end = s;
long_value = strtol(s, &s_end, base);
if( (s != s_end) && (*s_end == 0) ) {
*value = (uint8_t)long_value;
return HACKRF_SUCCESS;
} else {
return HACKRF_ERROR_INVALID_PARAM;
}
}
int si5351c_read_register(hackrf_device* device, const uint16_t register_number) {
uint16_t register_value;
int result = hackrf_si5351c_read(device, register_number, &register_value);
if( result == HACKRF_SUCCESS ) {
printf("[%3d] -> 0x%02x\n", register_number, register_value);
} else {
printf("hackrf_si5351c_read() failed: %s (%d)\n", hackrf_error_name(result), result);
}
return result;
}
int si5351c_write_register(
hackrf_device* device,
const uint16_t register_number,
const uint16_t register_value
) {
int result = HACKRF_SUCCESS;
result = hackrf_si5351c_write(device, register_number, register_value);
if( result == HACKRF_SUCCESS ) {
printf("0x%2x -> [%3d]\n", register_value, register_number);
} else {
printf("hackrf_max2837_write() failed: %s (%d)\n", hackrf_error_name(result), result);
}
return result;
}
#define SI5351C_CLK_POWERDOWN (1<<7)
#define SI5351C_CLK_INT_MODE (1<<6)
#define SI5351C_CLK_PLL_SRC (1<<5)
#define SI5351C_CLK_INV (1<<4)
#define SI5351C_CLK_SRC_XTAL 0
#define SI5351C_CLK_SRC_CLKIN 1
#define SI5351C_CLK_SRC_MULTISYNTH_0_4 2
#define SI5351C_CLK_SRC_MULTISYNTH_SELF 3
void print_clk_control(uint16_t clk_ctrl) {
uint8_t clk_src, clk_pwr;
printf("\tclock control = ");
if(clk_ctrl & SI5351C_CLK_POWERDOWN)
printf("Down, ");
else
printf("Up, ");
if(clk_ctrl & SI5351C_CLK_INT_MODE)
printf("Int Mode, ");
else
printf("Frac Mode, ");
if(clk_ctrl & SI5351C_CLK_PLL_SRC)
printf("PLL src B, ");
else
printf("PLL src A, ");
if(clk_ctrl & SI5351C_CLK_INV)
printf("Inverted, ");
clk_src = (clk_ctrl >> 2) & 0x3;
switch (clk_src) {
case 0:
printf("XTAL, ");
break;
case 1:
printf("CLKIN, ");
break;
case 2:
printf("MULTISYNTH 0 4, ");
break;
case 3:
printf("MULTISYNTH SELF, ");
break;
}
clk_pwr = clk_ctrl & 0x3;
switch (clk_pwr) {
case 0:
printf("2 mA\n");
break;
case 1:
printf("4 mA\n");
break;
case 2:
printf("6 mA\n");
break;
case 3:
printf("8 mA\n");
break;
}
}
int si5351c_read_multisynth_config(hackrf_device* device, const uint_fast8_t ms_number) {
uint_fast8_t i, reg_base, reg_number;
uint16_t parameters[8], clk_control;
uint32_t p1,p2,p3,r_div;
uint_fast8_t div_lut[] = {1,2,4,8,16,32,64,128};
int result;
printf("MS%d:\n", ms_number);
result = hackrf_si5351c_read(device, 16+ms_number, &clk_control);
if( result != HACKRF_SUCCESS ) {
return result;
}
print_clk_control(clk_control);
if(ms_number <6){
reg_base = 42 + (ms_number * 8);
for(i=0; i<8; i++) {
reg_number = reg_base + i;
result = hackrf_si5351c_read(device, reg_number, &parameters[i]);
if( result != HACKRF_SUCCESS ) {
return result;
}
}
p1 = ((parameters[2] & 0x03) << 16)
| (parameters[3] << 8)
| parameters[4];
p2 = ((parameters[5] & 0x0F) << 16)
| (parameters[6] << 8)
| parameters[7];
p3 = ((parameters[5] & 0xF0) << 12)
| (parameters[0] << 8)
| parameters[1];
r_div = (parameters[2] >> 4) & 0x7;
printf("\tp1 = %u\n", p1);
printf("\tp2 = %u\n", p2);
printf("\tp3 = %u\n", p3);
if(p3)
printf("\tOutput (800Mhz PLL): %#.10f Mhz\n", ((double)800 / (double)(((double)p1*p3 + p2 + 512*p3)/(double)(128*p3))) / div_lut[r_div] );
} else {
// MS6 and 7 are integer only
unsigned int parms;
reg_base = 90;
for(i=0; i<3; i++) {
uint_fast8_t reg_number = reg_base + i;
int result = hackrf_si5351c_read(device, reg_number, &parameters[i]);
if( result != HACKRF_SUCCESS ) {
return result;
}
}
r_div = (ms_number == 6) ? parameters[2] & 0x7 : (parameters[2] & 0x70) >> 4 ;
parms = (ms_number == 6) ? parameters[0] : parameters[1];
printf("\tp1_int = %u\n", parms);
if(parms)
printf("\tOutput (800Mhz PLL): %#.10f Mhz\n", (800.0f / parms) / div_lut[r_div] );
}
printf("\toutput divider = %u\n", div_lut[r_div]);
return HACKRF_SUCCESS;
}
int si5351c_read_configuration(hackrf_device* device) {
uint_fast8_t ms_number;
int result;
for(ms_number=0; ms_number<8; ms_number++) {
result = si5351c_read_multisynth_config(device, ms_number);
if( result != HACKRF_SUCCESS ) {
return result;
}
}
return HACKRF_SUCCESS;
}
static void usage() {
printf("hackrf_clock - HackRF clock configuration utility\n");
printf("Usage:\n");
printf("\t-h, --help: this help\n");
printf("\t-r, --read <clock_num>: read settings for clock_num\n");
printf("\t-a, --all: read settings for all clocks\n");
printf("\t-o, --clkout <clkout_enable>: enable/disable CLKOUT\n");
printf("\t-d, --device <serial_number>: Serial number of desired HackRF.\n");
printf("\nExamples:\n");
printf("\thackrf_clock -r 3 : prints settings for CLKOUT\n");
}
static struct option long_options[] = {
{ "help", no_argument, 0, 'h' },
{ "read", required_argument, 0, 'r' },
{ "all", no_argument, 0, 'a' },
{ "clkout", required_argument, 0, 'o' },
{ "device", required_argument, 0, 'd' },
{ 0, 0, 0, 0 },
};
int main(int argc, char** argv) {
hackrf_device* device = NULL;
int opt, option_index = 0;
bool read = false;
uint8_t clock = CLOCK_UNDEFINED;
bool clkout = false;
uint8_t clkout_enable;
const char* serial_number = NULL;
int result = hackrf_init();
if(result) {
printf("hackrf_init() failed: %s (%d)\n", hackrf_error_name(result), result);
return EXIT_FAILURE;
}
while( (opt = getopt_long(argc, argv, "r:ao:d:h?", long_options, &option_index)) != EOF ) {
switch( opt ) {
case 'r':
read = true;
result = parse_int(optarg, &clock);
break;
case 'a':
read = true;
break;
case 'o':
clkout = true;
result = parse_int(optarg, &clkout_enable);
break;
case 'd':
serial_number = optarg;
break;
case 'h':
case '?':
usage();
return EXIT_SUCCESS;
default:
fprintf(stderr, "unknown argument '-%c %s'\n", opt, optarg);
usage();
return EXIT_FAILURE;
}
if(result != HACKRF_SUCCESS) {
printf("argument error: %s (%d)\n", hackrf_error_name(result), result);
usage();
return EXIT_FAILURE;
}
}
if(!clkout && !read) {
fprintf(stderr, "Either read or enable CLKOUT option must be specified.\n");
usage();
return EXIT_FAILURE;
}
result = hackrf_open_by_serial(serial_number, &device);
if(result) {
printf("hackrf_open() failed: %s (%d)\n", hackrf_error_name(result), result);
return EXIT_FAILURE;
}
if(clkout) {
result = hackrf_set_clkout_enable(device, clkout_enable);
if(result) {
printf("hackrf_set_clkout_enable() failed: %s (%d)\n", hackrf_error_name(result), result);
return EXIT_FAILURE;
}
}
if(read) {
if(clock == CLOCK_UNDEFINED)
si5351c_read_configuration(device);
else {
printf("%d\n", clock);
si5351c_read_multisynth_config(device, clock);
}
}
result = hackrf_close(device);
if(result) {
printf("hackrf_close() failed: %s (%d)\n", hackrf_error_name(result), result);
return EXIT_FAILURE;
}
hackrf_exit();
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,208 @@
/*
* Copyright 2012 Jared Boone <jared@sharebrained.com>
* Copyright 2013 Benjamin Vernoux <titanmkd@gmail.com>
* Copyright 2013 Michael Ossmann <mike@ossmann.com>
*
* This file is part of HackRF.
*
* 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, 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; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include <hackrf.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <sys/types.h>
#include <stdint.h>
#ifdef _MSC_VER
#ifdef _WIN64
typedef int64_t ssize_t;
#else
typedef int32_t ssize_t;
#endif
#endif
/* input file shouldn't be any longer than this */
#define MAX_XSVF_LENGTH 0x10000
#define PACKET_LEN 4096
uint8_t data[MAX_XSVF_LENGTH];
static struct option long_options[] = {
{ "xsvf", required_argument, 0, 'x' },
{ "device", required_argument, 0, 'd' },
{ "help", no_argument, 0, 'h' },
{ 0, 0, 0, 0 },
};
int parse_int(char* s, uint32_t* const value)
{
uint_fast8_t base = 10;
char* s_end;
long long_value;
if (strlen(s) > 2) {
if (s[0] == '0') {
if ((s[1] == 'x') || (s[1] == 'X')) {
base = 16;
s += 2;
} else if ((s[1] == 'b') || (s[1] == 'B')) {
base = 2;
s += 2;
}
}
}
s_end = s;
long_value = strtol(s, &s_end, base);
if ((s != s_end) && (*s_end == 0)) {
*value = long_value;
return HACKRF_SUCCESS;
} else {
return HACKRF_ERROR_INVALID_PARAM;
}
}
static void usage()
{
printf("Usage:\n");
printf("\t-h, --help: this help\n");
printf("\t-x, --xsvf <filename>: XSVF file to be written to CPLD.\n");
printf("\t-d, --device <serialnumber>: Serial number of device, if multiple devices\n");
}
int main(int argc, char** argv)
{
int opt;
uint32_t length = 0;
uint32_t total_length = 0;
const char* path = NULL;
const char* serial_number = NULL;
hackrf_device* device = NULL;
int result = HACKRF_SUCCESS;
int option_index = 0;
FILE* infile = NULL;
ssize_t bytes_read;
uint8_t* pdata = &data[0];
while ((opt = getopt_long(argc, argv, "x:d:h?", long_options,
&option_index)) != EOF) {
switch (opt) {
case 'x':
path = optarg;
break;
case 'd':
serial_number = optarg;
break;
case 'h':
case '?':
usage();
return EXIT_SUCCESS;
default:
fprintf(stderr, "unknown argument '-%c %s'\n", opt, optarg);
usage();
return EXIT_FAILURE;
}
}
if (path == NULL) {
fprintf(stderr, "Specify a path to a file.\n");
usage();
return EXIT_FAILURE;
}
infile = fopen(path, "rb");
if (infile == NULL)
{
fprintf(stderr, "Failed to open file: %s\n", path);
return EXIT_FAILURE;
}
/* Get size of the file */
fseek(infile, 0, SEEK_END); /* Not really portable but work on major OS Linux/Win32 */
length = ftell(infile);
/* Move to start */
rewind(infile);
printf("File size %d bytes.\n", length);
if (length > MAX_XSVF_LENGTH) {
fprintf(stderr, "XSVF file too large.\n");
usage();
return EXIT_FAILURE;
}
total_length = length;
bytes_read = fread(data, 1, total_length, infile);
if (bytes_read != total_length)
{
fprintf(stderr, "Failed to read all bytes (read %d bytes instead of %d bytes).\n",
(int)bytes_read, total_length);
fclose(infile);
infile = NULL;
return EXIT_FAILURE;
}
result = hackrf_init();
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_init() failed: %s (%d)\n",
hackrf_error_name(result), result);
return EXIT_FAILURE;
}
result = hackrf_open_by_serial(serial_number, &device);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_open() failed: %s (%d)\n",
hackrf_error_name(result), result);
return EXIT_FAILURE;
}
printf("LED1/2/3 blinking means CPLD program success.\nLED3/RED steady means error.\n");
printf("Wait message 'Write finished' or in case of LED3/RED steady, Power OFF/Disconnect the HackRF.\n");
result = hackrf_cpld_write(device, pdata, total_length);
if (result != HACKRF_SUCCESS)
{
fprintf(stderr, "hackrf_cpld_write() failed: %s (%d)\n",
hackrf_error_name(result), result);
fclose(infile);
infile = NULL;
return EXIT_FAILURE;
}
printf("Write finished.\n");
printf("Please Power OFF/Disconnect the HackRF.\n");
fflush(stdout);
result = hackrf_close(device);
if( result != HACKRF_SUCCESS )
{
fprintf(stderr, "hackrf_close() failed: %s (%d)\n",
hackrf_error_name(result), result);
fclose(infile);
infile = NULL;
return EXIT_FAILURE;
}
hackrf_exit();
if (infile != NULL) {
fclose(infile);
}
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,651 @@
/*
* Copyright 2012 Jared Boone <jared@sharebrained.com>
* Copyright 2013 Benjamin Vernoux <titanmkd@gmail.com>
* Copyright 2017 Dominic Spill <dominicgs@gmail.com>
*
* This file is part of HackRF.
*
* 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, 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; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include <hackrf.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#ifndef bool
typedef int bool;
#define true 1
#define false 0
#endif
#define REGISTER_INVALID 32767
int parse_int(char* s, uint32_t* const value) {
uint_fast8_t base = 10;
char* s_end;
long long_value;
if( strlen(s) > 2 ) {
if( s[0] == '0' ) {
if( (s[1] == 'x') || (s[1] == 'X') ) {
base = 16;
s += 2;
} else if( (s[1] == 'b') || (s[1] == 'B') ) {
base = 2;
s += 2;
}
}
}
s_end = s;
long_value = strtol(s, &s_end, base);
if( (s != s_end) && (*s_end == 0) ) {
*value = (uint32_t)long_value;
return HACKRF_SUCCESS;
} else {
return HACKRF_ERROR_INVALID_PARAM;
}
}
int max2837_read_register(hackrf_device* device, const uint16_t register_number) {
uint16_t register_value;
int result = hackrf_max2837_read(device, (uint8_t)register_number, &register_value);
if( result == HACKRF_SUCCESS ) {
printf("[%2d] -> 0x%03x\n", register_number, register_value);
} else {
printf("hackrf_max2837_read() failed: %s (%d)\n", hackrf_error_name(result), result);
}
return result;
}
int max2837_read_registers(hackrf_device* device) {
uint16_t register_number;
int result = HACKRF_SUCCESS;
for(register_number=0; register_number<32; register_number++) {
result = max2837_read_register(device, register_number);
if( result != HACKRF_SUCCESS ) {
break;
}
}
return result;
}
int max2837_write_register(
hackrf_device* device,
const uint16_t register_number,
const uint16_t register_value
) {
int result = HACKRF_SUCCESS;
result = hackrf_max2837_write(device, (uint8_t)register_number, register_value);
if( result == HACKRF_SUCCESS ) {
printf("0x%03x -> [%2d]\n", register_value, register_number);
} else {
printf("hackrf_max2837_write() failed: %s (%d)\n", hackrf_error_name(result), result);
}
return result;
}
int si5351c_read_register(hackrf_device* device, const uint16_t register_number) {
uint16_t register_value;
int result = hackrf_si5351c_read(device, register_number, &register_value);
if( result == HACKRF_SUCCESS ) {
printf("[%3d] -> 0x%02x\n", register_number, register_value);
} else {
printf("hackrf_si5351c_read() failed: %s (%d)\n", hackrf_error_name(result), result);
}
return result;
}
int si5351c_read_registers(hackrf_device* device) {
uint16_t register_number;
int result = HACKRF_SUCCESS;
for(register_number=0; register_number<256; register_number++) {
result = si5351c_read_register(device, register_number);
if( result != HACKRF_SUCCESS ) {
break;
}
}
return result;
}
int si5351c_write_register(
hackrf_device* device,
const uint16_t register_number,
const uint16_t register_value
) {
int result = HACKRF_SUCCESS;
result = hackrf_si5351c_write(device, register_number, register_value);
if( result == HACKRF_SUCCESS ) {
printf("0x%2x -> [%3d]\n", register_value, register_number);
} else {
printf("hackrf_max2837_write() failed: %s (%d)\n", hackrf_error_name(result), result);
}
return result;
}
#define SI5351C_CLK_POWERDOWN (1<<7)
#define SI5351C_CLK_INT_MODE (1<<6)
#define SI5351C_CLK_PLL_SRC (1<<5)
#define SI5351C_CLK_INV (1<<4)
#define SI5351C_CLK_SRC_XTAL 0
#define SI5351C_CLK_SRC_CLKIN 1
#define SI5351C_CLK_SRC_MULTISYNTH_0_4 2
#define SI5351C_CLK_SRC_MULTISYNTH_SELF 3
void print_clk_control(uint16_t clk_ctrl) {
uint8_t clk_src, clk_pwr;
printf("\tclock control = \n");
if(clk_ctrl & SI5351C_CLK_POWERDOWN)
printf("\t\tPower Down\n");
else
printf("\t\tPower Up\n");
if(clk_ctrl & SI5351C_CLK_INT_MODE)
printf("\t\tInt Mode\n");
else
printf("\t\tFrac Mode\n");
if(clk_ctrl & SI5351C_CLK_PLL_SRC)
printf("\t\tPLL src B\n");
else
printf("\t\tPLL src A\n");
if(clk_ctrl & SI5351C_CLK_INV)
printf("\t\tInverted\n");
clk_src = (clk_ctrl >> 2) & 0x3;
switch (clk_src) {
case 0:
printf("\t\tXTAL\n");
break;
case 1:
printf("\t\tCLKIN\n");
break;
case 2:
printf("\t\tMULTISYNTH 0 4\n");
break;
case 3:
printf("\t\tMULTISYNTH SELF\n");
break;
}
clk_pwr = clk_ctrl & 0x3;
switch (clk_pwr) {
case 0:
printf("\t\t2 mA\n");
break;
case 1:
printf("\t\t4 mA\n");
break;
case 2:
printf("\t\t6 mA\n");
break;
case 3:
printf("\t\t8 mA\n");
break;
}
}
int si5351c_read_multisynth_config(hackrf_device* device, const uint_fast8_t ms_number) {
uint_fast8_t i, reg_base, reg_number;
uint16_t parameters[8], clk_control;
uint32_t p1,p2,p3,r_div;
uint_fast8_t div_lut[] = {1,2,4,8,16,32,64,128};
int result;
printf("MS%d:", ms_number);
result = hackrf_si5351c_read(device, 16+ms_number, &clk_control);
if( result != HACKRF_SUCCESS ) {
return result;
}
print_clk_control(clk_control);
if(ms_number <6){
reg_base = 42 + (ms_number * 8);
for(i=0; i<8; i++) {
reg_number = reg_base + i;
result = hackrf_si5351c_read(device, reg_number, &parameters[i]);
if( result != HACKRF_SUCCESS ) {
return result;
}
}
p1 = ((parameters[2] & 0x03) << 16)
| (parameters[3] << 8)
| parameters[4];
p2 = ((parameters[5] & 0x0F) << 16)
| (parameters[6] << 8)
| parameters[7];
p3 = ((parameters[5] & 0xF0) << 12)
| (parameters[0] << 8)
| parameters[1];
r_div = (parameters[2] >> 4) & 0x7;
printf("\tp1 = %u\n", p1);
printf("\tp2 = %u\n", p2);
printf("\tp3 = %u\n", p3);
if(p3)
printf("\tOutput (800Mhz PLL): %#.10f Mhz\n", ((double)800 / (double)(((double)p1*p3 + p2 + 512*p3)/(double)(128*p3))) / div_lut[r_div] );
} else {
// MS6 and 7 are integer only
unsigned int parms;
reg_base = 90;
for(i=0; i<3; i++) {
uint_fast8_t reg_number = reg_base + i;
int result = hackrf_si5351c_read(device, reg_number, &parameters[i]);
if( result != HACKRF_SUCCESS ) {
return result;
}
}
r_div = (ms_number == 6) ? parameters[2] & 0x7 : (parameters[2] & 0x70) >> 4 ;
parms = (ms_number == 6) ? parameters[0] : parameters[1];
printf("\tp1_int = %u\n", parms);
if(parms)
printf("\tOutput (800Mhz PLL): %#.10f Mhz\n", (800.0f / parms) / div_lut[r_div] );
}
printf("\toutput divider = %u\n", div_lut[r_div]);
return HACKRF_SUCCESS;
}
int si5351c_read_configuration(hackrf_device* device) {
uint_fast8_t ms_number;
int result;
for(ms_number=0; ms_number<8; ms_number++) {
result = si5351c_read_multisynth_config(device, ms_number);
if( result != HACKRF_SUCCESS ) {
return result;
}
}
return HACKRF_SUCCESS;
}
/*
* RFFC5071 and RFFC5072 are similar components with a compatible control
* interface. RFFC5071 was used on some early prototypes, so the libhackrf API
* calls are named that way. Because we use RFFC5072 on production hardware,
* we use that name here and present it to the user.
*/
int rffc5072_read_register(hackrf_device* device, const uint16_t register_number) {
uint16_t register_value;
int result = hackrf_rffc5071_read(device, (uint8_t)register_number, &register_value);
if( result == HACKRF_SUCCESS ) {
printf("[%2d] -> 0x%03x\n", register_number, register_value);
} else {
printf("hackrf_rffc5071_read() failed: %s (%d)\n", hackrf_error_name(result), result);
}
return result;
}
int rffc5072_read_registers(hackrf_device* device) {
uint16_t register_number;
int result = HACKRF_SUCCESS;
for(register_number=0; register_number<31; register_number++) {
result = rffc5072_read_register(device, register_number);
if( result != HACKRF_SUCCESS ) {
break;
}
}
return result;
}
int rffc5072_write_register(
hackrf_device* device,
const uint16_t register_number,
const uint16_t register_value
) {
int result = HACKRF_SUCCESS;
result = hackrf_rffc5071_write(device, (uint8_t)register_number, register_value);
if( result == HACKRF_SUCCESS ) {
printf("0x%03x -> [%2d]\n", register_value, register_number);
} else {
printf("hackrf_rffc5071_write() failed: %s (%d)\n", hackrf_error_name(result), result);
}
return result;
}
enum parts {
PART_NONE = 0,
PART_MAX2837 = 1,
PART_SI5351C = 2,
PART_RFFC5072 = 3,
};
int read_register(hackrf_device* device, uint8_t part,
const uint16_t register_number) {
switch (part) {
case PART_MAX2837:
return max2837_read_register(device, register_number);
case PART_SI5351C:
return si5351c_read_register(device, register_number);
case PART_RFFC5072:
return rffc5072_read_register(device, register_number);
}
return HACKRF_ERROR_INVALID_PARAM;
}
int read_registers(hackrf_device* device, uint8_t part) {
switch (part) {
case PART_MAX2837:
return max2837_read_registers(device);
case PART_SI5351C:
return si5351c_read_registers(device);
case PART_RFFC5072:
return rffc5072_read_registers(device);
}
return HACKRF_ERROR_INVALID_PARAM;
}
int write_register(hackrf_device* device, uint8_t part,
const uint16_t register_number,
const uint16_t register_value) {
switch (part) {
case PART_MAX2837:
return max2837_write_register(device, register_number, register_value);
case PART_SI5351C:
return si5351c_write_register(device, register_number, register_value);
case PART_RFFC5072:
return rffc5072_write_register(device, register_number, register_value);
}
return HACKRF_ERROR_INVALID_PARAM;
}
static const char * mode_name(uint32_t mode) {
const char *mode_names[] = {"IDLE", "WAIT", "RX", "TX_START", "TX_RUN"};
const uint32_t num_modes = sizeof(mode_names) / sizeof(mode_names[0]);
if (mode < num_modes)
return mode_names[mode];
else
return "UNKNOWN";
}
static const char * error_name(uint32_t error) {
const char *error_names[] = {"NONE", "RX_TIMEOUT", "TX_TIMEOUT"};
const uint32_t num_errors = sizeof(error_names) / sizeof(error_names[0]);
if (error < num_errors)
return error_names[error];
else
return "UNKNOWN";
}
static void print_state(hackrf_m0_state *state) {
printf("M0 state:\n");
printf("Requested mode: %u (%s) [%s]\n",
state->requested_mode, mode_name(state->requested_mode),
state->request_flag ? "pending" : "complete");
printf("Active mode: %u (%s)\n", state->active_mode, mode_name(state->active_mode));
printf("M0 count: %u bytes\n", state->m0_count);
printf("M4 count: %u bytes\n", state->m4_count);
printf("Number of shortfalls: %u\n", state->num_shortfalls);
printf("Longest shortfall: %u bytes\n", state->longest_shortfall);
printf("Shortfall limit: %u bytes\n", state->shortfall_limit);
printf("Mode change threshold: %u bytes\n", state->threshold);
printf("Next mode: %u (%s)\n", state->next_mode, mode_name(state->next_mode));
printf("Error: %u (%s)\n", state->error, error_name(state->error));
}
static void usage() {
printf("\nUsage:\n");
printf("\t-h, --help: this help\n");
printf("\t-n, --register <n>: set register number for read/write operations\n");
printf("\t-r, --read: read register specified by last -n argument, or all registers\n");
printf("\t-w, --write <v>: write register specified by last -n argument with value <v>\n");
printf("\t-c, --config: print SI5351C multisynth configuration information\n");
printf("\t-d, --device <s>: specify a particular device by serial number\n");
printf("\t-m, --max2837: target MAX2837\n");
printf("\t-s, --si5351c: target SI5351C\n");
printf("\t-f, --rffc5072: target RFFC5072\n");
printf("\t-S, --state: display M0 state\n");
printf("\t-T, --tx-underrun-limit <n>: set TX underrun limit in bytes (0 for no limit)\n");
printf("\t-R, --rx-overrun-limit <n>: set RX overrun limit in bytes (0 for no limit)\n");
printf("\t-u, --ui <1/0>: enable/disable UI\n");
printf("\nExamples:\n");
printf("\thackrf_debug --si5351c -n 0 -r # reads from si5351c register 0\n");
printf("\thackrf_debug --si5351c -c # displays si5351c multisynth configuration\n");
printf("\thackrf_debug --rffc5072 -r # reads all rffc5072 registers\n");
printf("\thackrf_debug --max2837 -n 10 -w 22 # writes max2837 register 10 with 22 decimal\n");
printf("\thackrf_debug --state # displays M0 state\n");
}
static struct option long_options[] = {
{ "config", no_argument, 0, 'c' },
{ "register", required_argument, 0, 'n' },
{ "write", required_argument, 0, 'w' },
{ "read", no_argument, 0, 'r' },
{ "device", no_argument, 0, 'd' },
{ "help", no_argument, 0, 'h' },
{ "max2837", no_argument, 0, 'm' },
{ "si5351c", no_argument, 0, 's' },
{ "rffc5072", no_argument, 0, 'f' },
{ "state", no_argument, 0, 'S' },
{ "tx-underrun-limit", required_argument, 0, 'T' },
{ "rx-overrun-limit", required_argument, 0, 'R' },
{ "ui", required_argument, 0, 'u' },
{ 0, 0, 0, 0 },
};
int main(int argc, char** argv) {
int opt;
uint32_t register_number = REGISTER_INVALID;
uint32_t register_value;
hackrf_device* device = NULL;
int option_index = 0;
bool read = false;
bool write = false;
bool dump_config = false;
bool dump_state = false;
uint8_t part = PART_NONE;
const char* serial_number = NULL;
bool set_ui = false;
uint32_t ui_enable;
uint32_t tx_limit;
uint32_t rx_limit;
bool set_tx_limit = false;
bool set_rx_limit = false;
int result = hackrf_init();
if(result) {
printf("hackrf_init() failed: %s (%d)\n", hackrf_error_name(result), result);
return EXIT_FAILURE;
}
while( (opt = getopt_long(argc, argv, "n:rw:d:cmsfST:R:h?u:", long_options, &option_index)) != EOF ) {
switch( opt ) {
case 'n':
result = parse_int(optarg, &register_number);
break;
case 'w':
write = true;
result = parse_int(optarg, &register_value);
break;
case 'r':
read = true;
break;
case 'c':
dump_config = true;
break;
case 'S':
dump_state = true;
break;
case 'T':
set_tx_limit = true;
result = parse_int(optarg, &tx_limit);
break;
case 'R':
set_rx_limit = true;
result = parse_int(optarg, &rx_limit);
break;
case 'd':
serial_number = optarg;
break;
case 'm':
if(part != PART_NONE) {
fprintf(stderr, "Only one part can be specified.'\n");
return EXIT_FAILURE;
}
part = PART_MAX2837;
break;
case 's':
if(part != PART_NONE) {
fprintf(stderr, "Only one part can be specified.'\n");
return EXIT_FAILURE;
}
part = PART_SI5351C;
break;
case 'f':
if(part != PART_NONE) {
fprintf(stderr, "Only one part can be specified.'\n");
return EXIT_FAILURE;
}
part = PART_RFFC5072;
break;
case 'u':
set_ui = true;
result = parse_int(optarg, &ui_enable);
break;
case 'h':
case '?':
usage();
return EXIT_SUCCESS;
default:
fprintf(stderr, "unknown argument '-%c %s'\n", opt, optarg);
usage();
return EXIT_FAILURE;
}
if(result != HACKRF_SUCCESS) {
printf("argument error: %s (%d)\n", hackrf_error_name(result), result);
usage();
return EXIT_FAILURE;
}
}
if(write && read) {
fprintf(stderr, "Read and write options are mutually exclusive.\n");
usage();
return EXIT_FAILURE;
}
if(write && dump_config) {
fprintf(stderr, "Config and write options are mutually exclusive.\n");
usage();
return EXIT_FAILURE;
}
if(dump_config && part != PART_SI5351C) {
fprintf(stderr, "Config option is only valid for SI5351C.\n");
usage();
return EXIT_FAILURE;
}
if(!(write || read || dump_config || dump_state || set_tx_limit || set_rx_limit || set_ui)) {
fprintf(stderr, "Specify read, write, or config option.\n");
usage();
return EXIT_FAILURE;
}
if(part == PART_NONE && !set_ui && !dump_state && !set_tx_limit && !set_rx_limit) {
fprintf(stderr, "Specify a part to read, write, or print config from.\n");
usage();
return EXIT_FAILURE;
}
result = hackrf_open_by_serial(serial_number, &device);
if(result) {
printf("hackrf_open() failed: %s (%d)\n", hackrf_error_name(result), result);
return EXIT_FAILURE;
}
if(write) {
result = write_register(device, part, register_number, register_value);
}
if(read) {
if(register_number == REGISTER_INVALID) {
result = read_registers(device, part);
} else {
result = read_register(device, part, register_number);
}
}
if(dump_config) {
si5351c_read_configuration(device);
}
if (set_tx_limit) {
result = hackrf_set_tx_underrun_limit(device, tx_limit);
if(result != HACKRF_SUCCESS) {
printf("hackrf_set_tx_underrun_limit() failed: %s (%d)\n", hackrf_error_name(result), result);
return EXIT_FAILURE;
}
}
if (set_rx_limit) {
result = hackrf_set_rx_overrun_limit(device, rx_limit);
if(result != HACKRF_SUCCESS) {
printf("hackrf_set_rx_overrun_limit() failed: %s (%d)\n", hackrf_error_name(result), result);
return EXIT_FAILURE;
}
}
if(dump_state) {
hackrf_m0_state state;
result = hackrf_get_m0_state(device, &state);
if(result != HACKRF_SUCCESS) {
printf("hackrf_get_m0_state() failed: %s (%d)\n", hackrf_error_name(result), result);
return EXIT_FAILURE;
}
print_state(&state);
}
if(set_ui) {
result = hackrf_set_ui_enable(device, ui_enable);
}
result = hackrf_close(device);
if(result) {
printf("hackrf_close() failed: %s (%d)\n", hackrf_error_name(result), result);
return EXIT_FAILURE;
}
hackrf_exit();
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,153 @@
/*
* Copyright 2012 Jared Boone <jared@sharebrained.com>
* Copyright 2013 Benjamin Vernoux <titanmkd@gmail.com>
* Copyright 2013 Michael Ossmann <mike@ossmann.com>
*
* This file is part of HackRF.
*
* 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, 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; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include <hackrf.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int result = HACKRF_SUCCESS;
uint8_t board_id = BOARD_ID_INVALID;
char version[255 + 1];
uint16_t usb_version;
read_partid_serialno_t read_partid_serialno;
uint8_t operacakes[8];
hackrf_device_list_t *list;
hackrf_device* device;
int i, j;
result = hackrf_init();
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_init() failed: %s (%d)\n",
hackrf_error_name(result), result);
return EXIT_FAILURE;
}
printf("hackrf_info version: %s\n", TOOL_RELEASE);
printf("libhackrf version: %s (%s)\n", hackrf_library_release(),
hackrf_library_version());
list = hackrf_device_list();
if (list->devicecount < 1 ) {
printf("No HackRF boards found.\n");
return EXIT_FAILURE;
}
for (i = 0; i < list->devicecount; i++) {
if (i > 0)
printf("\n");
printf("Found HackRF\n");
printf("Index: %d\n", i);
if (list->serial_numbers[i])
printf("Serial number: %s\n", list->serial_numbers[i]);
device = NULL;
result = hackrf_device_list_open(list, i, &device);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_open() failed: %s (%d)\n",
hackrf_error_name(result), result);
if(result == HACKRF_ERROR_LIBUSB) {
continue;
}
return EXIT_FAILURE;
}
result = hackrf_board_id_read(device, &board_id);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_board_id_read() failed: %s (%d)\n",
hackrf_error_name(result), result);
return EXIT_FAILURE;
}
printf("Board ID Number: %d (%s)\n", board_id,
hackrf_board_id_name(board_id));
result = hackrf_version_string_read(device, &version[0], 255);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_version_string_read() failed: %s (%d)\n",
hackrf_error_name(result), result);
return EXIT_FAILURE;
}
result = hackrf_usb_api_version_read(device, &usb_version);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_usb_api_version_read() failed: %s (%d)\n",
hackrf_error_name(result), result);
return EXIT_FAILURE;
}
printf("Firmware Version: %s (API:%x.%02x)\n", version,
(usb_version>>8)&0xFF, usb_version&0xFF);
result = hackrf_board_partid_serialno_read(device, &read_partid_serialno);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_board_partid_serialno_read() failed: %s (%d)\n",
hackrf_error_name(result), result);
return EXIT_FAILURE;
}
printf("Part ID Number: 0x%08x 0x%08x\n",
read_partid_serialno.part_id[0],
read_partid_serialno.part_id[1]);
result = hackrf_get_operacake_boards(device, &operacakes[0]);
if ((result != HACKRF_SUCCESS) && (result != HACKRF_ERROR_USB_API_VERSION)) {
fprintf(stderr, "hackrf_get_operacake_boards() failed: %s (%d)\n",
hackrf_error_name(result), result);
return EXIT_FAILURE;
}
if(result == HACKRF_SUCCESS) {
for(j=0; j<8; j++) {
if(operacakes[j] == HACKRF_OPERACAKE_ADDRESS_INVALID)
break;
printf("Opera Cake found, address: %d\n", operacakes[j]);
}
}
#ifdef HACKRF_ISSUE_609_IS_FIXED
uint32_t cpld_crc = 0;
result = hackrf_cpld_checksum(device, &cpld_crc);
if ((result != HACKRF_SUCCESS) && (result != HACKRF_ERROR_USB_API_VERSION)) {
fprintf(stderr, "hackrf_cpld_checksum() failed: %s (%d)\n",
hackrf_error_name(result), result);
return EXIT_FAILURE;
}
if(result == HACKRF_SUCCESS) {
printf("CPLD checksum: 0x%08x\n", cpld_crc);
}
#endif /* HACKRF_ISSUE_609_IS_FIXED */
result = hackrf_close(device);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_close() failed: %s (%d)\n",
hackrf_error_name(result), result);
}
}
hackrf_device_list_free(list);
hackrf_exit();
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,483 @@
/*
* Copyright 2016 Dominic Spill <dominicgs@gmail.com>
*
* This file is part of HackRF.
*
* 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, 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; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include <hackrf.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#ifndef bool
typedef int bool;
#define true 1
#define false 0
#endif
#define FREQ_MIN_MHZ (0) /* 0 MHz */
#define FREQ_MAX_MHZ (7250) /* 7250 MHz */
#define INVALID_ADDRESS 0xFF
#define INVALID_MODE 0xFF
#define INVALID_PORT 0xFF
#define GPIO_TEST_DISABLED 0xFFFF
static void usage() {
printf("\nUsage:\n");
printf("\t-h, --help: this help\n");
printf("\t-d, --device <n>: specify a particular device by serial number\n");
printf("\t-o, --address <n>: specify a particular operacake by address [default: 0]\n");
printf("\t-m, --mode <mode>: specify switching mode [options: manual, frequency, time]\n");
printf("\t-a <n>: set port A connection\n");
printf("\t-b <n>: set port B connection\n");
printf("\t-f <port:min:max>: automatically assign <port> for range <min:max> in MHz\n");
printf("\t-t <port:dwell>: in time-switching mode, dwell on <port> for <dwell> samples. Specify only <port> to use the default dwell time (with -w). This argument can be repeated to specify a list of ports.\n");
printf("\t-w <n>: set default dwell time for time-switching mode\n");
printf("\t-l, --list: list available operacake boards\n");
printf("\t-g, --gpio_test: test GPIO functionality of an opera cake\n");
}
static struct option long_options[] = {
{ "device", required_argument, 0, 'd' },
{ "address", required_argument, 0, 'o' },
{ "mode", required_argument, 0, 'm' },
{ "list", no_argument, 0, 'l' },
{ "gpio_test", no_argument, 0, 'g' },
{ "help", no_argument, 0, 'h' },
{ 0, 0, 0, 0 },
};
int parse_uint16(char* const s, uint16_t* const value) {
char* s_end = s;
const long long_value = strtol(s, &s_end, 10);
if( (s != s_end) && (*s_end == 0) ) {
*value = (uint16_t)long_value;
return HACKRF_SUCCESS;
} else {
return HACKRF_ERROR_INVALID_PARAM;
}
}
int parse_uint32(char* const s, uint32_t* const value) {
char* s_end = s;
const long long_value = strtol(s, &s_end, 10);
if( (s != s_end) && (*s_end == 0) ) {
*value = (uint32_t)long_value;
return HACKRF_SUCCESS;
} else {
return HACKRF_ERROR_INVALID_PARAM;
}
}
int parse_port(char* str, uint8_t* port) {
uint16_t tmp_port;
int result;
if(str[0] == 'A' || str[0] == 'B') {
// The port was specified as a side and number eg. A1 or B3
result = parse_uint16(str+1, &tmp_port);
if (result != HACKRF_SUCCESS)
return result;
if(tmp_port >= 5 || tmp_port <= 0) {
fprintf(stderr, "invalid port: %s\n", str);
return HACKRF_ERROR_INVALID_PARAM;
}
// Value was a valid port between 0-4
if(str[0] == 'A') {
// A1=0, A2=1, A3=2, A4=3
tmp_port -= 1;
} else {
// If B was specfied just add 4-1 ports
// B1=4, B2=5, B3=6, B4=7
tmp_port += 3;
}
} else {
result = parse_uint16(str, &tmp_port);
if (result != HACKRF_SUCCESS)
return result;
}
*port = tmp_port & 0xFF;
// printf("Port: %d\n", *port);
return HACKRF_SUCCESS;
}
int parse_range(char* s, hackrf_operacake_freq_range* range) {
char port[16];
float min;
float max;
int result;
// Read frequency as a float here to support scientific notation (e.g: 1e6)
if (sscanf(s, "%15[^:]:%f:%f", port, &min, &max) == 3) {
result = parse_port(port, &(range->port));
if (result != HACKRF_SUCCESS)
return result;
range->freq_min = min;
range->freq_max = max;
return HACKRF_SUCCESS;
}
return HACKRF_ERROR_INVALID_PARAM;
}
int parse_dwell(char* s, hackrf_operacake_dwell_time* dwell_time) {
int result;
char port[16];
float dwell;
// Read dwell as a float here to support scientific notation (e.g: 1e6)
if (sscanf(s, "%15[^:]:%f", port, &dwell) == 2) {
result = parse_port(port, &dwell_time->port);
if (result != HACKRF_SUCCESS)
return result;
if (dwell == 0) {
fprintf(stderr, "dwell time cannot be 0\n");
return HACKRF_ERROR_INVALID_PARAM;
}
dwell_time->dwell = (uint32_t)dwell;
return HACKRF_SUCCESS;
} else if (sscanf(s, "%15[^:]", port) == 1) {
result = parse_port(port, &dwell_time->port);
if (result != HACKRF_SUCCESS)
return result;
// This will be replaced with the default dwell time later.
dwell_time->dwell = 0;
return HACKRF_SUCCESS;
}
return HACKRF_ERROR_INVALID_PARAM;
}
int main(int argc, char** argv) {
int opt;
const char* serial_number = NULL;
uint8_t operacake_address = 0;
bool set_mode = false;
uint8_t mode;
uint8_t port_a = INVALID_PORT;
uint8_t port_b = INVALID_PORT;
bool set_ports = false;
bool list = false;
bool gpio_test = false;
uint8_t operacakes[8];
uint8_t operacake_count = 0;
int i = 0;
hackrf_device* device = NULL;
int option_index = 0;
hackrf_operacake_freq_range ranges[HACKRF_OPERACAKE_MAX_FREQ_RANGES];
hackrf_operacake_dwell_time dwell_times[HACKRF_OPERACAKE_MAX_DWELL_TIMES];
uint8_t range_idx = 0;
uint8_t dwell_idx = 0;
uint32_t default_dwell = 0;
int result = hackrf_init();
if( result ) {
printf("hackrf_init() failed: %s (%d)\n", hackrf_error_name(result), result);
return -1;
}
while( (opt = getopt_long(argc, argv, "d:o:a:m:b:lf:t:w:hg?", long_options, &option_index)) != EOF ) {
switch( opt ) {
case 'd':
serial_number = optarg;
break;
case 'o':
operacake_address = atoi(optarg);
break;
case 'm':
if (strcmp(optarg, "manual") == 0) {
mode = OPERACAKE_MODE_MANUAL;
set_mode = true;
} else if (strcmp(optarg, "frequency") == 0) {
mode = OPERACAKE_MODE_FREQUENCY;
set_mode = true;
} else if (strcmp(optarg, "time") == 0) {
mode = OPERACAKE_MODE_TIME;
set_mode = true;
} else {
fprintf(stderr,
"argument error: mode must be one of [manual, frequency, time].\n");
usage();
return EXIT_FAILURE;
}
break;
case 'f':
if (HACKRF_OPERACAKE_MAX_FREQ_RANGES == range_idx) {
fprintf(stderr,
"argument error: specify a maximum of %u frequency ranges.\n",
HACKRF_OPERACAKE_MAX_FREQ_RANGES);
usage();
return EXIT_FAILURE;
}
result = parse_range(optarg, &ranges[range_idx]);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "failed to parse range\n");
return EXIT_FAILURE;
}
if(ranges[range_idx].freq_min >= ranges[range_idx].freq_max) {
fprintf(stderr,
"argument error: freq_max must be greater than freq_min.\n");
usage();
return EXIT_FAILURE;
}
if(FREQ_MAX_MHZ < ranges[range_idx].freq_max) {
fprintf(stderr,
"argument error: freq_max may not be higher than %u.\n",
FREQ_MAX_MHZ);
usage();
return EXIT_FAILURE;
}
range_idx++;
break;
case 't':
if(HACKRF_OPERACAKE_MAX_DWELL_TIMES == dwell_idx) {
fprintf(stderr,
"argument error: specify a maximum of %u dwell times.\n",
HACKRF_OPERACAKE_MAX_DWELL_TIMES);
usage();
return EXIT_FAILURE;
}
result = parse_dwell(optarg, &dwell_times[dwell_idx]);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "failed to parse dwell time\n");
return EXIT_FAILURE;
}
dwell_idx++;
break;
case 'w':
default_dwell = atof(optarg);
break;
case 'a':
result = parse_port(optarg, &port_a);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "failed to parse port\n");
return EXIT_FAILURE;
}
set_ports = true;
break;
case 'b':
result = parse_port(optarg, &port_b);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "failed to parse port\n");
return EXIT_FAILURE;
}
set_ports = true;
break;
case 'l':
list = true;
break;
case 'g':
gpio_test = true;
break;
case 'h':
case '?':
usage();
return EXIT_SUCCESS;
default:
fprintf(stderr, "unknown argument '-%c %s'\n", opt, optarg);
usage();
return EXIT_FAILURE;
}
}
// Any operations that set a parameter on an Opera Cake board.
bool set_params = set_mode || set_ports || range_idx || dwell_idx;
// Error out unless exactly one option is selected.
if (list + set_params + gpio_test != 1) {
fprintf(stderr, "Specify either list, mode, or GPIO test option.\n");
usage();
return EXIT_FAILURE;
}
result = hackrf_open_by_serial(serial_number, &device);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_open() failed: %s (%d)\n",
hackrf_error_name(result), result);
return EXIT_FAILURE;
}
if (set_mode) {
result = hackrf_set_operacake_mode(device, operacake_address, mode);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_set_operacake_mode() failed: %s (%d)\n",
hackrf_error_name(result), result);
return EXIT_FAILURE;
}
}
if(list) {
result = hackrf_get_operacake_boards(device, operacakes);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_get_operacake_boards() failed: %s (%d)\n",
hackrf_error_name(result), result);
return EXIT_FAILURE;
}
printf("Opera Cakes found: ");
for(i=0; i<8; i++) {
if(operacakes[i] != HACKRF_OPERACAKE_ADDRESS_INVALID) {
printf("\n\tAddress: %d", operacakes[i]);
enum operacake_switching_mode mode;
hackrf_get_operacake_mode(device, i, &mode);
printf("\tSwitching mode: ");
if (mode == OPERACAKE_MODE_MANUAL) {
printf("manual\n");
} else if (mode == OPERACAKE_MODE_FREQUENCY) {
printf("frequency\n");
} else if (mode == OPERACAKE_MODE_TIME) {
printf("time\n");
} else {
printf("unknown\n");
}
operacake_count++;
}
}
if(!operacake_count)
printf("None");
printf("\n");
}
if(gpio_test) {
uint16_t test_result;
uint8_t reg, mask = 0x7;
result = hackrf_operacake_gpio_test(device, operacake_address, &test_result);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_operacake_gpio_test() failed: %s (%d)\n",
hackrf_error_name(result), result);
return EXIT_FAILURE;
}
if(test_result == GPIO_TEST_DISABLED) {
fprintf(stderr, "GPIO mode diabled.\n");
fprintf(stderr, "Remove additional addon boards and retry.\n");
}else if(test_result) {
fprintf(stderr, "GPIO test failed\n");
fprintf(stderr, "Pin\tHigh\tShorts\tLow\n");
reg = test_result & mask;
fprintf(stderr, "u2ctrl1\t%d\t%d\t%d\n",
(reg>>2) & 1,
(reg>>1) & 1,
reg & 1);
test_result >>= 3;
reg = test_result & mask;
fprintf(stderr, "u2ctrl0\t%d\t%d\t%d\n",
(reg>>2) & 1,
(reg>>1) & 1,
reg & 1);
test_result >>= 3;
reg = test_result & mask;
fprintf(stderr, "u3ctrl1\t%d\t%d\t%d\n",
(reg>>2) & 1,
(reg>>1) & 1,
reg & 1);
test_result >>= 3;
reg = test_result & mask;
fprintf(stderr, "u3ctrl0\t%d\t%d\t%d\n",
(reg>>2) & 1,
(reg>>1) & 1,
reg & 1);
test_result >>= 3;
reg = test_result & mask;
fprintf(stderr, "u1ctrl \t%d\t%d\t%d\n",
(reg>>2) & 1,
(reg>>1) & 1,
reg & 1);
} else {
fprintf(stderr, "GPIO test passed\n");
}
}
if(set_ports) {
// Set other port to "don't care" if not set
if(port_a == INVALID_PORT) {
if(port_b >= 4) {
port_a = 0;
} else {
port_a = 4;
}
}
if(port_b == INVALID_PORT) {
if(port_a >= 4) {
port_b = 0;
} else {
port_b = 4;
}
}
if(((port_a<=3) && (port_b<=3)) || ((port_a>=4) && (port_b>=4))) {
fprintf(stderr, "Port A and B cannot be connected to the same side\n");
return EXIT_FAILURE;
}
result = hackrf_set_operacake_ports(device, operacake_address, port_a, port_b);
if( result ) {
printf("hackrf_set_operacake_ports() failed: %s (%d)\n", hackrf_error_name(result), result);
return EXIT_FAILURE;
}
}
if (range_idx) {
result = hackrf_set_operacake_freq_ranges(device, ranges, range_idx);
if (result) {
printf("hackrf_set_operacake_freq_ranges() failed: %s (%d)\n", hackrf_error_name(result), result);
return -1;
}
}
if(dwell_idx) {
for (i = 0; i < dwell_idx; i++) {
if (dwell_times[i].dwell == 0) {
if (default_dwell == 0) {
fprintf(stderr, "port '%u' set to use default dwell time, but default dwell time is not set. Use -w argument to set default dwell time.\n",
dwell_times[i].port);
return EXIT_FAILURE;
}
dwell_times[i].dwell = default_dwell;
}
}
result = hackrf_set_operacake_dwell_times(device, dwell_times, dwell_idx);
if( result ) {
printf("hackrf_set_operacake_dwell_times() failed: %s (%d)\n", hackrf_error_name(result), result);
return -1;
}
}
result = hackrf_close(device);
if( result ) {
printf("hackrf_close() failed: %s (%d)\n", hackrf_error_name(result), result);
return -1;
}
hackrf_exit();
return 0;
}

View File

@ -0,0 +1,453 @@
/*
* Copyright 2012 Jared Boone <jared@sharebrained.com>
* Copyright 2013 Benjamin Vernoux <titanmkd@gmail.com>
* Copyright 2013 Michael Ossmann <mike@ossmann.com>
*
* This file is part of HackRF.
*
* 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, 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; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include <hackrf.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <sys/types.h>
#ifndef bool
typedef int bool;
#define true 1
#define false 0
#endif
#ifdef _MSC_VER
#ifdef _WIN64
typedef int64_t ssize_t;
#else
typedef int32_t ssize_t;
#endif
#endif
/* 8 Mbit flash */
#define MAX_LENGTH 0x100000
static struct option long_options[] = {
{ "address", required_argument, 0, 'a' },
{ "length", required_argument, 0, 'l' },
{ "read", required_argument, 0, 'r' },
{ "write", required_argument, 0, 'w' },
{ "compatibility", no_argument, 0, 'c' },
{ "device", required_argument, 0, 'd' },
{ "reset", no_argument, 0, 'R' },
{ "status", no_argument, 0, 's' },
{ "clear", no_argument, 0, 'c' },
{ "verbose", no_argument, 0, 'v' },
{ "help", no_argument, 0, 'h' },
{ 0, 0, 0, 0 },
};
/* Check for USB product string descriptor text in firmware file
* It should match the appropriate one for the BOARD_ID
* If you're already running firmware that reports the wrong ID
* I can't help you, but you can use the -i optionto ignore (or DFU)
*/
int compatibility_check(uint8_t* data, int length, hackrf_device* device)
{
int str_len, i,j;
bool match = false;
uint8_t board_id;
char* dev_str;
hackrf_board_id_read(device, &board_id);
switch(board_id)
{
case BOARD_ID_JAWBREAKER:
dev_str = "HackRF Jawbreaker";
str_len = 17;
break;
case BOARD_ID_HACKRF_ONE:
dev_str = "HackRF One";
str_len = 10;
break;
case BOARD_ID_RAD1O:
dev_str = "rad1o";
str_len = 5;
break;
default:
printf("Unknown Board ID");
return 1;
}
// Search for dev_str in uint8_t array of bytes that we're flashing
for(i=0; i<length-str_len; i++){
if(data[i] == dev_str[0]) {
match = true;
for(j=1; j<str_len; j++) {
if((data[i+j*2] != dev_str[j]) ||
(data[1+i+j*2] != 0x00)) {
match = false;
break;
}
}
if(match)
return 0;
}
}
return 1;
}
int parse_u32(char* s, uint32_t* const value)
{
char* s_end;
uint_fast8_t base = 10;
uint32_t u32_value;
if (strlen(s) > 2) {
if (s[0] == '0') {
if ((s[1] == 'x') || (s[1] == 'X')) {
base = 16;
s += 2;
} else if ((s[1] == 'b') || (s[1] == 'B')) {
base = 2;
s += 2;
}
}
}
s_end = s;
u32_value = strtoul(s, &s_end, base);
if ((s != s_end) && (*s_end == 0)) {
*value = u32_value;
return HACKRF_SUCCESS;
} else {
return HACKRF_ERROR_INVALID_PARAM;
}
}
static void usage()
{
printf("Usage:\n");
printf("\t-h, --help: this help\n");
printf("\t-a, --address <n>: starting address (default: 0)\n");
printf("\t-l, --length <n>: number of bytes to read (default: %d)\n", MAX_LENGTH);
printf("\t-r, --read <filename>: Read data into file.\n");
printf("\t-w, --write <filename>: Write data from file.\n");
printf("\t-i, --no-check: Skip check for firmware compatibility with target device.\n");
printf("\t-d, --device <serialnumber>: Serial number of device, if multiple devices\n");
printf("\t-s, --status: Read SPI flash status registers before other operations.\n");
printf("\t-c, --clear: Clear SPI flash status registers before other operations.\n");
printf("\t-R, --reset: Reset HackRF after other operations.\n");
printf("\t-v, --verbose: Verbose output.\n");
}
int main(int argc, char** argv)
{
int opt;
uint8_t status[2];
uint32_t address = 0;
uint32_t length = MAX_LENGTH;
uint32_t tmp_length;
uint16_t xfer_len = 0;
const char* path = NULL;
const char* serial_number = NULL;
hackrf_device* device = NULL;
int result = HACKRF_SUCCESS;
int option_index = 0;
static uint8_t data[MAX_LENGTH];
uint8_t* pdata = &data[0];
FILE* infile = NULL;
bool read = false;
bool write = false;
bool ignore_compat_check = false;
bool verbose = false;
bool reset = false;
bool read_status = false;
bool clear_status = false;
uint16_t usb_api;
while ((opt = getopt_long(argc, argv, "a:l:r:w:id:scvRh?", long_options,
&option_index)) != EOF) {
switch (opt) {
case 'a':
result = parse_u32(optarg, &address);
break;
case 'l':
result = parse_u32(optarg, &length);
break;
case 'r':
read = true;
path = optarg;
break;
case 'w':
write = true;
path = optarg;
break;
case 'i':
ignore_compat_check = true;
break;
case 'd':
serial_number = optarg;
break;
case 's':
read_status = true;
break;
case 'c':
clear_status = true;
break;
case 'v':
verbose = true;
break;
case 'R':
reset = true;
break;
case 'h':
case '?':
usage();
return EXIT_SUCCESS;
default:
fprintf(stderr, "unknown argument '-%c %s'\n", opt, optarg);
usage();
return EXIT_FAILURE;
}
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "argument error: %s (%d)\n",
hackrf_error_name(result), result);
usage();
return EXIT_FAILURE;
}
}
if(write && read) {
fprintf(stderr, "Read and write options are mutually exclusive.\n");
usage();
return EXIT_FAILURE;
}
if(!(write || read || reset || read_status || clear_status)) {
fprintf(stderr, "Specify either read, write, or reset option.\n");
usage();
return EXIT_FAILURE;
}
if( write )
{
infile = fopen(path, "rb");
if(infile == NULL)
{
printf("Error opening file %s\n", path);
return EXIT_FAILURE;
}
/* Get size of the file */
fseek(infile, 0, SEEK_END); /* Not really portable but work on major OS Linux/Win32 */
length = ftell(infile);
/* Move to start */
rewind(infile);
printf("File size %d bytes.\n", length);
}
if (length == 0) {
fprintf(stderr, "Requested transfer of zero bytes.\n");
if(infile != NULL)
fclose(infile);
usage();
return EXIT_FAILURE;
}
if ((length > MAX_LENGTH) || (address > MAX_LENGTH)
|| ((address + length) > MAX_LENGTH)) {
fprintf(stderr, "Request exceeds size of flash memory.\n");
if(infile != NULL)
fclose(infile);
usage();
return EXIT_FAILURE;
}
if (read) {
infile = fopen(path, "wb");
if(infile == NULL)
{
printf("Error to open file %s\n", path);
return EXIT_FAILURE;
}
}
result = hackrf_init();
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_init() failed: %s (%d)\n",
hackrf_error_name(result), result);
return EXIT_FAILURE;
}
result = hackrf_open_by_serial(serial_number, &device);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_open() failed: %s (%d)\n",
hackrf_error_name(result), result);
return EXIT_FAILURE;
}
if(read_status) {
result = hackrf_spiflash_status(device, status);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_spiflash_status() failed: %s (%d)\n",
hackrf_error_name(result), result);
return EXIT_FAILURE;
}
if(!verbose) {
printf("Status: 0x%02x %02x\n", status[0], status[1]);
} else {
printf("SRP0\t%x\nSEC\t%x\nTB\t%x\nBP\t%x\nWEL\t%x\nBusy\t%x\n",
(status[0] & 0x80) >> 7,
(status[0] & 0x40) >> 6,
(status[0] & 0x20) >> 5,
(status[0] & 0x1C) >> 2,
(status[0] & 0x02) >> 1,
status[0] & 0x01);
printf("SUS\t%x\nCMP\t%x\nLB\t%x\nRes\t%x\nQE\t%x\nSRP1\t%x\n",
(status[1] & 0x80) >> 7,
(status[1] & 0x40) >> 6,
(status[1] & 0x38) >> 3,
(status[1] & 0x04) >> 2,
(status[1] & 0x02) >> 1,
status[1] & 0x01);
}
}
if(clear_status) {
result = hackrf_spiflash_clear_status(device);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_spiflash_clear_status() failed: %s (%d)\n",
hackrf_error_name(result), result);
return EXIT_FAILURE;
}
}
if(read) {
ssize_t bytes_written;
tmp_length = length;
while (tmp_length)
{
xfer_len = (tmp_length > 256) ? 256 : tmp_length;
if( verbose ) printf("Reading %d bytes from 0x%06x.\n", xfer_len, address);
result = hackrf_spiflash_read(device, address, xfer_len, pdata);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_spiflash_read() failed: %s (%d)\n",
hackrf_error_name(result), result);
fclose(infile);
infile = NULL;
return EXIT_FAILURE;
}
address += xfer_len;
pdata += xfer_len;
tmp_length -= xfer_len;
}
bytes_written = fwrite(data, 1, length, infile);
if (bytes_written != length) {
fprintf(stderr, "Failed write to file (wrote %d bytes).\n",
(int)bytes_written);
fclose(infile);
infile = NULL;
return EXIT_FAILURE;
}
}
if(write) {
ssize_t bytes_read = fread(data, 1, length, infile);
if (bytes_read != length) {
fprintf(stderr, "Failed read file (read %d bytes).\n",
(int)bytes_read);
fclose(infile);
infile = NULL;
return EXIT_FAILURE;
}
if(!ignore_compat_check) {
printf("Checking target device compatibility\n");
result = compatibility_check(data, length, device);
if(result) {
printf("Compatibility test failed.\n");
fclose(infile);
infile = NULL;
return EXIT_FAILURE;
}
}
printf("Erasing SPI flash.\n");
result = hackrf_spiflash_erase(device);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_spiflash_erase() failed: %s (%d)\n",
hackrf_error_name(result), result);
fclose(infile);
infile = NULL;
return EXIT_FAILURE;
}
if( !verbose ) printf("Writing %d bytes at 0x%06x.\n", length, address);
while (length) {
xfer_len = (length > 256) ? 256 : length;
if( verbose ) printf("Writing %d bytes at 0x%06x.\n", xfer_len, address);
result = hackrf_spiflash_write(device, address, xfer_len, pdata);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_spiflash_write() failed: %s (%d)\n",
hackrf_error_name(result), result);
fclose(infile);
infile = NULL;
return EXIT_FAILURE;
}
address += xfer_len;
pdata += xfer_len;
length -= xfer_len;
}
}
if (infile != NULL) {
fclose(infile);
infile = NULL;
}
if(reset) {
result = hackrf_reset(device);
if (result != HACKRF_SUCCESS) {
if (result == HACKRF_ERROR_USB_API_VERSION) {
hackrf_usb_api_version_read(device, &usb_api);
fprintf(stderr, "Reset is not supported by firmware API %x.%02x\n",
(usb_api>>8)&0xFF, usb_api&0xFF);
} else {
fprintf(stderr, "hackrf_reset() failed: %s (%d)\n",
hackrf_error_name(result), result);
}
return EXIT_FAILURE;
}
}
result = hackrf_close(device);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_close() failed: %s (%d)\n",
hackrf_error_name(result), result);
return EXIT_FAILURE;
}
hackrf_exit();
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,770 @@
/*
* Copyright 2016 Dominic Spill <dominicgs@gmail.com>
* Copyright 2016 Mike Walters <mike@flomp.net>
* Copyright 2017 Michael Ossmann <mike@ossmann.com>
*
* This file is part of HackRF.
*
* 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, 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; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include <hackrf.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <fftw3.h>
#include <inttypes.h>
#define _FILE_OFFSET_BITS 64
#ifndef bool
typedef int bool;
#define true 1
#define false 0
#endif
#ifdef _WIN32
#define _USE_MATH_DEFINES
#include <windows.h>
#ifdef _MSC_VER
#ifdef _WIN64
typedef int64_t ssize_t;
#else
typedef int32_t ssize_t;
#endif
#define strtoull _strtoui64
#define snprintf _snprintf
int gettimeofday(struct timeval *tv, void* ignored) {
FILETIME ft;
unsigned __int64 tmp = 0;
if (NULL != tv) {
GetSystemTimeAsFileTime(&ft);
tmp |= ft.dwHighDateTime;
tmp <<= 32;
tmp |= ft.dwLowDateTime;
tmp /= 10;
tmp -= 11644473600000000Ui64;
tv->tv_sec = (long)(tmp / 1000000UL);
tv->tv_usec = (long)(tmp % 1000000UL);
}
return 0;
}
#endif
#endif
#if defined(__GNUC__)
#include <unistd.h>
#include <sys/time.h>
#endif
#include <signal.h>
#include <math.h>
#define FD_BUFFER_SIZE (8*1024)
#define FREQ_ONE_MHZ (1000000ull)
#define FREQ_MIN_MHZ (0) /* 0 MHz */
#define FREQ_MAX_MHZ (7250) /* 7250 MHz */
#define DEFAULT_SAMPLE_RATE_HZ (20000000) /* 20MHz default sample rate */
#define DEFAULT_BASEBAND_FILTER_BANDWIDTH (15000000) /* 15MHz default */
#define TUNE_STEP (DEFAULT_SAMPLE_RATE_HZ / FREQ_ONE_MHZ)
#define OFFSET 7500000
#define BLOCKS_PER_TRANSFER 16
#define THROWAWAY_BLOCKS 2
#if defined _WIN32
#define m_sleep(a) Sleep( (a) )
#else
#define m_sleep(a) usleep((a*1000))
#endif
uint32_t num_sweeps = 0;
int num_ranges = 0;
uint16_t frequencies[MAX_SWEEP_RANGES*2];
int step_count;
static float TimevalDiff(const struct timeval *a, const struct timeval *b) {
return (a->tv_sec - b->tv_sec) + 1e-6f * (a->tv_usec - b->tv_usec);
}
int parse_u32(char* s, uint32_t* const value) {
uint_fast8_t base = 10;
char* s_end;
uint64_t ulong_value;
if( strlen(s) > 2 ) {
if( s[0] == '0' ) {
if( (s[1] == 'x') || (s[1] == 'X') ) {
base = 16;
s += 2;
} else if( (s[1] == 'b') || (s[1] == 'B') ) {
base = 2;
s += 2;
}
}
}
s_end = s;
ulong_value = strtoul(s, &s_end, base);
if( (s != s_end) && (*s_end == 0) ) {
*value = (uint32_t)ulong_value;
return HACKRF_SUCCESS;
} else {
return HACKRF_ERROR_INVALID_PARAM;
}
}
int parse_u32_range(char* s, uint32_t* const value_min, uint32_t* const value_max) {
int result;
char *sep = strchr(s, ':');
if (!sep)
return HACKRF_ERROR_INVALID_PARAM;
*sep = 0;
result = parse_u32(s, value_min);
if (result != HACKRF_SUCCESS)
return result;
result = parse_u32(sep + 1, value_max);
if (result != HACKRF_SUCCESS)
return result;
return HACKRF_SUCCESS;
}
volatile bool do_exit = false;
FILE* outfile = NULL;
volatile uint32_t byte_count = 0;
volatile uint64_t sweep_count = 0;
struct timeval time_start;
struct timeval t_start;
bool amp = false;
uint32_t amp_enable;
bool antenna = false;
uint32_t antenna_enable;
bool binary_output = false;
bool ifft_output = false;
bool one_shot = false;
bool finite_mode = false;
volatile bool sweep_started = false;
int fftSize = 20;
double fft_bin_width;
fftwf_complex *fftwIn = NULL;
fftwf_complex *fftwOut = NULL;
fftwf_plan fftwPlan = NULL;
fftwf_complex *ifftwIn = NULL;
fftwf_complex *ifftwOut = NULL;
fftwf_plan ifftwPlan = NULL;
uint32_t ifft_idx = 0;
float* pwr;
float* window;
float logPower(fftwf_complex in, float scale)
{
float re = in[0] * scale;
float im = in[1] * scale;
float magsq = re * re + im * im;
return (float) (log2(magsq) * 10.0f / log2(10.0f));
}
int rx_callback(hackrf_transfer* transfer) {
int8_t* buf;
uint8_t* ubuf;
uint64_t frequency; /* in Hz */
uint64_t band_edge;
uint32_t record_length;
int i, j, ifft_bins;
struct tm *fft_time;
char time_str[50];
struct timeval usb_transfer_time;
if(NULL == outfile) {
return -1;
}
if(do_exit) {
return 0;
}
gettimeofday(&usb_transfer_time, NULL);
byte_count += transfer->valid_length;
buf = (int8_t*) transfer->buffer;
ifft_bins = fftSize * step_count;
for(j=0; j<BLOCKS_PER_TRANSFER; j++) {
ubuf = (uint8_t*) buf;
if(ubuf[0] == 0x7F && ubuf[1] == 0x7F) {
frequency = ((uint64_t)(ubuf[9]) << 56) | ((uint64_t)(ubuf[8]) << 48) | ((uint64_t)(ubuf[7]) << 40)
| ((uint64_t)(ubuf[6]) << 32) | ((uint64_t)(ubuf[5]) << 24) | ((uint64_t)(ubuf[4]) << 16)
| ((uint64_t)(ubuf[3]) << 8) | ubuf[2];
} else {
buf += BYTES_PER_BLOCK;
continue;
}
if (frequency == (uint64_t)(FREQ_ONE_MHZ*frequencies[0])) {
if(sweep_started) {
if(ifft_output) {
fftwf_execute(ifftwPlan);
for(i=0; i < ifft_bins; i++) {
ifftwOut[i][0] *= 1.0f / ifft_bins;
ifftwOut[i][1] *= 1.0f / ifft_bins;
fwrite(&ifftwOut[i][0], sizeof(float), 1, outfile);
fwrite(&ifftwOut[i][1], sizeof(float), 1, outfile);
}
}
sweep_count++;
if(one_shot) {
do_exit = true;
}
else if(finite_mode && sweep_count == num_sweeps) {
do_exit = true;
}
}
sweep_started = true;
}
if(do_exit) {
return 0;
}
if(!sweep_started) {
buf += BYTES_PER_BLOCK;
continue;
}
if((FREQ_MAX_MHZ * FREQ_ONE_MHZ) < frequency) {
buf += BYTES_PER_BLOCK;
continue;
}
/* copy to fftwIn as floats */
buf += BYTES_PER_BLOCK - (fftSize * 2);
for(i=0; i < fftSize; i++) {
fftwIn[i][0] = buf[i*2] * window[i] * 1.0f / 128.0f;
fftwIn[i][1] = buf[i*2+1] * window[i] * 1.0f / 128.0f;
}
buf += fftSize * 2;
fftwf_execute(fftwPlan);
for (i=0; i < fftSize; i++) {
pwr[i] = logPower(fftwOut[i], 1.0f / fftSize);
}
if(binary_output) {
record_length = 2 * sizeof(band_edge)
+ (fftSize/4) * sizeof(float);
fwrite(&record_length, sizeof(record_length), 1, outfile);
band_edge = frequency;
fwrite(&band_edge, sizeof(band_edge), 1, outfile);
band_edge = frequency + DEFAULT_SAMPLE_RATE_HZ / 4;
fwrite(&band_edge, sizeof(band_edge), 1, outfile);
fwrite(&pwr[1+(fftSize*5)/8], sizeof(float), fftSize/4, outfile);
fwrite(&record_length, sizeof(record_length), 1, outfile);
band_edge = frequency + DEFAULT_SAMPLE_RATE_HZ / 2;
fwrite(&band_edge, sizeof(band_edge), 1, outfile);
band_edge = frequency + (DEFAULT_SAMPLE_RATE_HZ * 3) / 4;
fwrite(&band_edge, sizeof(band_edge), 1, outfile);
fwrite(&pwr[1+fftSize/8], sizeof(float), fftSize/4, outfile);
} else if(ifft_output) {
ifft_idx = (uint32_t) round((frequency - (uint64_t)(FREQ_ONE_MHZ*frequencies[0]))
/ fft_bin_width);
ifft_idx = (ifft_idx + ifft_bins/2) % ifft_bins;
for(i = 0; (fftSize / 4) > i; i++) {
ifftwIn[ifft_idx + i][0] = fftwOut[i + 1 + (fftSize*5)/8][0];
ifftwIn[ifft_idx + i][1] = fftwOut[i + 1 + (fftSize*5)/8][1];
}
ifft_idx += fftSize / 2;
ifft_idx %= ifft_bins;
for(i = 0; (fftSize / 4) > i; i++) {
ifftwIn[ifft_idx + i][0] = fftwOut[i + 1 + (fftSize/8)][0];
ifftwIn[ifft_idx + i][1] = fftwOut[i + 1 + (fftSize/8)][1];
}
} else {
time_t time_stamp_seconds = usb_transfer_time.tv_sec;
fft_time = localtime(&time_stamp_seconds);
strftime(time_str, 50, "%Y-%m-%d, %H:%M:%S", fft_time);
fprintf(outfile, "%s.%06ld, %" PRIu64 ", %" PRIu64 ", %.2f, %u",
time_str,
(long int)usb_transfer_time.tv_usec,
(uint64_t)(frequency),
(uint64_t)(frequency+DEFAULT_SAMPLE_RATE_HZ/4),
fft_bin_width,
fftSize);
for(i = 0; (fftSize / 4) > i; i++) {
fprintf(outfile, ", %.2f", pwr[i + 1 + (fftSize*5)/8]);
}
fprintf(outfile, "\n");
fprintf(outfile, "%s.%06ld, %" PRIu64 ", %" PRIu64 ", %.2f, %u",
time_str,
(long int)usb_transfer_time.tv_usec,
(uint64_t)(frequency+(DEFAULT_SAMPLE_RATE_HZ/2)),
(uint64_t)(frequency+((DEFAULT_SAMPLE_RATE_HZ*3)/4)),
fft_bin_width,
fftSize);
for(i = 0; (fftSize / 4) > i; i++) {
fprintf(outfile, ", %.2f", pwr[i + 1 + (fftSize/8)]);
}
fprintf(outfile, "\n");
}
}
return 0;
}
static void usage() {
fprintf(stderr, "Usage:\n");
fprintf(stderr, "\t[-h] # this help\n");
fprintf(stderr, "\t[-d serial_number] # Serial number of desired HackRF\n");
fprintf(stderr, "\t[-a amp_enable] # RX RF amplifier 1=Enable, 0=Disable\n");
fprintf(stderr, "\t[-f freq_min:freq_max] # minimum and maximum frequencies in MHz\n");
fprintf(stderr, "\t[-p antenna_enable] # Antenna port power, 1=Enable, 0=Disable\n");
fprintf(stderr, "\t[-l gain_db] # RX LNA (IF) gain, 0-40dB, 8dB steps\n");
fprintf(stderr, "\t[-g gain_db] # RX VGA (baseband) gain, 0-62dB, 2dB steps\n");
fprintf(stderr, "\t[-w bin_width] # FFT bin width (frequency resolution) in Hz, 2445-5000000\n");
fprintf(stderr, "\t[-1] # one shot mode\n");
fprintf(stderr, "\t[-N num_sweeps] # Number of sweeps to perform\n");
fprintf(stderr, "\t[-B] # binary output\n");
fprintf(stderr, "\t[-I] # binary inverse FFT output\n");
fprintf(stderr, "\t-r filename # output file\n");
fprintf(stderr, "\n");
fprintf(stderr, "Output fields:\n");
fprintf(stderr, "\tdate, time, hz_low, hz_high, hz_bin_width, num_samples, dB, dB, . . .\n");
}
static hackrf_device* device = NULL;
#ifdef _MSC_VER
BOOL WINAPI
sighandler(int signum) {
if (CTRL_C_EVENT == signum) {
fprintf(stderr, "Caught signal %d\n", signum);
do_exit = true;
return TRUE;
}
return FALSE;
}
#else
void sigint_callback_handler(int signum) {
fprintf(stderr, "Caught signal %d\n", signum);
do_exit = true;
}
#endif
int main(int argc, char** argv) {
int opt, i, result = 0;
const char* path = NULL;
const char* serial_number = NULL;
int exit_code = EXIT_SUCCESS;
struct timeval time_now;
struct timeval time_prev;
float time_diff;
float sweep_rate = 0;
unsigned int lna_gain=16, vga_gain=20;
uint32_t freq_min = 0;
uint32_t freq_max = 6000;
uint32_t requested_fft_bin_width;
while( (opt = getopt(argc, argv, "a:f:p:l:g:d:n:N:w:1BIr:h?")) != EOF ) {
result = HACKRF_SUCCESS;
switch( opt )
{
case 'd':
serial_number = optarg;
break;
case 'a':
amp = true;
result = parse_u32(optarg, &amp_enable);
break;
case 'f':
result = parse_u32_range(optarg, &freq_min, &freq_max);
if(freq_min >= freq_max) {
fprintf(stderr,
"argument error: freq_max must be greater than freq_min.\n");
usage();
return EXIT_FAILURE;
}
if(FREQ_MAX_MHZ <freq_max) {
fprintf(stderr,
"argument error: freq_max may not be higher than %u.\n",
FREQ_MAX_MHZ);
usage();
return EXIT_FAILURE;
}
if(MAX_SWEEP_RANGES <= num_ranges) {
fprintf(stderr,
"argument error: specify a maximum of %u frequency ranges.\n",
MAX_SWEEP_RANGES);
usage();
return EXIT_FAILURE;
}
frequencies[2*num_ranges] = (uint16_t)freq_min;
frequencies[2*num_ranges+1] = (uint16_t)freq_max;
num_ranges++;
break;
case 'p':
antenna = true;
result = parse_u32(optarg, &antenna_enable);
break;
case 'l':
result = parse_u32(optarg, &lna_gain);
break;
case 'g':
result = parse_u32(optarg, &vga_gain);
break;
case 'N':
finite_mode = true;
result = parse_u32(optarg, &num_sweeps);
break;
case 'w':
result = parse_u32(optarg, &requested_fft_bin_width);
fftSize = DEFAULT_SAMPLE_RATE_HZ / requested_fft_bin_width;
break;
case '1':
one_shot = true;
break;
case 'B':
binary_output = true;
break;
case 'I':
ifft_output = true;
break;
case 'r':
path = optarg;
break;
case 'h':
case '?':
usage();
return EXIT_SUCCESS;
default:
fprintf(stderr, "unknown argument '-%c %s'\n", opt, optarg);
usage();
return EXIT_FAILURE;
}
if( result != HACKRF_SUCCESS ) {
fprintf(stderr, "argument error: '-%c %s' %s (%d)\n", opt, optarg, hackrf_error_name(result), result);
usage();
return EXIT_FAILURE;
}
}
if (lna_gain % 8)
fprintf(stderr, "warning: lna_gain (-l) must be a multiple of 8\n");
if (vga_gain % 2)
fprintf(stderr, "warning: vga_gain (-g) must be a multiple of 2\n");
if( amp ) {
if( amp_enable > 1 ) {
fprintf(stderr, "argument error: amp_enable shall be 0 or 1.\n");
usage();
return EXIT_FAILURE;
}
}
if (antenna) {
if (antenna_enable > 1) {
fprintf(stderr, "argument error: antenna_enable shall be 0 or 1.\n");
usage();
return EXIT_FAILURE;
}
}
if (0 == num_ranges) {
frequencies[0] = (uint16_t)freq_min;
frequencies[1] = (uint16_t)freq_max;
num_ranges++;
}
if(binary_output && ifft_output) {
fprintf(stderr, "argument error: binary output (-B) and IFFT output (-I) are mutually exclusive.\n");
return EXIT_FAILURE;
}
if(ifft_output && (1 < num_ranges)) {
fprintf(stderr, "argument error: only one frequency range is supported in IFFT output (-I) mode.\n");
return EXIT_FAILURE;
}
/*
* The FFT bin width must be no more than a quarter of the sample rate
* for interleaved mode. With our fixed sample rate of 20 Msps, that
* results in a maximum bin width of 5000000 Hz.
*/
if(4 > fftSize) {
fprintf(stderr,
"argument error: FFT bin width (-w) must be no more than 5000000\n");
return EXIT_FAILURE;
}
/*
* The maximum number of FFT bins we support is equal to the number of
* samples in a block. Each block consists of 16384 bytes minus 10
* bytes for the frequency header, leaving room for 8187 two-byte
* samples. As we pad fftSize up to the next odd multiple of four, this
* makes our maximum supported fftSize 8180. With our fixed sample
* rate of 20 Msps, that results in a minimum bin width of 2445 Hz.
*/
if(8180 < fftSize) {
fprintf(stderr,
"argument error: FFT bin width (-w) must be no less than 2445\n");
return EXIT_FAILURE;
}
/* In interleaved mode, the FFT bin selection works best if the total
* number of FFT bins is equal to an odd multiple of four.
* (e.g. 4, 12, 20, 28, 36, . . .)
*/
while((fftSize + 4) % 8) {
fftSize++;
}
fft_bin_width = (double)DEFAULT_SAMPLE_RATE_HZ / fftSize;
fftwIn = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize);
fftwOut = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize);
fftwPlan = fftwf_plan_dft_1d(fftSize, fftwIn, fftwOut, FFTW_FORWARD, FFTW_MEASURE);
pwr = (float*)fftwf_malloc(sizeof(float) * fftSize);
window = (float*)fftwf_malloc(sizeof(float) * fftSize);
for (i = 0; i < fftSize; i++) {
window[i] = (float) (0.5f * (1.0f - cos(2 * M_PI * i / (fftSize - 1))));
}
#ifdef _MSC_VER
if(binary_output) {
_setmode(_fileno(stdout), _O_BINARY);
}
#endif
result = hackrf_init();
if( result != HACKRF_SUCCESS ) {
fprintf(stderr, "hackrf_init() failed: %s (%d)\n", hackrf_error_name(result), result);
usage();
return EXIT_FAILURE;
}
result = hackrf_open_by_serial(serial_number, &device);
if( result != HACKRF_SUCCESS ) {
fprintf(stderr, "hackrf_open() failed: %s (%d)\n", hackrf_error_name(result), result);
usage();
return EXIT_FAILURE;
}
if((NULL == path) || (strcmp(path, "-") == 0)) {
outfile = stdout;
} else {
outfile = fopen(path, "wb");
}
if(NULL == outfile) {
fprintf(stderr, "Failed to open file: %s\n", path);
return EXIT_FAILURE;
}
/* Change outfile buffer to have bigger one to store or read data on/to HDD */
result = setvbuf(outfile , NULL , _IOFBF , FD_BUFFER_SIZE);
if( result != 0 ) {
fprintf(stderr, "setvbuf() failed: %d\n", result);
usage();
return EXIT_FAILURE;
}
#ifdef _MSC_VER
SetConsoleCtrlHandler( (PHANDLER_ROUTINE) sighandler, TRUE );
#else
signal(SIGINT, &sigint_callback_handler);
signal(SIGILL, &sigint_callback_handler);
signal(SIGFPE, &sigint_callback_handler);
signal(SIGSEGV, &sigint_callback_handler);
signal(SIGTERM, &sigint_callback_handler);
signal(SIGABRT, &sigint_callback_handler);
#endif
fprintf(stderr, "call hackrf_sample_rate_set(%.03f MHz)\n",
((float)DEFAULT_SAMPLE_RATE_HZ/(float)FREQ_ONE_MHZ));
result = hackrf_set_sample_rate_manual(device, DEFAULT_SAMPLE_RATE_HZ, 1);
if( result != HACKRF_SUCCESS ) {
fprintf(stderr, "hackrf_sample_rate_set() failed: %s (%d)\n",
hackrf_error_name(result), result);
usage();
return EXIT_FAILURE;
}
fprintf(stderr, "call hackrf_baseband_filter_bandwidth_set(%.03f MHz)\n",
((float)DEFAULT_BASEBAND_FILTER_BANDWIDTH/(float)FREQ_ONE_MHZ));
result = hackrf_set_baseband_filter_bandwidth(device, DEFAULT_BASEBAND_FILTER_BANDWIDTH);
if( result != HACKRF_SUCCESS ) {
fprintf(stderr, "hackrf_baseband_filter_bandwidth_set() failed: %s (%d)\n",
hackrf_error_name(result), result);
usage();
return EXIT_FAILURE;
}
result = hackrf_set_vga_gain(device, vga_gain);
result |= hackrf_set_lna_gain(device, lna_gain);
/*
* For each range, plan a whole number of tuning steps of a certain
* bandwidth. Increase high end of range if necessary to accommodate a
* whole number of steps, minimum 1.
*/
for(i = 0; i < num_ranges; i++) {
step_count = 1 + (frequencies[2*i+1] - frequencies[2*i] - 1)
/ TUNE_STEP;
frequencies[2*i+1] = (uint16_t) (frequencies[2*i] + step_count * TUNE_STEP);
fprintf(stderr, "Sweeping from %u MHz to %u MHz\n",
frequencies[2*i], frequencies[2*i+1]);
}
if(ifft_output) {
ifftwIn = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize * step_count);
ifftwOut = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize * step_count);
ifftwPlan = fftwf_plan_dft_1d(fftSize * step_count, ifftwIn, ifftwOut, FFTW_BACKWARD, FFTW_MEASURE);
}
result = hackrf_init_sweep(device, frequencies, num_ranges, BYTES_PER_BLOCK,
TUNE_STEP * FREQ_ONE_MHZ, OFFSET, INTERLEAVED);
if( result != HACKRF_SUCCESS ) {
fprintf(stderr, "hackrf_init_sweep() failed: %s (%d)\n",
hackrf_error_name(result), result);
return EXIT_FAILURE;
}
result |= hackrf_start_rx_sweep(device, rx_callback, NULL);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_start_rx_sweep() failed: %s (%d)\n", hackrf_error_name(result), result);
usage();
return EXIT_FAILURE;
}
if (amp) {
fprintf(stderr, "call hackrf_set_amp_enable(%u)\n", amp_enable);
result = hackrf_set_amp_enable(device, (uint8_t)amp_enable);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_set_amp_enable() failed: %s (%d)\n",
hackrf_error_name(result), result);
usage();
return EXIT_FAILURE;
}
}
if (antenna) {
fprintf(stderr, "call hackrf_set_antenna_enable(%u)\n", antenna_enable);
result = hackrf_set_antenna_enable(device, (uint8_t)antenna_enable);
if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_set_antenna_enable() failed: %s (%d)\n",
hackrf_error_name(result), result);
usage();
return EXIT_FAILURE;
}
}
gettimeofday(&t_start, NULL);
time_prev = t_start;
fprintf(stderr, "Stop with Ctrl-C\n");
while((hackrf_is_streaming(device) == HACKRF_TRUE) && (do_exit == false)) {
float time_difference;
m_sleep(50);
gettimeofday(&time_now, NULL);
if (TimevalDiff(&time_now, &time_prev) >= 1.0f) {
time_difference = TimevalDiff(&time_now, &t_start);
sweep_rate = (float)sweep_count / time_difference;
fprintf(stderr, "%" PRIu64 " total sweeps completed, %.2f sweeps/second\n",
sweep_count, sweep_rate);
if (byte_count == 0) {
exit_code = EXIT_FAILURE;
fprintf(stderr, "\nCouldn't transfer any data for one second.\n");
break;
}
byte_count = 0;
time_prev = time_now;
}
}
fflush(outfile);
result = hackrf_is_streaming(device);
if (do_exit) {
fprintf(stderr, "\nExiting...\n");
} else {
fprintf(stderr, "\nExiting... hackrf_is_streaming() result: %s (%d)\n",
hackrf_error_name(result), result);
}
gettimeofday(&time_now, NULL);
time_diff = TimevalDiff(&time_now, &t_start);
if((sweep_rate == 0) && (time_diff > 0))
sweep_rate = sweep_count / time_diff;
fprintf(stderr, "Total sweeps: %" PRIu64 " in %.5f seconds (%.2f sweeps/second)\n",
sweep_count, time_diff, sweep_rate);
if(device != NULL) {
result = hackrf_close(device);
if(result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_close() failed: %s (%d)\n",
hackrf_error_name(result), result);
} else {
fprintf(stderr, "hackrf_close() done\n");
}
hackrf_exit();
fprintf(stderr, "hackrf_exit() done\n");
}
fflush(outfile);
if ( ( outfile != NULL ) && ( outfile != stdout ) ) {
fclose(outfile);
outfile = NULL;
fprintf(stderr, "fclose() done\n");
}
fftwf_free(fftwIn);
fftwf_free(fftwOut);
fftwf_free(pwr);
fftwf_free(window);
fftwf_free(ifftwIn);
fftwf_free(ifftwOut);
fprintf(stderr, "exit\n");
return exit_code;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,4 @@
ATTR{idVendor}=="1d50", ATTR{idProduct}=="604b", SYMLINK+="hackrf-jawbreaker-%k", MODE="660", GROUP="plugdev"
ATTR{idVendor}=="1d50", ATTR{idProduct}=="6089", SYMLINK+="hackrf-one-%k", MODE="660", GROUP="plugdev"
ATTR{idVendor}=="1d50", ATTR{idProduct}=="cc15", SYMLINK+="rad1o-%k", MODE="660", GROUP="plugdev"
ATTR{idVendor}=="1fc9", ATTR{idProduct}=="000c", SYMLINK+="nxp-dfu-%k", MODE="660", GROUP="plugdev"

View File

@ -0,0 +1,13 @@
# HackRF Jawbreaker
ATTR{idVendor}=="1d50", ATTR{idProduct}=="604b", SYMLINK+="hackrf-jawbreaker-%k", MODE="660", GROUP="@HACKRF_GROUP@"
# HackRF One
ATTR{idVendor}=="1d50", ATTR{idProduct}=="6089", SYMLINK+="hackrf-one-%k", MODE="660", GROUP="@HACKRF_GROUP@"
# rad1o
ATTR{idVendor}=="1d50", ATTR{idProduct}=="cc15", SYMLINK+="rad1o-%k", MODE="660", GROUP="@HACKRF_GROUP@"
# NXP Semiconductors DFU mode (HackRF and rad1o)
ATTR{idVendor}=="1fc9", ATTR{idProduct}=="000c", SYMLINK+="nxp-dfu-%k", MODE="660", GROUP="@HACKRF_GROUP@"
# rad1o "full flash" mode
KERNEL=="sd?", SUBSYSTEM=="block", ENV{ID_VENDOR_ID}=="1fc9", ENV{ID_MODEL_ID}=="0042", SYMLINK+="rad1o-flash-%k", MODE="660", GROUP="@HACKRF_GROUP@"
# rad1o flash disk
KERNEL=="sd?", SUBSYSTEM=="block", ENV{ID_VENDOR_ID}=="1fc9", ENV{ID_MODEL_ID}=="0082", SYMLINK+="rad1o-msc-%k", MODE="660", GROUP="@HACKRF_GROUP@"
#

View File

@ -0,0 +1,168 @@
# Copyright 2012 Jared Boone
# Copyright 2013 Benjamin Vernoux
#
# This file is part of HackRF.
#
# 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, 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; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
# Based heavily upon the libftdi cmake setup.
cmake_minimum_required(VERSION 2.8)
project(libhackrf C)
set(MAJOR_VERSION 0)
set(MINOR_VERSION 7)
set(PACKAGE libhackrf)
set(VERSION_STRING ${MAJOR_VERSION}.${MINOR_VERSION})
set(VERSION ${VERSION_STRING})
add_definitions(-DLIBRARY_VERSION="${VERSION_STRING}")
include(${PROJECT_SOURCE_DIR}/../cmake/set_release.cmake)
add_definitions(-DLIBRARY_RELEASE="${RELEASE}")
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../cmake/modules)
if(MSVC)
set(THREADS_USE_PTHREADS_WIN32 true)
else()
add_definitions(-Wall)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu90")
INCLUDE(TestBigEndian)
TEST_BIG_ENDIAN(BIGENDIAN)
if(${BIGENDIAN})
add_definitions(-DHACKRF_BIG_ENDIAN)
endif(${BIGENDIAN})
endif()
find_package(USB1 REQUIRED)
find_package(Threads REQUIRED)
include_directories(${LIBUSB_INCLUDE_DIR} ${THREADS_PTHREADS_INCLUDE_DIR})
add_subdirectory(src)
########################################################################
# Create Pkg Config File
########################################################################
FOREACH(inc ${LIBUSB_INCLUDE_DIR})
LIST(APPEND HACKRF_PC_CFLAGS "-I${inc}")
ENDFOREACH(inc)
# use space-separation format for the pc file
STRING(REPLACE ";" " " HACKRF_PC_CFLAGS "${HACKRF_PC_CFLAGS}")
STRING(REPLACE ";" " " HACKRF_PC_LIBS "${HACKRF_PC_LIBS}")
# unset these vars to avoid hard-coded paths to cross environment
IF(CMAKE_CROSSCOMPILING)
UNSET(HACKRF_PC_CFLAGS)
UNSET(HACKRF_PC_LIBS)
ENDIF(CMAKE_CROSSCOMPILING)
set(prefix ${CMAKE_INSTALL_PREFIX})
set(exec_prefix \${prefix})
set(libdir \${exec_prefix}/lib${LIB_SUFFIX})
set(includedir \${prefix}/include)
set(libpkgdata lib${LIB_SUFFIX})
if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
set(libpkgdata "libdata")
endif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
CONFIGURE_FILE(
${CMAKE_CURRENT_SOURCE_DIR}/libhackrf.pc.in
${CMAKE_CURRENT_BINARY_DIR}/libhackrf.pc
@ONLY)
INSTALL(
FILES ${CMAKE_CURRENT_BINARY_DIR}/libhackrf.pc
DESTINATION ${libpkgdata}/pkgconfig
)
########################################################################
# Create Pkg Config File
########################################################################
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
SET(SYSTEM_IS_LINUX TRUE)
SET(UDEV_OPTION_DEFAULT ON)
else()
SET(SYSTEM_IS_LINUX FALSE)
SET(UDEV_OPTION_DEFAULT OFF)
endif()
option(INSTALL_UDEV_RULES
"Install udev rules for the HackRF"
${UDEV_OPTION_DEFAULT}
)
set(UDEV_RULES_PATH
"/etc/udev/rules.d"
CACHE STRING
"Target directory for udev rule installation. Ensure you have permissions to write to this directory."
)
if(SYSTEM_IS_LINUX)
if(INSTALL_UDEV_RULES)
if(NOT DEFINED UDEV_RULES_GROUP)
foreach(group usb plugdev)
execute_process(COMMAND "getent" group "${group}"
RESULT_VARIABLE _GETENT_RESULT
OUTPUT_QUIET
ERROR_QUIET)
if(NOT _GETENT_RESULT)
message(STATUS "Setting udev rule group to - ${group}")
set(UDEV_RULES_GROUP ${group})
break()
endif(NOT _GETENT_RESULT)
endforeach(group)
endif(NOT DEFINED UDEV_RULES_GROUP)
if(DEFINED UDEV_RULES_GROUP)
set(HACKRF_GROUP "${UDEV_RULES_GROUP}"
CACHE STRING "Group to associate HackRF devices with in udev rules")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/53-hackrf.rules.in
${CMAKE_CURRENT_BINARY_DIR}/53-hackrf.rules
@ONLY
)
message(STATUS "HackRF udev rules will be installed to '${UDEV_RULES_PATH}' upon running 'make install'")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/53-hackrf.rules
DESTINATION ${UDEV_RULES_PATH}
COMPONENT "udev_rules")
else(UDEV_RULES_GROUP)
message(STATUS "HackRF udev rules will not be installed because no suitable group was found")
message(STATUS "A group can be specified with -DUDEV_RULES_GROUP=<group>")
endif(DEFINED UDEV_RULES_GROUP)
else(INSTALL_UDEV_RULES)
message(STATUS
"HackRF udev rules will not be installed because INSTALL_UDEV_RULES=OFF"
)
endif(INSTALL_UDEV_RULES)
else(SYSTEM_IS_LINUX)
if(INSTALL_UDEV_RULES)
message(STATUS "udev rules not supported on this platform. Hide this message via -DINSTALL_UDEV_RULES=Off")
endif(INSTALL_UDEV_RULES)
endif(SYSTEM_IS_LINUX)
########################################################################
# Create uninstall target
########################################################################
if(NOT HackRF_SOURCE_DIR)
configure_file(
${PROJECT_SOURCE_DIR}/../cmake/cmake_uninstall.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
@ONLY)
add_custom_target(uninstall
${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
)
endif()

View File

@ -0,0 +1,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: HackRF Library
Description: C Utility Library
Version: @VERSION@
Cflags: -I${includedir} -I${includedir}/libhackrf @HACKRF_PC_CFLAGS@
Libs: -L${libdir} -lhackrf
Libs.private: @HACKRF_PC_LIBS@

View File

@ -0,0 +1,81 @@
#
# Copyright (c) 2012, Jared Boone <jared@sharebrained.com>
# Copyright (c) 2013, Benjamin Vernoux <titanmkd@gmail.com>
# Copyright (c) 2013, Michael Ossmann <mike@ossmann.com>
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
#
# Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
# Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# Neither the name of Great Scott Gadgets nor the names of its contributors may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Based heavily upon the libftdi cmake setup.
# Targets
set(c_sources ${CMAKE_CURRENT_SOURCE_DIR}/hackrf.c CACHE INTERNAL "List of C sources")
set(c_headers ${CMAKE_CURRENT_SOURCE_DIR}/hackrf.h CACHE INTERNAL "List of C headers")
# Dynamic library
add_library(hackrf SHARED ${c_sources})
set_target_properties(hackrf PROPERTIES VERSION ${MAJOR_VERSION}.${MINOR_VERSION}.0 SOVERSION 0)
# Static library
add_library(hackrf-static STATIC ${c_sources})
if(MSVC)
set_target_properties(hackrf-static PROPERTIES OUTPUT_NAME "hackrf_static")
else()
set_target_properties(hackrf-static PROPERTIES OUTPUT_NAME "hackrf")
endif()
set_target_properties(hackrf PROPERTIES CLEAN_DIRECT_OUTPUT 1)
set_target_properties(hackrf-static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
# Dependencies
target_link_libraries(hackrf ${LIBUSB_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
# For cygwin just force UNIX OFF and WIN32 ON
if( ${CYGWIN} )
SET(UNIX OFF)
SET(WIN32 ON)
endif( ${CYGWIN} )
if( ${UNIX} )
install(TARGETS hackrf
LIBRARY DESTINATION lib${LIB_SUFFIX}
COMPONENT sharedlibs
)
install(TARGETS hackrf-static
ARCHIVE DESTINATION lib${LIB_SUFFIX}
COMPONENT staticlibs
)
install(FILES ${c_headers}
DESTINATION include/${PROJECT_NAME}
COMPONENT headers
)
endif( ${UNIX} )
if( ${WIN32} )
install(TARGETS hackrf
DESTINATION bin
COMPONENT sharedlibs
)
install(TARGETS hackrf-static
DESTINATION bin
COMPONENT staticlibs
)
install(FILES ${c_headers}
DESTINATION include/${PROJECT_NAME}
COMPONENT headers
)
endif( ${WIN32} )

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,335 @@
/*
Copyright (c) 2012, Jared Boone <jared@sharebrained.com>
Copyright (c) 2013, Benjamin Vernoux <titanmkd@gmail.com>
Copyright (c) 2013, Michael Ossmann <mike@ossmann.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of Great Scott Gadgets nor the names of its contributors may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __HACKRF_H__
#define __HACKRF_H__
#include <stdint.h>
#ifdef _WIN32
#define ADD_EXPORTS
/* You should define ADD_EXPORTS *only* when building the DLL. */
#ifdef ADD_EXPORTS
#define ADDAPI __declspec(dllexport)
#else
#define ADDAPI __declspec(dllimport)
#endif
/* Define calling convention in one place, for convenience. */
#define ADDCALL __cdecl
#else /* _WIN32 not defined. */
/* Define with no value on non-Windows OSes. */
#define ADDAPI
#define ADDCALL
#endif
#define SAMPLES_PER_BLOCK 8192
#define BYTES_PER_BLOCK 16384
#define MAX_SWEEP_RANGES 10
#define HACKRF_OPERACAKE_ADDRESS_INVALID 0xFF
#define HACKRF_OPERACAKE_MAX_BOARDS 8
#define HACKRF_OPERACAKE_MAX_DWELL_TIMES 16
#define HACKRF_OPERACAKE_MAX_FREQ_RANGES 8
enum hackrf_error {
HACKRF_SUCCESS = 0,
HACKRF_TRUE = 1,
HACKRF_ERROR_INVALID_PARAM = -2,
HACKRF_ERROR_NOT_FOUND = -5,
HACKRF_ERROR_BUSY = -6,
HACKRF_ERROR_NO_MEM = -11,
HACKRF_ERROR_LIBUSB = -1000,
HACKRF_ERROR_THREAD = -1001,
HACKRF_ERROR_STREAMING_THREAD_ERR = -1002,
HACKRF_ERROR_STREAMING_STOPPED = -1003,
HACKRF_ERROR_STREAMING_EXIT_CALLED = -1004,
HACKRF_ERROR_USB_API_VERSION = -1005,
HACKRF_ERROR_NOT_LAST_DEVICE = -2000,
HACKRF_ERROR_OTHER = -9999,
};
enum hackrf_board_id {
BOARD_ID_JELLYBEAN = 0,
BOARD_ID_JAWBREAKER = 1,
BOARD_ID_HACKRF_ONE = 2,
BOARD_ID_RAD1O = 3,
BOARD_ID_INVALID = 0xFF,
};
enum hackrf_usb_board_id {
USB_BOARD_ID_JAWBREAKER = 0x604B,
USB_BOARD_ID_HACKRF_ONE = 0x6089,
USB_BOARD_ID_RAD1O = 0xCC15,
USB_BOARD_ID_INVALID = 0xFFFF,
};
enum rf_path_filter {
RF_PATH_FILTER_BYPASS = 0,
RF_PATH_FILTER_LOW_PASS = 1,
RF_PATH_FILTER_HIGH_PASS = 2,
};
enum operacake_ports {
OPERACAKE_PA1 = 0,
OPERACAKE_PA2 = 1,
OPERACAKE_PA3 = 2,
OPERACAKE_PA4 = 3,
OPERACAKE_PB1 = 4,
OPERACAKE_PB2 = 5,
OPERACAKE_PB3 = 6,
OPERACAKE_PB4 = 7,
};
enum operacake_switching_mode {
/**
* Port connections are set manually using @ref hackrf_set_operacake_ports.
*/
OPERACAKE_MODE_MANUAL,
/**
* Port connections are switched automatically when the frequency is changed. Frequency ranges can be set using @ref hackrf_set_operacake_freq_ranges.
*/
OPERACAKE_MODE_FREQUENCY,
/**
* Port connections are switched automatically over time.
*/
OPERACAKE_MODE_TIME,
};
enum sweep_style {
LINEAR = 0,
INTERLEAVED = 1,
};
typedef struct hackrf_device hackrf_device;
/**
* USB transfer information passed to RX or TX callback.
* A callback should treat all these fields as read-only except that a TX callback should write to the data buffer.
*/
typedef struct {
hackrf_device* device; /**< HackRF USB device for this transfer */
uint8_t* buffer; /**< transfer data buffer */
int buffer_length; /**< length of data buffer in bytes */
int valid_length; /**< number of buffer bytes that were transferred */
void* rx_ctx; /**< RX libusb context */
void* tx_ctx; /**< TX libusb context */
} hackrf_transfer;
typedef struct {
uint32_t part_id[2];
uint32_t serial_no[4];
} read_partid_serialno_t;
typedef struct {
uint32_t dwell;
uint8_t port;
} hackrf_operacake_dwell_time;
typedef struct {
uint16_t freq_min;
uint16_t freq_max;
uint8_t port;
} hackrf_operacake_freq_range;
/** State of the SGPIO loop running on the M0 core. */
typedef struct {
/** Requested mode. */
uint16_t requested_mode;
/** Request flag. */
uint16_t request_flag;
/** Active mode. */
uint32_t active_mode;
/** Number of bytes transferred by the M0. */
uint32_t m0_count;
/** Number of bytes transferred by the M4. */
uint32_t m4_count;
/** Number of shortfalls. */
uint32_t num_shortfalls;
/** Longest shortfall. */
uint32_t longest_shortfall;
/** Shortfall limit in bytes. */
uint32_t shortfall_limit;
/** Threshold m0_count value for next mode change. */
uint32_t threshold;
/** Mode which will be switched to when threshold is reached. */
uint32_t next_mode;
/** Error, if any, that caused the M0 to revert to IDLE mode. */
uint32_t error;
} hackrf_m0_state;
struct hackrf_device_list {
char **serial_numbers;
enum hackrf_usb_board_id *usb_board_ids;
int *usb_device_index;
int devicecount;
void **usb_devices;
int usb_devicecount;
};
typedef struct hackrf_device_list hackrf_device_list_t;
typedef int (*hackrf_sample_block_cb_fn)(hackrf_transfer* transfer);
#ifdef __cplusplus
extern "C"
{
#endif
extern ADDAPI int ADDCALL hackrf_init();
extern ADDAPI int ADDCALL hackrf_exit();
extern ADDAPI const char* ADDCALL hackrf_library_version();
extern ADDAPI const char* ADDCALL hackrf_library_release();
extern ADDAPI hackrf_device_list_t* ADDCALL hackrf_device_list();
extern ADDAPI int ADDCALL hackrf_device_list_open(hackrf_device_list_t *list, int idx, hackrf_device** device);
extern ADDAPI void ADDCALL hackrf_device_list_free(hackrf_device_list_t *list);
extern ADDAPI int ADDCALL hackrf_open(hackrf_device** device);
extern ADDAPI int ADDCALL hackrf_open_by_serial(const char* const desired_serial_number, hackrf_device** device);
extern ADDAPI int ADDCALL hackrf_close(hackrf_device* device);
extern ADDAPI int ADDCALL hackrf_start_rx(hackrf_device* device, hackrf_sample_block_cb_fn callback, void* rx_ctx);
extern ADDAPI int ADDCALL hackrf_stop_rx(hackrf_device* device);
extern ADDAPI int ADDCALL hackrf_start_tx(hackrf_device* device, hackrf_sample_block_cb_fn callback, void* tx_ctx);
extern ADDAPI int ADDCALL hackrf_stop_tx(hackrf_device* device);
extern ADDAPI int ADDCALL hackrf_get_m0_state(hackrf_device* device, hackrf_m0_state* value);
extern ADDAPI int ADDCALL hackrf_set_tx_underrun_limit(hackrf_device* device, uint32_t value);
extern ADDAPI int ADDCALL hackrf_set_rx_overrun_limit(hackrf_device* device, uint32_t value);
/* return HACKRF_TRUE if success */
extern ADDAPI int ADDCALL hackrf_is_streaming(hackrf_device* device);
extern ADDAPI int ADDCALL hackrf_max2837_read(hackrf_device* device, uint8_t register_number, uint16_t* value);
extern ADDAPI int ADDCALL hackrf_max2837_write(hackrf_device* device, uint8_t register_number, uint16_t value);
extern ADDAPI int ADDCALL hackrf_si5351c_read(hackrf_device* device, uint16_t register_number, uint16_t* value);
extern ADDAPI int ADDCALL hackrf_si5351c_write(hackrf_device* device, uint16_t register_number, uint16_t value);
extern ADDAPI int ADDCALL hackrf_set_baseband_filter_bandwidth(hackrf_device* device, const uint32_t bandwidth_hz);
extern ADDAPI int ADDCALL hackrf_rffc5071_read(hackrf_device* device, uint8_t register_number, uint16_t* value);
extern ADDAPI int ADDCALL hackrf_rffc5071_write(hackrf_device* device, uint8_t register_number, uint16_t value);
extern ADDAPI int ADDCALL hackrf_spiflash_erase(hackrf_device* device);
extern ADDAPI int ADDCALL hackrf_spiflash_write(hackrf_device* device, const uint32_t address, const uint16_t length, unsigned char* const data);
extern ADDAPI int ADDCALL hackrf_spiflash_read(hackrf_device* device, const uint32_t address, const uint16_t length, unsigned char* data);
extern ADDAPI int ADDCALL hackrf_spiflash_status(hackrf_device* device, uint8_t* data);
extern ADDAPI int ADDCALL hackrf_spiflash_clear_status(hackrf_device* device);
/* device will need to be reset after hackrf_cpld_write */
extern ADDAPI int ADDCALL hackrf_cpld_write(hackrf_device* device,
unsigned char* const data, const unsigned int total_length);
extern ADDAPI int ADDCALL hackrf_board_id_read(hackrf_device* device, uint8_t* value);
extern ADDAPI int ADDCALL hackrf_version_string_read(hackrf_device* device, char* version, uint8_t length);
extern ADDAPI int ADDCALL hackrf_usb_api_version_read(hackrf_device* device, uint16_t* version);
extern ADDAPI int ADDCALL hackrf_set_freq(hackrf_device* device, const uint64_t freq_hz);
extern ADDAPI int ADDCALL hackrf_set_freq_explicit(hackrf_device* device,
const uint64_t if_freq_hz, const uint64_t lo_freq_hz,
const enum rf_path_filter path);
/* 2-20Mhz - either as a fraction, i.e. freq 20000000hz divider 2 -> 10Mhz or as plain old 10000000hz (double) */
extern ADDAPI int ADDCALL hackrf_set_sample_rate_manual(hackrf_device* device, const uint32_t freq_hz, const uint32_t divider);
extern ADDAPI int ADDCALL hackrf_set_sample_rate(hackrf_device* device, const double freq_hz);
/* external amp, bool on/off */
extern ADDAPI int ADDCALL hackrf_set_amp_enable(hackrf_device* device, const uint8_t value);
extern ADDAPI int ADDCALL hackrf_board_partid_serialno_read(hackrf_device* device, read_partid_serialno_t* read_partid_serialno);
/* range 0-40 step 8d, IF gain in osmosdr */
extern ADDAPI int ADDCALL hackrf_set_lna_gain(hackrf_device* device, uint32_t value);
/* range 0-62 step 2db, BB gain in osmosdr */
extern ADDAPI int ADDCALL hackrf_set_vga_gain(hackrf_device* device, uint32_t value);
/* range 0-47 step 1db */
extern ADDAPI int ADDCALL hackrf_set_txvga_gain(hackrf_device* device, uint32_t value);
/* antenna port power control */
extern ADDAPI int ADDCALL hackrf_set_antenna_enable(hackrf_device* device, const uint8_t value);
extern ADDAPI const char* ADDCALL hackrf_error_name(enum hackrf_error errcode);
extern ADDAPI const char* ADDCALL hackrf_board_id_name(enum hackrf_board_id board_id);
extern ADDAPI const char* ADDCALL hackrf_usb_board_id_name(enum hackrf_usb_board_id usb_board_id);
extern ADDAPI const char* ADDCALL hackrf_filter_path_name(const enum rf_path_filter path);
/* Compute nearest freq for bw filter (manual filter) */
extern ADDAPI uint32_t ADDCALL hackrf_compute_baseband_filter_bw_round_down_lt(const uint32_t bandwidth_hz);
/* Compute best default value depending on sample rate (auto filter) */
extern ADDAPI uint32_t ADDCALL hackrf_compute_baseband_filter_bw(const uint32_t bandwidth_hz);
/* All features below require USB API version 0x1002 or higher) */
/* set hardware sync mode */
extern ADDAPI int ADDCALL hackrf_set_hw_sync_mode(hackrf_device* device, const uint8_t value);
/* Start sweep mode */
extern ADDAPI int ADDCALL hackrf_init_sweep(hackrf_device* device,
const uint16_t* frequency_list, const int num_ranges,
const uint32_t num_bytes, const uint32_t step_width,
const uint32_t offset, const enum sweep_style style);
/* Operacake functions */
extern ADDAPI int ADDCALL hackrf_get_operacake_boards(hackrf_device* device, uint8_t* boards);
extern ADDAPI int ADDCALL hackrf_set_operacake_mode(hackrf_device* device, uint8_t address, enum operacake_switching_mode mode);
extern ADDAPI int ADDCALL hackrf_get_operacake_mode(hackrf_device* device, uint8_t address, enum operacake_switching_mode *mode);
extern ADDAPI int ADDCALL hackrf_set_operacake_ports(hackrf_device* device,
uint8_t address,
uint8_t port_a,
uint8_t port_b);
extern ADDAPI int ADDCALL hackrf_set_operacake_dwell_times(hackrf_device* device, hackrf_operacake_dwell_time *dwell_times, uint8_t count);
extern ADDAPI int ADDCALL hackrf_set_operacake_freq_ranges(hackrf_device* device, hackrf_operacake_freq_range *freq_ranges, uint8_t count);
extern ADDAPI int ADDCALL hackrf_reset(hackrf_device* device);
extern ADDAPI int ADDCALL hackrf_set_operacake_ranges(hackrf_device* device,
uint8_t* ranges,
uint8_t num_ranges);
extern ADDAPI int ADDCALL hackrf_set_clkout_enable(hackrf_device* device, const uint8_t value);
extern ADDAPI int ADDCALL hackrf_operacake_gpio_test(hackrf_device* device,
uint8_t address,
uint16_t* test_result);
#ifdef HACKRF_ISSUE_609_IS_FIXED
extern ADDAPI int ADDCALL hackrf_cpld_checksum(hackrf_device* device,
uint32_t* crc);
#endif /* HACKRF_ISSUE_609_IS_FIXED */
extern ADDAPI int ADDCALL hackrf_set_ui_enable(hackrf_device* device, const uint8_t value);
extern ADDAPI int ADDCALL hackrf_start_rx_sweep(hackrf_device* device, hackrf_sample_block_cb_fn callback, void* rx_ctx);
#ifdef __cplusplus
} // __cplusplus defined.
#endif
#endif /*__HACKRF_H__*/