libfreemkv v0.1.0 — Open source 4K UHD / Blu-ray / DVD drive library

Features:
- Open drive identification via SPC-4 INQUIRY + MMC-6 GET CONFIGURATION
- 141 supported drives with bundled profiles
- MT1959 platform: unlock, calibrate, raw sector reads
- DriveSpeed enum: BD1x-BD12x, DVD1x-DVD16x
- Field names follow SPC-4 §6.4.2 and MMC-6 §5.3.10 standards
- No proprietary fingerprints — open matching by SCSI fields
- Zero config: profiles compiled into binary

Tested on real hardware: HL-DT-ST BD-RE BU40N 1.03
This commit is contained in:
MattJackson
2026-04-06 10:00:00 -07:00
commit b9ea1d29dd
17 changed files with 3781 additions and 0 deletions
+46
View File
@@ -0,0 +1,46 @@
use std::fmt;
#[derive(Debug)]
pub enum Error {
DeviceNotFound(String),
UnsupportedDrive(String),
ScsiError { cdb: Vec<u8>, status: u8, sense: Vec<u8> },
UnlockFailed(String),
NotUnlocked,
NotCalibrated,
ProfileNotFound(String),
ProfileParse(String),
SignatureMismatch { expected: [u8; 4], got: [u8; 4] },
Io(std::io::Error),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::DeviceNotFound(s) => write!(f, "device not found: {s}"),
Error::UnsupportedDrive(s) => write!(f, "unsupported drive: {s}"),
Error::ScsiError { status, .. } => write!(f, "SCSI error: status 0x{status:02x}"),
Error::UnlockFailed(s) => write!(f, "unlock failed: {s}"),
Error::NotUnlocked => write!(f, "drive not unlocked, call unlock() first"),
Error::NotCalibrated => write!(f, "speed not calibrated, call calibrate() first"),
Error::ProfileNotFound(s) => write!(f, "no profile for: {s}"),
Error::ProfileParse(s) => write!(f, "profile parse error: {s}"),
Error::SignatureMismatch { expected, got } => {
write!(f, "signature mismatch: expected {:02x}{:02x}{:02x}{:02x}, got {:02x}{:02x}{:02x}{:02x}",
expected[0], expected[1], expected[2], expected[3],
got[0], got[1], got[2], got[3])
}
Error::Io(e) => write!(f, "I/O error: {e}"),
}
}
}
impl std::error::Error for Error {}
impl From<std::io::Error> for Error {
fn from(e: std::io::Error) -> Self {
Error::Io(e)
}
}
pub type Result<T> = std::result::Result<T, Error>;