Remove standalone binaries — functionality lives in freemkv CLI and tests

Deleted:
- freemkv_info.rs — duplicate of freemkv drive-info CLI command
- freemkv_test.rs — duplicate of bdemu capture-disc
- aacs_test.rs — covered by inline #[test] functions (31 tests)

libfreemkv is a library. CLI tools belong in the freemkv repo.
Dev/debug tools belong in (internal).
This commit is contained in:
MattJackson
2026-04-07 12:34:10 -07:00
parent df652c5735
commit 5fa6b064da
4 changed files with 0 additions and 374 deletions
-11
View File
@@ -25,14 +25,3 @@ zip = { version = "2", default-features = false, features = ["deflate"] }
[target.'cfg(target_os = "linux")'.dependencies] [target.'cfg(target_os = "linux")'.dependencies]
libc = "0.2" libc = "0.2"
[[bin]]
name = "freemkv-info"
path = "src/bin/freemkv_info.rs"
[[bin]]
name = "freemkv-test"
path = "src/bin/freemkv_test.rs"
[[bin]]
name = "aacs-test"
path = "src/bin/aacs_test.rs"
-105
View File
@@ -1,105 +0,0 @@
//! aacs-test — Test AACS handshake against a real drive.
//!
//! Usage: aacs-test /dev/sr0 /path/to/keydb.cfg
use std::env;
use std::path::Path;
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() < 3 {
eprintln!("Usage: aacs-test <device> <keydb_path>");
std::process::exit(1);
}
let device = Path::new(&args[1]);
let keydb_path = Path::new(&args[2]);
println!("aacs-test v{}", env!("CARGO_PKG_VERSION"));
println!();
// Open drive WITHOUT unlock — AACS auth must happen before raw mode
print!("Opening {} (no unlock)... ", device.display());
let mut session = match libfreemkv::DriveSession::open_no_unlock(device) {
Ok(s) => { println!("OK"); s }
Err(e) => { println!("FAILED: {}", e); std::process::exit(1); }
};
println!(" Drive: {} {}", session.profile.drive_id.trim(), session.profile.chipset.name());
// Load KEYDB
print!("Loading KEYDB... ");
let keydb = match libfreemkv::aacs::KeyDb::load(keydb_path) {
Ok(db) => {
println!("OK ({} disc entries, {} DK, {} PK)",
db.disc_entries.len(), db.device_keys.len(), db.processing_keys.len());
db
}
Err(e) => { println!("FAILED: {}", e); std::process::exit(1); }
};
let host_cert = match &keydb.host_cert {
Some(hc) => {
println!(" Host cert: {} bytes, priv_key[0]=0x{:02x}",
hc.certificate.len(), hc.private_key[0]);
hc
}
None => { println!(" No host cert in KEYDB"); std::process::exit(1); }
};
// AACS handshake
println!();
print!("AACS authenticate... ");
let mut auth = match libfreemkv::aacs::handshake::aacs_authenticate(
&mut session,
&host_cert.private_key,
&host_cert.certificate,
) {
Ok(a) => {
println!("OK");
println!(" Bus key: {:02x?}", &a.bus_key);
println!(" AGID: {}", a.agid);
println!(" Drive cert type: 0x{:02x}", a.drive_cert[0]);
a
}
Err(e) => {
println!("FAILED: {}", e);
std::process::exit(1);
}
};
// Read Volume ID
print!("Reading Volume ID... ");
match libfreemkv::aacs::handshake::read_volume_id(&mut session, &mut auth) {
Ok(vid) => {
println!("OK");
println!(" VID: {:02x?}", vid);
// Try to find matching disc in KEYDB
let matched = keydb.disc_entries.values()
.find(|e| e.disc_id == Some(vid));
if let Some(entry) = matched {
println!(" KEYDB match: {} (hash {})", entry.title, entry.disc_hash);
if let Some(vuk) = entry.vuk {
println!(" VUK: {:02x?}", vuk);
}
} else {
println!(" No exact VID match in KEYDB");
}
}
Err(e) => println!("FAILED: {}", e),
}
// Read data keys (AACS 2.0)
print!("Reading data keys... ");
match libfreemkv::aacs::handshake::read_data_keys(&mut session, &mut auth) {
Ok((rdk, wdk)) => {
println!("OK (AACS 2.0 bus encryption)");
println!(" Read data key: {:02x?}", rdk);
println!(" Write data key: {:02x?}", wdk);
}
Err(e) => println!("not available: {} (likely AACS 1.0)", e),
}
println!();
println!("Done.");
}
-159
View File
@@ -1,159 +0,0 @@
//! freemkv-info — Drive identification and compatibility checker.
//!
//! Sends standard SCSI INQUIRY and GET CONFIGURATION commands to an optical drive,
//! displays drive identity and compatibility status, and optionally outputs raw
//! response data for profile contribution.
//!
//! Usage:
//! freemkv-info /dev/sr0
//! freemkv-info /dev/sr0 --raw
//! freemkv-info /dev/sr0 --json
use std::env;
use std::path::Path;
use std::process;
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
eprintln!("freemkv-info — Drive identification and compatibility checker");
eprintln!();
eprintln!("Usage: freemkv-info <device> [options]");
eprintln!();
eprintln!(" <device> Optical drive device (e.g. /dev/sr0)");
eprintln!(" --raw Output raw SCSI response hex (for profile contribution)");
eprintln!(" --json Output machine-readable JSON");
eprintln!(" --profiles Path to profiles directory (default: ./profiles)");
eprintln!();
eprintln!("Examples:");
eprintln!(" freemkv-info /dev/sr0");
eprintln!(" freemkv-info /dev/sr0 --raw > my_drive.txt");
process::exit(1);
}
let device = Path::new(&args[1]);
let raw_mode = args.iter().any(|a| a == "--raw");
let json_mode = args.iter().any(|a| a == "--json");
let profiles_dir = args.iter()
.position(|a| a == "--profiles")
.and_then(|i| args.get(i + 1))
.map(|s| s.as_str())
.unwrap_or("profiles");
// Open SCSI transport
let mut transport = match libfreemkv::scsi::open(device) {
Ok(t) => t,
Err(e) => {
eprintln!("Error: Cannot open {}: {}", device.display(), e);
process::exit(1);
}
};
// INQUIRY
let inquiry = match libfreemkv::scsi::inquiry(transport.as_mut()) {
Ok(i) => i,
Err(e) => {
eprintln!("Error: INQUIRY failed: {}", e);
process::exit(1);
}
};
// GET CONFIGURATION feature 0x010C
let gc_010c = libfreemkv::scsi::get_config_010c(transport.as_mut()).ok();
if json_mode {
print_json(&inquiry, &gc_010c);
} else if raw_mode {
print_raw(&inquiry, &gc_010c);
} else {
print_human(&inquiry, &gc_010c, profiles_dir);
}
}
fn print_human(
inquiry: &libfreemkv::scsi::InquiryResult,
gc_010c: &Option<Vec<u8>>,
profiles_dir: &str,
) {
println!("freemkv-info v{}", env!("CARGO_PKG_VERSION"));
println!();
println!("Drive: {} {} {}", inquiry.vendor_id, inquiry.model, inquiry.firmware);
println!("INQUIRY: additional_length=0x{:02X} ({})",
inquiry.raw.get(4).unwrap_or(&0),
inquiry.raw.get(4).unwrap_or(&0));
if let Some(gc) = gc_010c {
let data_hex: String = gc.iter().map(|b| format!("{:02x}", b)).collect();
println!("Feature 0x010C: {}", data_hex);
} else {
println!("Feature 0x010C: not available");
}
// Try to match profile
if let Ok(profiles) = libfreemkv::profile::load_all(Path::new(profiles_dir)) {
let matched = profiles.iter().find(|p| {
p.drive_id.contains(&inquiry.vendor_id)
&& p.drive_id.contains(&inquiry.model)
});
println!();
match matched {
Some(p) => {
println!("Profile: FOUND ({})", p.chipset.name());
println!("Raw Read: Supported");
}
None => {
println!("Profile: NOT FOUND");
println!("Raw Read: Unknown — run with --raw and submit a profile request");
}
}
} else {
println!();
println!("Profile: No profiles directory found at '{}'", profiles_dir);
}
}
fn print_raw(
inquiry: &libfreemkv::scsi::InquiryResult,
gc_010c: &Option<Vec<u8>>,
) {
println!("# freemkv-info raw output");
println!("# Submit this file to https://github.com/freemkv/libfreemkv/issues");
println!();
println!("vendor: {}", inquiry.vendor_id);
println!("model: {}", inquiry.model);
println!("firmware: {}", inquiry.firmware);
println!();
// Full INQUIRY hex
println!("inquiry_hex: {}", hex_encode(&inquiry.raw));
println!("inquiry_length: {}", inquiry.raw.len());
// GET CONFIG 0x010C
if let Some(gc) = gc_010c {
println!("get_config_010c_hex: {}", hex_encode(gc));
println!("get_config_010c_length: {}", gc.len());
} else {
println!("get_config_010c_hex: ERROR");
}
}
fn print_json(
inquiry: &libfreemkv::scsi::InquiryResult,
gc_010c: &Option<Vec<u8>>,
) {
let json = serde_json::json!({
"vendor": inquiry.vendor_id,
"model": inquiry.model,
"firmware": inquiry.firmware,
"inquiry_hex": hex_encode(&inquiry.raw),
"inquiry_length": inquiry.raw.len(),
"get_config_010c_hex": gc_010c.as_ref().map(|g| hex_encode(g)),
});
println!("{}", serde_json::to_string_pretty(&json).unwrap());
}
fn hex_encode(data: &[u8]) -> String {
data.iter().map(|b| format!("{:02x}", b)).collect()
}
-99
View File
@@ -1,99 +0,0 @@
//! freemkv-test — Quick verification that raw disc access works.
//!
//! Enables raw read mode, calibrates speed, reads a few test sectors.
//! Use this to verify your drive and profile are working correctly.
//!
//! Usage:
//! freemkv-test /dev/sr0
//! freemkv-test /dev/sr0 --profiles ./profiles
use std::env;
use std::path::Path;
use std::process;
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
eprintln!("freemkv-test — Verify raw disc access works");
eprintln!();
eprintln!("Usage: freemkv-test <device> [--profiles <dir>]");
process::exit(1);
}
let device = Path::new(&args[1]);
println!("freemkv-test v{}", env!("CARGO_PKG_VERSION"));
println!();
// Open drive session (uses bundled profiles)
print!("Opening {}... ", device.display());
let mut session = match libfreemkv::DriveSession::open(device) {
Ok(s) => { println!("OK"); s }
Err(e) => { println!("FAILED: {}", e); process::exit(1); }
};
println!(" Drive ID: {}", session.profile.drive_id);
println!(" Chipset: {}", session.profile.chipset.name());
println!();
// Enable raw read mode
print!("Unlocking drive... ");
match session.unlock() {
Ok(()) => println!("OK"),
Err(e) => { println!("FAILED: {}", e); process::exit(1); }
}
// Check status
print!("Checking status... ");
match session.status() {
Ok(status) => {
if status.unlocked {
println!("OK (active)");
} else {
println!("WARNING: drive reported as locked");
}
}
Err(e) => println!("SKIP ({})", e),
}
// Calibrate speed
print!("Calibrating speed... ");
match session.calibrate() {
Ok(()) => println!("OK"),
Err(e) => println!("SKIP ({})", e),
}
// Read test sectors
let test_lbas: &[u32] = &[0, 100, 1000, 10000];
let mut buf = vec![0u8; 2048];
let mut pass = 0;
let mut fail = 0;
for &lba in test_lbas {
print!("Reading sector {}... ", lba);
match session.read_sectors(lba, 1, &mut buf) {
Ok(n) if n == 2048 => {
let nonzero = buf.iter().filter(|&&b| b != 0).count();
println!("OK ({} bytes, {} non-zero)", n, nonzero);
pass += 1;
}
Ok(n) => {
println!("PARTIAL ({} bytes)", n);
fail += 1;
}
Err(e) => {
println!("FAILED: {}", e);
fail += 1;
}
}
}
println!();
if fail == 0 {
println!("All {} checks passed. Drive is fully functional.", pass);
} else {
println!("{} passed, {} failed.", pass, fail);
process::exit(1);
}
}