Merge pull request #950 from miek/operacake-cleanup
Opera Cake CLI/API cleanup
This commit is contained in:
@ -34,7 +34,6 @@ typedef int bool;
|
|||||||
|
|
||||||
#define FREQ_MIN_MHZ (0) /* 0 MHz */
|
#define FREQ_MIN_MHZ (0) /* 0 MHz */
|
||||||
#define FREQ_MAX_MHZ (7250) /* 7250 MHz */
|
#define FREQ_MAX_MHZ (7250) /* 7250 MHz */
|
||||||
#define MAX_FREQ_RANGES 8
|
|
||||||
|
|
||||||
#define INVALID_ADDRESS 0xFF
|
#define INVALID_ADDRESS 0xFF
|
||||||
#define INVALID_MODE 0xFF
|
#define INVALID_MODE 0xFF
|
||||||
@ -46,12 +45,13 @@ static void usage() {
|
|||||||
printf("\nUsage:\n");
|
printf("\nUsage:\n");
|
||||||
printf("\t-h, --help: this help\n");
|
printf("\t-h, --help: this help\n");
|
||||||
printf("\t-d, --device <n>: specify a particular device by serial number\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: 0x00]\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-m, --mode <mode>: specify switching mode [options: manual, frequency, time]\n");
|
||||||
printf("\t-a <n>: set port A connection\n");
|
printf("\t-a <n>: set port A connection\n");
|
||||||
printf("\t-b <n>: set port B connection\n");
|
printf("\t-b <n>: set port B connection\n");
|
||||||
printf("\t-f <min:max:port>: automatically assign <port> for range <min:max> in MHz\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. This argument can be repeated to specify a list of ports.\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");
|
||||||
printf("\t-l, --list: list available operacake boards\n");
|
printf("\t-l, --list: list available operacake boards\n");
|
||||||
printf("\t-g, --gpio_test: test GPIO functionality of an opera cake\n");
|
printf("\t-g, --gpio_test: test GPIO functionality of an opera cake\n");
|
||||||
}
|
}
|
||||||
@ -66,12 +66,6 @@ static struct option long_options[] = {
|
|||||||
{ 0, 0, 0, 0 },
|
{ 0, 0, 0, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint16_t freq_min;
|
|
||||||
uint16_t freq_max;
|
|
||||||
uint8_t port;
|
|
||||||
} hackrf_oc_range;
|
|
||||||
|
|
||||||
int parse_uint16(char* const s, uint16_t* const value) {
|
int parse_uint16(char* const s, uint16_t* const value) {
|
||||||
char* s_end = s;
|
char* s_end = s;
|
||||||
const long long_value = strtol(s, &s_end, 10);
|
const long long_value = strtol(s, &s_end, 10);
|
||||||
@ -128,30 +122,23 @@ int parse_port(char* str, uint8_t* port) {
|
|||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_range(char* s, hackrf_oc_range* range) {
|
int parse_range(char* s, hackrf_operacake_freq_range* range) {
|
||||||
|
char port[16];
|
||||||
|
float min;
|
||||||
|
float max;
|
||||||
int result;
|
int result;
|
||||||
char *sep = strchr(s, ':');
|
|
||||||
if (!sep)
|
|
||||||
return HACKRF_ERROR_INVALID_PARAM;
|
|
||||||
// Replace : separator to null terminate string for strtol()
|
|
||||||
*sep = 0;
|
|
||||||
sep++; // Skip past the separator
|
|
||||||
|
|
||||||
char *sep2 = strchr(sep, ':');
|
// Read frequency as a float here to support scientific notation (e.g: 1e6)
|
||||||
if (!sep2)
|
if (sscanf(s, "%15[^:]:%f:%f", port, &min, &max) == 3) {
|
||||||
return HACKRF_ERROR_INVALID_PARAM;
|
result = parse_port(port, &(range->port));
|
||||||
// Replace : separator to null terminate string for strtol()
|
|
||||||
*sep2 = 0;
|
|
||||||
sep2++; // Skip past the separator
|
|
||||||
|
|
||||||
result = parse_uint16(s, &range->freq_min);
|
|
||||||
if (result != HACKRF_SUCCESS)
|
if (result != HACKRF_SUCCESS)
|
||||||
return result;
|
return result;
|
||||||
result = parse_uint16(sep, &range->freq_max);
|
|
||||||
if (result != HACKRF_SUCCESS)
|
range->freq_min = min;
|
||||||
return result;
|
range->freq_max = max;
|
||||||
result = parse_port(sep2, &(range->port));
|
return HACKRF_SUCCESS;
|
||||||
return result;
|
}
|
||||||
|
return HACKRF_ERROR_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_dwell(char* s, hackrf_operacake_dwell_time* dwell_time) {
|
int parse_dwell(char* s, hackrf_operacake_dwell_time* dwell_time) {
|
||||||
@ -165,8 +152,20 @@ int parse_dwell(char* s, hackrf_operacake_dwell_time* dwell_time) {
|
|||||||
if (result != HACKRF_SUCCESS)
|
if (result != HACKRF_SUCCESS)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
if (dwell == 0) {
|
||||||
|
fprintf(stderr, "dwell time cannot be 0\n");
|
||||||
|
return HACKRF_ERROR_INVALID_PARAM;
|
||||||
|
}
|
||||||
dwell_time->dwell = (uint32_t)dwell;
|
dwell_time->dwell = (uint32_t)dwell;
|
||||||
return HACKRF_SUCCESS;
|
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;
|
return HACKRF_ERROR_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
@ -174,7 +173,7 @@ int parse_dwell(char* s, hackrf_operacake_dwell_time* dwell_time) {
|
|||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
int opt;
|
int opt;
|
||||||
const char* serial_number = NULL;
|
const char* serial_number = NULL;
|
||||||
uint8_t operacake_address = INVALID_ADDRESS;
|
uint8_t operacake_address = 0;
|
||||||
bool set_mode = false;
|
bool set_mode = false;
|
||||||
uint8_t mode;
|
uint8_t mode;
|
||||||
uint8_t port_a = INVALID_PORT;
|
uint8_t port_a = INVALID_PORT;
|
||||||
@ -187,10 +186,11 @@ int main(int argc, char** argv) {
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
hackrf_device* device = NULL;
|
hackrf_device* device = NULL;
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
hackrf_oc_range ranges[MAX_FREQ_RANGES];
|
hackrf_operacake_freq_range ranges[HACKRF_OPERACAKE_MAX_FREQ_RANGES];
|
||||||
hackrf_operacake_dwell_time dwell_times[HACKRF_OPERACAKE_MAX_DWELL_TIMES];
|
hackrf_operacake_dwell_time dwell_times[HACKRF_OPERACAKE_MAX_DWELL_TIMES];
|
||||||
uint8_t range_idx = 0;
|
uint8_t range_idx = 0;
|
||||||
uint8_t dwell_idx = 0;
|
uint8_t dwell_idx = 0;
|
||||||
|
uint32_t default_dwell = 0;
|
||||||
|
|
||||||
int result = hackrf_init();
|
int result = hackrf_init();
|
||||||
if( result ) {
|
if( result ) {
|
||||||
@ -198,7 +198,7 @@ int main(int argc, char** argv) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while( (opt = getopt_long(argc, argv, "d:o:a:m:b:lf:t:hg?", long_options, &option_index)) != EOF ) {
|
while( (opt = getopt_long(argc, argv, "d:o:a:m:b:lf:t:w:hg?", long_options, &option_index)) != EOF ) {
|
||||||
switch( opt ) {
|
switch( opt ) {
|
||||||
case 'd':
|
case 'd':
|
||||||
serial_number = optarg;
|
serial_number = optarg;
|
||||||
@ -227,10 +227,10 @@ int main(int argc, char** argv) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
if(MAX_FREQ_RANGES == range_idx) {
|
if (HACKRF_OPERACAKE_MAX_FREQ_RANGES == range_idx) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"argument error: specify a maximum of %u frequency ranges.\n",
|
"argument error: specify a maximum of %u frequency ranges.\n",
|
||||||
MAX_FREQ_RANGES);
|
HACKRF_OPERACAKE_MAX_FREQ_RANGES);
|
||||||
usage();
|
usage();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
@ -271,6 +271,10 @@ int main(int argc, char** argv) {
|
|||||||
dwell_idx++;
|
dwell_idx++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'w':
|
||||||
|
default_dwell = atof(optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'a':
|
case 'a':
|
||||||
result = parse_port(optarg, &port_a);
|
result = parse_port(optarg, &port_a);
|
||||||
if (result != HACKRF_SUCCESS) {
|
if (result != HACKRF_SUCCESS) {
|
||||||
@ -309,14 +313,12 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!(list || set_mode || set_ports || range_idx || gpio_test)) {
|
// Any operations that set a parameter on an Opera Cake board.
|
||||||
fprintf(stderr, "Specify either list, mode, address, or GPIO test option.\n");
|
bool set_params = set_mode || set_ports || range_idx || dwell_idx;
|
||||||
usage();
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((set_mode || set_ports || gpio_test) && (operacake_address == INVALID_ADDRESS)) {
|
// Error out unless exactly one option is selected.
|
||||||
fprintf(stderr, "An address is required.\n");
|
if (list + set_params + gpio_test != 1) {
|
||||||
|
fprintf(stderr, "Specify either list, mode, or GPIO test option.\n");
|
||||||
usage();
|
usage();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
@ -446,25 +448,24 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (range_idx) {
|
if (range_idx) {
|
||||||
uint8_t range_bytes[MAX_FREQ_RANGES * sizeof(hackrf_oc_range)];
|
result = hackrf_set_operacake_freq_ranges(device, ranges, range_idx);
|
||||||
uint8_t ptr;
|
|
||||||
for(i=0; i<range_idx; i++) {
|
|
||||||
ptr = 5*i;
|
|
||||||
range_bytes[ptr] = ranges[i].freq_min >> 8;
|
|
||||||
range_bytes[ptr+1] = ranges[i].freq_min & 0xFF;
|
|
||||||
range_bytes[ptr+2] = ranges[i].freq_max >> 8;
|
|
||||||
range_bytes[ptr+3] = ranges[i].freq_max & 0xFF;
|
|
||||||
range_bytes[ptr+4] = ranges[i].port;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = hackrf_set_operacake_ranges(device, range_bytes, range_idx*5);
|
|
||||||
if (result) {
|
if (result) {
|
||||||
printf("hackrf_set_operacake_ranges() failed: %s (%d)\n", hackrf_error_name(result), result);
|
printf("hackrf_set_operacake_freq_ranges() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dwell_idx) {
|
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);
|
result = hackrf_set_operacake_dwell_times(device, dwell_times, dwell_idx);
|
||||||
if( result ) {
|
if( result ) {
|
||||||
printf("hackrf_set_operacake_dwell_times() failed: %s (%d)\n", hackrf_error_name(result), result);
|
printf("hackrf_set_operacake_dwell_times() failed: %s (%d)\n", hackrf_error_name(result), result);
|
||||||
|
@ -2266,6 +2266,9 @@ int ADDCALL hackrf_reset(hackrf_device* device) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated This has been replaced by @ref hackrf_set_operacake_freq_ranges
|
||||||
|
*/
|
||||||
int ADDCALL hackrf_set_operacake_ranges(hackrf_device* device, uint8_t* ranges, uint8_t len_ranges)
|
int ADDCALL hackrf_set_operacake_ranges(hackrf_device* device, uint8_t* ranges, uint8_t len_ranges)
|
||||||
{
|
{
|
||||||
USB_API_REQUIRED(device, 0x0103)
|
USB_API_REQUIRED(device, 0x0103)
|
||||||
@ -2290,6 +2293,43 @@ int ADDCALL hackrf_set_operacake_ranges(hackrf_device* device, uint8_t* ranges,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ADDCALL hackrf_set_operacake_freq_ranges(hackrf_device* device, hackrf_operacake_freq_range* freq_ranges, uint8_t count)
|
||||||
|
{
|
||||||
|
USB_API_REQUIRED(device, 0x0103)
|
||||||
|
|
||||||
|
uint8_t range_bytes[HACKRF_OPERACAKE_MAX_FREQ_RANGES * sizeof(hackrf_operacake_freq_range)];
|
||||||
|
uint8_t ptr;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
ptr = 5*i;
|
||||||
|
range_bytes[ptr] = freq_ranges[i].freq_min >> 8;
|
||||||
|
range_bytes[ptr+1] = freq_ranges[i].freq_min & 0xFF;
|
||||||
|
range_bytes[ptr+2] = freq_ranges[i].freq_max >> 8;
|
||||||
|
range_bytes[ptr+3] = freq_ranges[i].freq_max & 0xFF;
|
||||||
|
range_bytes[ptr+4] = freq_ranges[i].port;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result;
|
||||||
|
int len_ranges = count*5;
|
||||||
|
result = libusb_control_transfer(
|
||||||
|
device->usb_device,
|
||||||
|
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||||
|
HACKRF_VENDOR_REQUEST_OPERACAKE_SET_RANGES,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
range_bytes,
|
||||||
|
len_ranges,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result < len_ranges) {
|
||||||
|
last_libusb_error = result;
|
||||||
|
return HACKRF_ERROR_LIBUSB;
|
||||||
|
} else {
|
||||||
|
return HACKRF_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define DWELL_TIME_SIZE 5
|
#define DWELL_TIME_SIZE 5
|
||||||
static uint8_t dwell_data[DWELL_TIME_SIZE*HACKRF_OPERACAKE_MAX_DWELL_TIMES];
|
static uint8_t dwell_data[DWELL_TIME_SIZE*HACKRF_OPERACAKE_MAX_DWELL_TIMES];
|
||||||
int ADDCALL hackrf_set_operacake_dwell_times(hackrf_device* device, hackrf_operacake_dwell_time *dwell_times, uint8_t count)
|
int ADDCALL hackrf_set_operacake_dwell_times(hackrf_device* device, hackrf_operacake_dwell_time *dwell_times, uint8_t count)
|
||||||
|
@ -53,6 +53,7 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSI
|
|||||||
#define HACKRF_OPERACAKE_ADDRESS_INVALID 0xFF
|
#define HACKRF_OPERACAKE_ADDRESS_INVALID 0xFF
|
||||||
#define HACKRF_OPERACAKE_MAX_BOARDS 8
|
#define HACKRF_OPERACAKE_MAX_BOARDS 8
|
||||||
#define HACKRF_OPERACAKE_MAX_DWELL_TIMES 16
|
#define HACKRF_OPERACAKE_MAX_DWELL_TIMES 16
|
||||||
|
#define HACKRF_OPERACAKE_MAX_FREQ_RANGES 8
|
||||||
|
|
||||||
enum hackrf_error {
|
enum hackrf_error {
|
||||||
HACKRF_SUCCESS = 0,
|
HACKRF_SUCCESS = 0,
|
||||||
@ -144,6 +145,11 @@ typedef struct {
|
|||||||
uint8_t port;
|
uint8_t port;
|
||||||
} hackrf_operacake_dwell_time;
|
} hackrf_operacake_dwell_time;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t freq_min;
|
||||||
|
uint16_t freq_max;
|
||||||
|
uint8_t port;
|
||||||
|
} hackrf_operacake_freq_range;
|
||||||
|
|
||||||
struct hackrf_device_list {
|
struct hackrf_device_list {
|
||||||
char **serial_numbers;
|
char **serial_numbers;
|
||||||
@ -267,6 +273,7 @@ extern ADDAPI int ADDCALL hackrf_set_operacake_ports(hackrf_device* device,
|
|||||||
uint8_t port_a,
|
uint8_t port_a,
|
||||||
uint8_t port_b);
|
uint8_t port_b);
|
||||||
extern ADDAPI int ADDCALL hackrf_set_operacake_dwell_times(hackrf_device* device, hackrf_operacake_dwell_time *dwell_times, uint8_t count);
|
extern ADDAPI int ADDCALL hackrf_set_operacake_dwell_times(hackrf_device* device, hackrf_operacake_dwell_time *dwell_times, uint8_t count);
|
||||||
|
extern ADDAPI int ADDCALL hackrf_set_operacake_freq_ranges(hackrf_device* device, hackrf_operacake_freq_range *freq_ranges, uint8_t count);
|
||||||
|
|
||||||
extern ADDAPI int ADDCALL hackrf_reset(hackrf_device* device);
|
extern ADDAPI int ADDCALL hackrf_reset(hackrf_device* device);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user