From ea5422d788f757939173310c91cc7aeb0af1077d Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 21 Feb 2013 13:18:03 -0700 Subject: [PATCH] hackrf_spiflash example program (untested) --- host/libhackrf/examples/CMakeLists.txt | 2 + host/libhackrf/examples/hackrf_spiflash.c | 213 ++++++++++++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 host/libhackrf/examples/hackrf_spiflash.c diff --git a/host/libhackrf/examples/CMakeLists.txt b/host/libhackrf/examples/CMakeLists.txt index b4d7feda..a0d395ed 100644 --- a/host/libhackrf/examples/CMakeLists.txt +++ b/host/libhackrf/examples/CMakeLists.txt @@ -28,11 +28,13 @@ IF( EXAMPLES ) add_executable(hackrf_si5351c hackrf_si5351c.c) add_executable(hackrf_transfer hackrf_transfer.c) add_executable(hackrf_rffc5071 hackrf_rffc5071.c) + add_executable(hackrf_spiflash hackrf_spiflash.c) target_link_libraries(hackrf_max2837 hackrf) target_link_libraries(hackrf_si5351c hackrf) target_link_libraries(hackrf_transfer hackrf) target_link_libraries(hackrf_rffc5071 hackrf) + target_link_libraries(hackrf_spiflash hackrf) include_directories(BEFORE ${CMAKE_SOURCE_DIR}/src) endif(EXAMPLES) diff --git a/host/libhackrf/examples/hackrf_spiflash.c b/host/libhackrf/examples/hackrf_spiflash.c new file mode 100644 index 00000000..ba856628 --- /dev/null +++ b/host/libhackrf/examples/hackrf_spiflash.c @@ -0,0 +1,213 @@ +/* + * Copyright 2012 Jared Boone + * Copyright 2013 Benjamin Vernoux + * Copyright 2013 Michael Ossmann + * + * 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 + +#include +#include +#include +#include +#include +#include + +/* 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' }, + { 0, 0, 0, 0 }, +}; + +int parse_int(char* s, uint32_t* const value) +{ + uint_fast8_t base = 10; + 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; + } + } + } + + char* s_end = s; + const long 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-a, --address : starting address (default: 0)\n"); + printf("\t-l, --length : number of bytes to read or write (default: 0)\n"); + printf("\t-r : Read data into file.\n"); + printf("\t-w : Write data from file.\n"); +} + +int main(int argc, char** argv) +{ + int opt; + uint32_t address = 0; + uint32_t length = 0; + const char* path = NULL; + hackrf_device* device = NULL; + int result = HACKRF_SUCCESS; + int option_index = 0; + uint8_t data[MAX_LENGTH]; + FILE* fd = NULL; + bool read = false; + bool write = false; + + while ((opt = getopt_long(argc, argv, "a:l:r:w:", long_options, + &option_index)) != EOF) { + switch (opt) { + case 'a': + result = parse_int(optarg, &address); + break; + + case 'l': + result = parse_int(optarg, &length); + break; + + case 'r': + read = true; + path = optarg; + break; + + case 'w': + write = true; + path = optarg; + break; + + default: + 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) { + if (write == true) { + fprintf(stderr, "Read and write options are mutually exclusive.\n"); + } else { + fprintf(stderr, "Specify either read or write option.\n"); + } + usage(); + return EXIT_FAILURE; + } + + if ((length > MAX_LENGTH) || (address > MAX_LENGTH) + || ((address + length) > MAX_LENGTH)) { + fprintf(stderr, "Request exceeds size of flash memory.\n"); + usage(); + return EXIT_FAILURE; + } + + if (path == NULL) { + fprintf(stderr, "Specify a path to a file.\n"); + usage(); + 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(&device); + if (result != HACKRF_SUCCESS) { + fprintf(stderr, "hackrf_open() failed: %s (%d)\n", + hackrf_error_name(result), result); + return EXIT_FAILURE; + } + + if (read) { + fd = fopen(path, "wb"); + } else { + fd = fopen(path, "rb"); + } + + if (fd == NULL) { + fprintf(stderr, "Failed to open file: %s\n", path); + return EXIT_FAILURE; + } + + if (read) { + result = hackrf_spiflash_read(device, address, length, data); + if (result == HACKRF_SUCCESS) { + const ssize_t bytes_written = fwrite(data, 1, length, fd); + if (bytes_written != length) { + fprintf(stderr, "Failed write to file (wrote %d bytes).\n", + (int)bytes_written); + fclose(fd); + fd = NULL; + return EXIT_FAILURE; + } + } + } else { + const ssize_t bytes_read = fread(data, 1, length, fd); + if (bytes_read == length) { + result = hackrf_spiflash_write(device, address, length, data); + } else { + fprintf(stderr, "Failed read file (read %d bytes).\n", + (int)bytes_read); + fclose(fd); + fd = NULL; + 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 -1; + } + + hackrf_exit(); + + if (fd != NULL) { + fclose(fd); + } + + return EXIT_SUCCESS; +}