libfreemkv 0.4.1

Open source raw disc access library for optical drives
Documentation
//! Platform-specific implementations of raw disc access commands.
//!
//! Each chipset family (MT1959, Pioneer) implements the Platform trait.
//! The trait methods correspond to the drive's command handler table,
//! accessed via SCSI READ BUFFER with platform-specific mode and buffer ID.

pub mod mt1959;

use crate::error::Result;
use crate::scsi::ScsiTransport;

/// Platform trait — raw disc access commands implemented per chipset.
///
/// Command handlers accessed via READ BUFFER:
///   handler 0 = enable           — activate raw disc access mode
///   handler 1 = read_config      — read drive configuration block
///   handler 2 = read_register A  — read hardware register (offset A)
///   handler 3 = read_register B  — read hardware register (offset B)
///   handler 4 = calibrate        — build speed lookup table for disc
///   handler 5 = keepalive        — periodic ping to maintain session
///   handler 6 = status           — query current mode and feature flags
///   handler 7 = probe            — generic READ BUFFER with caller params
///   handler 8 = read_sectors     — raw sector read with speed control
///   handler 9 = timing           — timing calibration ping
pub trait Platform {
    /// Handler 0: Activate raw disc access mode.
    ///
    /// Sends the platform-specific READ BUFFER CDB and verifies
    /// the response signature bytes.
    fn unlock(&mut self, scsi: &mut dyn ScsiTransport) -> Result<()>;

    /// Handler 1: Read drive configuration block (1888 bytes).
    ///
    /// Performs a primary READ BUFFER for the configuration data,
    /// followed by a secondary 4-byte status read.
    fn read_config(&mut self, scsi: &mut dyn ScsiTransport) -> Result<Vec<u8>>;

    /// Handlers 2-3: Read hardware register.
    ///
    /// `index` selects which register offset from the profile to use.
    /// Returns 16 bytes of register data extracted from a 36-byte response.
    fn read_register(&mut self, scsi: &mut dyn ScsiTransport, index: u8) -> Result<[u8; 16]>;

    /// Handler 4: Speed calibration.
    ///
    /// Probes the disc surface via READ BUFFER sub-commands to build
    /// a 64-entry speed lookup table for optimal read performance.
    /// Issues SET CD SPEED at maximum after calibration completes.
    fn calibrate(&mut self, scsi: &mut dyn ScsiTransport) -> Result<()>;

    /// Handler 5: Keepalive ping.
    ///
    /// Periodic command to maintain the raw access session.
    fn keepalive(&mut self, scsi: &mut dyn ScsiTransport) -> Result<()>;

    /// Handler 6: Read drive status and feature flags.
    ///
    /// Verifies the response signature and returns 16 bytes of
    /// feature/status data.
    fn status(&mut self, scsi: &mut dyn ScsiTransport) -> Result<DriveStatus>;

    /// Handler 7: Generic probe with caller-provided parameters.
    ///
    /// Sends a READ BUFFER command with dynamic sub-command, address,
    /// and length. Used for disc structure reads and feature queries.
    fn probe(&mut self, scsi: &mut dyn ScsiTransport, sub_cmd: u8, address: u32, length: u32) -> Result<Vec<u8>>;

    /// Handler 8: Read raw disc sectors with speed optimization.
    ///
    /// Looks up the LBA in the speed table, issues SET CD SPEED,
    /// then performs a READ(10) with the raw read flag (0x08).
    fn read_sectors(&mut self, scsi: &mut dyn ScsiTransport, lba: u32, count: u16, buf: &mut [u8]) -> Result<usize>;

    /// Handler 9: Timing calibration ping.
    fn timing(&mut self, scsi: &mut dyn ScsiTransport) -> Result<()>;

    /// Check if raw disc access mode is currently enabled.
    fn is_unlocked(&self) -> bool;
}

/// Drive status information from the status command (handler 6).
#[derive(Debug, Clone)]
pub struct DriveStatus {
    pub unlocked: bool,
    pub features: [u8; 16],
}