From 98eaa6374026e6a3e042c1ead2b2d6d595b14da3 Mon Sep 17 00:00:00 2001 From: Greg Shuflin Date: Mon, 1 Mar 2021 19:43:01 -0800 Subject: [PATCH] Port radio_read_image to rust --- radio.c | 84 ------------------------------------------------- src/radio.rs | 89 +++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 74 insertions(+), 99 deletions(-) diff --git a/radio.c b/radio.c index 56799ce..e5b7e00 100644 --- a/radio.c +++ b/radio.c @@ -71,90 +71,6 @@ void set_active_device(radio_device_t* d) { unsigned char radio_mem [1024*1024*2]; // Radio memory contents, up to 2 Mbytes -// -// Read firmware image from the binary file. -// -radio_device_t* radio_read_image(const char *filename) -{ - FILE *img; - struct stat st; - char ident[8]; - radio_device_t * dev = NULL; - - fprintf(stderr, "Read codeplug from file '%s'.\n", filename); - img = fopen(filename, "rb"); - if (! img) { - perror(filename); - exit(-1); - } - - // Guess device type by file size. - if (stat(filename, &st) < 0) { - perror(filename); - exit(-1); - } - switch (st.st_size) { - case 851968: - case 852533: - dev = &radio_uv380; - break; - case 262144: - case 262709: - dev = &radio_md380; - break; - case 1606528: - if (fread(ident, 1, 8, img) != 8) { - fprintf(stderr, "%s: Cannot read header.\n", filename); - exit(-1); - } - fseek(img, 0, SEEK_SET); - if (memcmp(ident, "D868UVE", 7) == 0) { - dev = &radio_d868uv; - } else if (memcmp(ident, "D878UV", 6) == 0) { - dev = &radio_d878uv; - } else if (memcmp(ident, "D6X2UV", 6) == 0) { - dev = &radio_dmr6x2; - } else { - fprintf(stderr, "%s: Unrecognized header '%.6s'\n", - filename, ident); - exit(-1); - } - break; - case 131072: - if (fread(ident, 1, 8, img) != 8) { - fprintf(stderr, "%s: Cannot read header.\n", filename); - exit(-1); - } - if (memcmp(ident, "BF-5R", 5) == 0) { - dev = &radio_rd5r; - } else if (memcmp(ident, "MD-760P", 7) == 0) { - dev = &radio_gd77; - } else if (memcmp(ident, "1801", 4) == 0) { - dev = &radio_dm1801; - } else if (memcmp(ident, "MD-760", 6) == 0) { - fprintf(stderr, "Old Radioddity GD-77 v2.6 image not supported!\n"); - exit(-1); - } else { - fprintf(stderr, "%s: Unrecognized header '%.6s'\n", - filename, ident); - exit(-1); - } - fseek(img, 0, SEEK_SET); - break; - default: - fprintf(stderr, "%s: Unrecognized file size %u bytes.\n", - filename, (int) st.st_size); - exit(-1); - } - - - dev->read_image(dev, img); - fclose(img); - - set_active_device(dev); - return dev; -} - // // Read the configuration from text file, and modify the firmware. // diff --git a/src/radio.rs b/src/radio.rs index eba845b..1504b34 100644 --- a/src/radio.rs +++ b/src/radio.rs @@ -37,7 +37,6 @@ extern { fn set_active_device(device: *const radio_device_t); fn radio_print_config(device: *const radio_device_t, file: *const libc::FILE, verbose: c_int); - fn radio_read_image(filename: *const c_char) -> *const radio_device_t; fn radio_parse_config(device: *const radio_device_t, filename: *const c_char); fn radio_write_csv(device: *const radio_device_t, filename: *const c_char); @@ -189,38 +188,98 @@ pub fn verify_config(radio: &Radio) { /// Read firmware image from the binary file. pub fn read_image(filename: &str) -> Radio { + use std::io::{Seek, SeekFrom, Read}; - /* - eprintln!"Read codeplug from file '{}'.", filename); + fn read_header(file: &mut std::fs::File, filename: &str) -> Vec { + let mut header_buf: [u8; 7] = [0; 7]; + match file.read(&mut header_buf) { + Ok(7) => (), + Ok(_) => { + eprintln!("{}: Cannot read header.", filename); + exit(-1); + }, + Err(e) => { + eprintln!("{}: Cannot read header. Error: {}", filename, e); + exit(-1); + } + }; - let img = std::fs::File::open(filename).unwrap(); + file.seek(SeekFrom::Start(0)).unwrap(); + + header_buf.to_vec() + } + + eprintln!("Read codeplug from file '{}'.", filename); + + let mut img_file = std::fs::File::open(filename).unwrap(); let metadata = std::fs::metadata(filename).unwrap(); let file_size = metadata.len(); - match file_size { - 851968 | 852533 => { + let device = unsafe {match file_size { + 851968 | 852533 => { + &radio_uv380 } 262144 | 262709 => { - + &radio_md380 } 1606528 => { + let header = read_header(&mut img_file, filename); + if header.as_slice().starts_with(b"D868UVE") { + &radio_d868uv + } else if header.as_slice().starts_with(b"D878UV") { + &radio_d878uv + } else if header.as_slice().starts_with(b"D6X2UV") { + &radio_dmr6x2 + } else { + match std::str::from_utf8(&header) { + Ok(s) => eprintln!("Unrecognized header: {}", s), + Err(_) => eprintln!("Unrecognized header: {:?}", header), + }; + exit(-1) + } } 131072 => { + let header = read_header(&mut img_file, filename); + if header.as_slice().starts_with(b"BF-5R") { + &radio_rd5r + } else if header.as_slice().starts_with(b"MD-760P") { + &radio_gd77 + } else if header.as_slice().starts_with(b"1801") { + &radio_dm1801 + } else if header.as_slice().starts_with(b"MD-760") { + eprintln!("Old Radioddity GD-77 v2.6 image not supported!"); + exit(-1) + } else { + match std::str::from_utf8(&header) { + Ok(s) => eprintln!("Unrecognized header: {}", s), + Err(_) => eprintln!("Unrecognized header: {:?}", header), + }; + exit(-1) + + } } size => { eprintln!("{}: Unrecognized file size {} bytes.", filename, size); - exit(-1); + exit(-1) } - }; - */ + } }; + + let fd = img_file.as_raw_fd(); + let mode = CString::new("rb").unwrap(); + unsafe { + let device = device as *const radio_device_t; + let device = device as *mut radio_device_t; + let file = libc::fdopen(fd, mode.as_ptr()); + let read_image_fn = (*device).read_image.unwrap(); + + read_image_fn(device, file); + libc::fclose(file); + set_active_device(device); + Radio { ptr: device } + } - let filename = CString::new(filename.to_string()).unwrap(); - let ptr = unsafe { - radio_read_image(filename.as_ptr()) - }; - Radio { ptr: ptr as *mut radio_device_t } } /// Save firmware image to the binary file.