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,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