cd-da-reader 1.0.0

CD-DA (audio CD) reading library
Documentation
use crate::{CdReaderError, ScsiError, ScsiOp};

#[repr(C)]
#[derive(Debug, Default, Clone, Copy)]
pub(super) struct MacScsiError {
    has_scsi_error: u8,
    scsi_status: u8,
    has_sense: u8,
    sense_key: u8,
    asc: u8,
    ascq: u8,
    exec_error: u32,
    task_status: u32,
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub(super) struct MacDriveInfo {
    pub(super) bsd_name: [libc::c_char; 64],
}

#[link(name = "macos_cd_shim", kind = "static")]
unsafe extern "C" {
    pub(super) fn cd_read_toc(
        fd: libc::c_int,
        out_buf: *mut *mut u8,
        out_len: *mut u32,
        out_err: *mut MacScsiError,
    ) -> bool;
    pub(super) fn cd_read_track_information(
        fd: libc::c_int,
        track_number: u8,
        out_buf: *mut *mut u8,
        out_len: *mut u32,
        out_err: *mut MacScsiError,
    ) -> bool;
    pub(super) fn read_cd_sectors(
        fd: libc::c_int,
        lba: u32,
        sectors: u32,
        format_id: u32,
        out_buf: *mut *mut u8,
        out_len: *mut u32,
        out_err: *mut MacScsiError,
    ) -> bool;
    pub(super) fn request_cd_read_speed(fd: libc::c_int, multiplier: libc::c_ushort) -> bool;
    pub(super) fn cd_free(pointer: *mut libc::c_void);
    pub(super) fn list_cd_drives(out_drives: *mut *mut MacDriveInfo, out_count: *mut u32) -> bool;
    pub(super) fn open_cd_raw_device(bsd_name: *const libc::c_char) -> libc::c_int;
}

pub(super) fn map_error(
    error: MacScsiError,
    op: ScsiOp,
    lba: Option<u32>,
    sectors: Option<u32>,
) -> CdReaderError {
    if error.has_scsi_error != 0 {
        return CdReaderError::Scsi(ScsiError {
            op,
            lba,
            sectors,
            scsi_status: error.scsi_status,
            sense_key: (error.has_sense != 0).then_some(error.sense_key),
            asc: (error.has_sense != 0).then_some(error.asc),
            ascq: (error.has_sense != 0).then_some(error.ascq),
        });
    }

    CdReaderError::Io(std::io::Error::other("macOS CD command failed"))
}