Version 0.0.1
This commit is contained in:
237
main.c
237
main.c
@@ -48,11 +48,25 @@
|
||||
// Output formats
|
||||
enum Format { BINARY, HEX, BASE64, DECIMAL };
|
||||
|
||||
// Device types
|
||||
enum DeviceType { DEVICE_TRUERNGPROV2 = 1, DEVICE_TRUERNGPRO = 2, DEVICE_TRUERNG = 3 };
|
||||
|
||||
// Device information structure
|
||||
struct DeviceInfo {
|
||||
char port_path[MAX_PATH];
|
||||
char device_name[32];
|
||||
enum DeviceType type;
|
||||
char vid[8];
|
||||
char pid[8];
|
||||
};
|
||||
|
||||
// Command-line options structure
|
||||
struct Options {
|
||||
long long bytes;
|
||||
enum Format format;
|
||||
char *output_file;
|
||||
char *device_selector;
|
||||
int list_devices;
|
||||
int quiet;
|
||||
int verbose;
|
||||
int help;
|
||||
@@ -183,23 +197,35 @@ void print_usage(void) {
|
||||
printf(" Supports suffixes: K, MB, GB, TB (e.g., 1K, 2.5MB, 1GB)\n");
|
||||
printf(" -f, --format <FORMAT> Output format: binary, hex, base64, decimal (default: binary when piped, interactive otherwise)\n");
|
||||
printf(" -o, --output <FILE> Output filename (ignored in piped mode)\n");
|
||||
printf(" -d, --device <DEVICE> Select specific device (index, port, or type)\n");
|
||||
printf(" Examples: 1, /dev/ttyACM0, pro, prov2\n");
|
||||
printf(" -l, --list List all available TrueRNG devices\n");
|
||||
printf(" -q, --quiet Suppress statistics/progress\n");
|
||||
printf(" -v, --verbose Show detailed device information\n");
|
||||
printf(" -h, --help Show this help message\n");
|
||||
printf("\nDevice Selection:\n");
|
||||
printf(" When multiple devices are present, use -d to select:\n");
|
||||
printf(" -d 1 Select first device from list\n");
|
||||
printf(" -d /dev/ttyACM1 Select by port path\n");
|
||||
printf(" -d pro Select TrueRNGpro device\n");
|
||||
printf(" -d prov2 Select TrueRNGproV2 device\n");
|
||||
printf(" -d truerng Select original TrueRNG device\n");
|
||||
printf("\nExamples:\n");
|
||||
printf(" truerng -n 1024 -f hex # Interactive mode with hex output\n");
|
||||
printf(" truerng -n 1K -f hex # Same as above using K suffix\n");
|
||||
printf(" truerng -n 2.5MB | xxd # Piped mode with MB suffix\n");
|
||||
printf(" truerng -n 1GB -o random.dat -q # Save 1GB to file quietly\n");
|
||||
printf(" truerng -n 512K -f hex -o output.hex # Save 512KB as hex to file\n");
|
||||
printf(" truerng --list # List available devices\n");
|
||||
printf(" truerng -n 1K -f hex # Use first available device\n");
|
||||
printf(" truerng -d 2 -n 1MB # Use second device from list\n");
|
||||
printf(" truerng -d /dev/ttyACM1 -n 512K # Use specific port\n");
|
||||
printf(" truerng -d pro -n 1GB -o random.dat # Use TrueRNGpro device\n");
|
||||
}
|
||||
|
||||
int parse_arguments(int argc, char *argv[]) {
|
||||
static const char *opt_string = "n:f:o:qvh";
|
||||
static const char *opt_string = "n:f:o:d:lqvh";
|
||||
static struct option long_options[] = {
|
||||
{"bytes", required_argument, 0, 'n'},
|
||||
{"format", required_argument, 0, 'f'},
|
||||
{"output", required_argument, 0, 'o'},
|
||||
{"device", required_argument, 0, 'd'},
|
||||
{"list", no_argument, 0, 'l'},
|
||||
{"quiet", no_argument, 0, 'q'},
|
||||
{"verbose", no_argument, 0, 'v'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
@@ -209,6 +235,8 @@ int parse_arguments(int argc, char *argv[]) {
|
||||
options.bytes = 1048576; // Default 1MB
|
||||
options.format = BINARY;
|
||||
options.output_file = NULL;
|
||||
options.device_selector = NULL;
|
||||
options.list_devices = 0;
|
||||
options.quiet = 0;
|
||||
options.verbose = 0;
|
||||
options.help = 0;
|
||||
@@ -239,6 +267,12 @@ int parse_arguments(int argc, char *argv[]) {
|
||||
case 'o':
|
||||
options.output_file = optarg;
|
||||
break;
|
||||
case 'd':
|
||||
options.device_selector = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
options.list_devices = 1;
|
||||
break;
|
||||
case 'q':
|
||||
options.quiet = 1;
|
||||
break;
|
||||
@@ -262,7 +296,9 @@ int is_piped(void) {
|
||||
|
||||
// Function prototypes
|
||||
void init_ones_lookup_table(void);
|
||||
int find_truerng_port(char* port_path, int piped, int verbose);
|
||||
int find_all_truerng_devices(struct DeviceInfo devices[], int max_devices);
|
||||
int select_device_from_list(struct DeviceInfo devices[], int device_count, const char* selector, char* selected_port);
|
||||
void list_devices(struct DeviceInfo devices[], int device_count);
|
||||
int setup_serial_port(const char* port_path);
|
||||
int read_usb_device_info(const char* port_name, char* vid, char* pid);
|
||||
double get_time_diff(struct timeval start, struct timeval end);
|
||||
@@ -289,6 +325,132 @@ void init_ones_lookup_table(void) {
|
||||
}
|
||||
}
|
||||
|
||||
// Find all TrueRNG devices and populate device list
|
||||
// Returns: number of devices found
|
||||
int find_all_truerng_devices(struct DeviceInfo devices[], int max_devices) {
|
||||
DIR *dir;
|
||||
struct dirent *entry;
|
||||
char vid[8], pid[8];
|
||||
int device_count = 0;
|
||||
|
||||
dir = opendir("/dev");
|
||||
if (dir == NULL) {
|
||||
perror("Cannot open /dev directory");
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((entry = readdir(dir)) != NULL && device_count < max_devices) {
|
||||
// Look for ttyUSB* or ttyACM* devices
|
||||
if (strncmp(entry->d_name, "ttyUSB", 6) == 0 ||
|
||||
strncmp(entry->d_name, "ttyACM", 6) == 0) {
|
||||
|
||||
if (read_usb_device_info(entry->d_name, vid, pid)) {
|
||||
// Convert to uppercase for comparison
|
||||
for (int i = 0; vid[i]; i++) vid[i] = toupper(vid[i]);
|
||||
for (int i = 0; pid[i]; i++) pid[i] = toupper(pid[i]);
|
||||
|
||||
// Check for TrueRNGproV2
|
||||
if (strcmp(vid, TRUERNGPROV2_PID) == 0 && strcmp(pid, TRUERNGPROV2_HID) == 0) {
|
||||
snprintf(devices[device_count].port_path, MAX_PATH, "/dev/%s", entry->d_name);
|
||||
strcpy(devices[device_count].device_name, "TrueRNGproV2");
|
||||
devices[device_count].type = DEVICE_TRUERNGPROV2;
|
||||
strcpy(devices[device_count].vid, vid);
|
||||
strcpy(devices[device_count].pid, pid);
|
||||
device_count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for TrueRNGpro
|
||||
if (strcmp(vid, TRUERNGPRO_PID) == 0 && strcmp(pid, TRUERNGPRO_HID) == 0) {
|
||||
snprintf(devices[device_count].port_path, MAX_PATH, "/dev/%s", entry->d_name);
|
||||
strcpy(devices[device_count].device_name, "TrueRNGpro");
|
||||
devices[device_count].type = DEVICE_TRUERNGPRO;
|
||||
strcpy(devices[device_count].vid, vid);
|
||||
strcpy(devices[device_count].pid, pid);
|
||||
device_count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for TrueRNG
|
||||
if (strcmp(vid, TRUERNG_PID) == 0 && strcmp(pid, TRUERNG_HID) == 0) {
|
||||
snprintf(devices[device_count].port_path, MAX_PATH, "/dev/%s", entry->d_name);
|
||||
strcpy(devices[device_count].device_name, "TrueRNG");
|
||||
devices[device_count].type = DEVICE_TRUERNG;
|
||||
strcpy(devices[device_count].vid, vid);
|
||||
strcpy(devices[device_count].pid, pid);
|
||||
device_count++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
return device_count;
|
||||
}
|
||||
|
||||
// List all available devices
|
||||
void list_devices(struct DeviceInfo devices[], int device_count) {
|
||||
if (device_count == 0) {
|
||||
printf("No TrueRNG devices found.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Available TrueRNG devices:\n");
|
||||
for (int i = 0; i < device_count; i++) {
|
||||
printf(" %d. %s at %s (VID:%s PID:%s)\n",
|
||||
i + 1,
|
||||
devices[i].device_name,
|
||||
devices[i].port_path,
|
||||
devices[i].vid,
|
||||
devices[i].pid);
|
||||
}
|
||||
}
|
||||
|
||||
// Select device from list based on selector string
|
||||
// Returns: 0 on success, -1 on error
|
||||
int select_device_from_list(struct DeviceInfo devices[], int device_count, const char* selector, char* selected_port) {
|
||||
if (device_count == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// If no selector, use first device
|
||||
if (!selector) {
|
||||
strcpy(selected_port, devices[0].port_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Try to parse as device index (1-based)
|
||||
char* endptr;
|
||||
long index = strtol(selector, &endptr, 10);
|
||||
if (*endptr == '\0' && index >= 1 && index <= device_count) {
|
||||
strcpy(selected_port, devices[index - 1].port_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Try to match by port path
|
||||
if (strncmp(selector, "/dev/", 5) == 0) {
|
||||
for (int i = 0; i < device_count; i++) {
|
||||
if (strcmp(devices[i].port_path, selector) == 0) {
|
||||
strcpy(selected_port, devices[i].port_path);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try to match by device type
|
||||
for (int i = 0; i < device_count; i++) {
|
||||
if ((strcasecmp(selector, "prov2") == 0 && devices[i].type == DEVICE_TRUERNGPROV2) ||
|
||||
(strcasecmp(selector, "pro") == 0 && devices[i].type == DEVICE_TRUERNGPRO) ||
|
||||
(strcasecmp(selector, "truerng") == 0 && devices[i].type == DEVICE_TRUERNG)) {
|
||||
strcpy(selected_port, devices[i].port_path);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1; // No match found
|
||||
}
|
||||
|
||||
// Read USB device info from sysfs
|
||||
int read_usb_device_info(const char* port_name, char* vid, char* pid) {
|
||||
char path[MAX_PATH];
|
||||
@@ -471,6 +633,33 @@ int main(int argc, char *argv[]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Initialize lookup table
|
||||
init_ones_lookup_table();
|
||||
|
||||
// Find all available devices
|
||||
struct DeviceInfo devices[MAX_PORTS];
|
||||
int device_count = find_all_truerng_devices(devices, MAX_PORTS);
|
||||
|
||||
// Handle device listing
|
||||
if (options.list_devices) {
|
||||
list_devices(devices, device_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check if any devices were found
|
||||
if (device_count == 0) {
|
||||
fprintf(stderr, "No TrueRNG devices found\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Select device based on options
|
||||
char port_path[MAX_PATH];
|
||||
if (select_device_from_list(devices, device_count, options.device_selector, port_path) != 0) {
|
||||
fprintf(stderr, "Error: Could not select device '%s'\n", options.device_selector);
|
||||
fprintf(stderr, "Use --list to see available devices\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Determine mode: interactive (no args) vs piped (has args or actual piping)
|
||||
int interactive_mode = (argc == 1);
|
||||
int piped_mode = !interactive_mode || is_piped();
|
||||
@@ -481,6 +670,16 @@ int main(int argc, char *argv[]) {
|
||||
options.format = HEX;
|
||||
}
|
||||
|
||||
// Show multiple device warning if verbose or interactive
|
||||
if (device_count > 1 && !options.quiet) {
|
||||
if (interactive_mode || (piped_mode && options.verbose)) {
|
||||
if (!options.device_selector) {
|
||||
printf("Multiple TrueRNG devices found - using first available\n");
|
||||
printf("(Use -d option to select specific device or --list to see all)\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Print headers based on mode
|
||||
if (interactive_mode && !options.quiet) {
|
||||
// Interactive mode: always show headers unless quiet
|
||||
@@ -493,7 +692,20 @@ int main(int argc, char *argv[]) {
|
||||
printf("==================================================\n");
|
||||
}
|
||||
|
||||
char port_path[MAX_PATH];
|
||||
// Find the selected device info for display
|
||||
const char* device_name = "Unknown";
|
||||
for (int i = 0; i < device_count; i++) {
|
||||
if (strcmp(devices[i].port_path, port_path) == 0) {
|
||||
device_name = devices[i].device_name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Show device info
|
||||
if ((interactive_mode && !options.quiet) || (piped_mode && options.verbose && !options.quiet)) {
|
||||
printf("%s Found\n", device_name);
|
||||
}
|
||||
|
||||
int serial_fd;
|
||||
FILE *fp;
|
||||
unsigned char buffer[BLOCKSIZE];
|
||||
@@ -503,15 +715,6 @@ int main(int argc, char *argv[]) {
|
||||
struct timeval starttime, currenttime;
|
||||
double elapsed_time, rate;
|
||||
|
||||
// Initialize lookup table
|
||||
init_ones_lookup_table();
|
||||
|
||||
// Find TrueRNG device
|
||||
if (!find_truerng_port(port_path, piped_mode, options.verbose)) {
|
||||
fprintf(stderr, "TrueRNG Not Found\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Setup output
|
||||
if (piped_mode && !options.output_file) {
|
||||
fp = stdout;
|
||||
|
||||
Reference in New Issue
Block a user