unlock: route_unlock returns a structured UnlockRoute; ctx carries opts

Replace route_unlock's Option<(name, Vid)> with a structured UnlockRoute
{ Unlocked(name, Unlocked) | Failed(UnlockError) | NoMatch } so a single
dispatch serves every caller: drive-prep wants "did anything unlock", and the
AACS cert route (next) needs the FAILURE REASON to render "missing keys" vs
"host cert rejected" instead of collapsing it to a bare None. Only a genuine
SCSI transport fault still returns Err (abort). UnlockCtx gains an optional
ScanOptions (the cert route's host-cert source), and read_mkb_from_drive now
takes &mut dyn ScsiTransport — both prerequisites for the cert handshake to
become an external freemkv-unlock-aacs unlocker. Drive-prep + CSS callers fold
the new outcome; no behavior change.
This commit is contained in:
Matthew Jackson
2026-06-29 17:18:11 -07:00
parent 326d17c2f4
commit ab8f09645f
5 changed files with 130 additions and 75 deletions
+22 -6
View File
@@ -1482,12 +1482,28 @@ impl Disc {
let drive_id = session.drive_id.clone();
let css_ctx =
crate::unlock::UnlockCtx::new(&drive_id, crate::unlock::DiscKind::Css);
if let Err(e) = crate::unlock::route_unlock(session.scsi_mut(), &css_ctx) {
tracing::warn!(
target: "freemkv::scan",
error_code = e.code(),
"CSS bus-auth unlock failed; scrambled sectors may be unavailable"
);
match crate::unlock::route_unlock(session.scsi_mut(), &css_ctx) {
Ok(crate::unlock::UnlockRoute::Unlocked(..)) => {}
Ok(crate::unlock::UnlockRoute::Failed(e)) => {
tracing::warn!(
target: "freemkv::scan",
outcome = ?e,
"CSS bus-auth unlock failed; scrambled sectors may be unavailable"
);
}
Ok(crate::unlock::UnlockRoute::NoMatch) => {
tracing::warn!(
target: "freemkv::scan",
"no CSS unlocker registered; scrambled sectors may be unavailable"
);
}
Err(e) => {
tracing::warn!(
target: "freemkv::scan",
error_code = e.code(),
"CSS bus-auth unlock hit a transport fault; scrambled sectors may be unavailable"
);
}
}
// Size the crack's batch reads to THIS drive's per-command max
// (DVD ≈ 16; the USB bridge may be lower) — an over-large