commit 20965bbafc9b3193c0cdb364898d4473b87046de Author: G2-Games Date: Mon Jan 27 15:28:35 2025 -0600 Initally working! diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..22bb23b --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,109 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "bitflags" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" + +[[package]] +name = "cd_read" +version = "0.1.0" +dependencies = [ + "nix", + "num-derive", + "num-traits", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "proc-macro2" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11cd88e12b17c6494200a9c1b683a04fcac9573ed74cd1b62aeb2727c5592243" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..f5b8b7c --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "cd_read" +version = "0.1.0" +edition = "2021" + +[dependencies] +nix = { version = "0.29.0", features = ["ioctl"] } +num-derive = "0.4.2" +num-traits = "0.2.19" diff --git a/src/constants.rs b/src/constants.rs new file mode 100644 index 0000000..889ba9a --- /dev/null +++ b/src/constants.rs @@ -0,0 +1,157 @@ +//! Read more about the meanings of the below bytes here: +//! + +use num_traits::ToPrimitive; + +/// CDROM ioctl byte, from +pub const IOC_BYTE: u8 = 0x53; + +#[repr(u8)] +#[derive(FromPrimitive, ToPrimitive)] +#[derive(Debug, Clone, Copy)] +pub enum Operations { + /// Pause Audio Operation + Pause = 0x01, + /// Resume paused Audio Operation + Resume = 0x02, + /// Play Audio MSF (struct cdrom_msf) + PlayMsf = 0x03, + /// Play Audio Track/index (struct cdrom_ti) + PlayTrackIndex = 0x04, + /// Read TOC header (struct cdrom_tochdr) + ReadTocHeader = 0x05, + /// Read TOC entry (struct cdrom_tocentry) + ReadTocEntry = 0x06, + /// Stop the cdrom drive + Stop = 0x07, + /// Start the cdrom drive + Start = 0x08, + /// Ejects the cdrom media + Eject = 0x09, + /// Control output volume (struct cdrom_volctrl) + VolumeControl = 0x0a, + /// Read subchannel data (struct cdrom_subchnl) + SubChannel = 0x0b, + /// Read CDROM mode 2 data (2336 Bytes) (struct cdrom_subchnl) + ReadMode2 = 0x0c, + /// Read CDROM mode 1 data (2048 Bytes) (struct cdrom_read) + ReadMode1 = 0x0d, + /// (struct cdrom_read_audio) + ReadAudio = 0x0e, + /// Enable (1)/Disable (0) auto-ejecting + EjectSoftware = 0x0f, + /// Obtain the start-of-last-session address of multi session disks (struct cdrom_multisession) + MultiSession = 0x10, + /// Obtain the "Universal Product Code" if available (struct cdrom_mcn) + GetMcn = 0x11, + /// Hard-reset the drive + Reset = 0x12, + /// Get the drive's volume setting (struct cdrom_volctrl) + VolumeRead = 0x13, + /// Read data in raw mode (2352 Bytes) (struct cdrom_read) + ReadRaw = 0x14, + + + // These ioctls are only used in aztcd.c and optcd.c + + /// Read data in cooked mode (???) + ReadCooked = 0x15, + /// Seek msf address + Seek = 0x16, + + + // This ioctl is only used by the scsi-cd driver. + // It is for playing audio in logtal block addresing mode. + + /// (struct cdrom_blk) + PlayBlock = 0x17, + + + // These ioctls are only used in optcd.c + + /// Read all 2646 bytes + ReadAll = 0x18, + + + // These ioctls were only in (now removed) ide-cd.c for controlling + // drive spindown time. They should be implemented in the + // Uniform driver, via generic packet commands, GPCMD_MODE_SELECT_10, + // GPCMD_MODE_SENSE_10 and the GPMODE_POWER_PAGE... + // -Erik + GetSpindown = 0x1d, + SetSpindown = 0x1e, + + // These ioctls are implemented through the uniform CD-ROM driver + // They _will_ be adopted by all CD-ROM drivers, when all the CD-ROM + // drivers are eventually ported to the uniform CD-ROM driver interface. + + /// Pendant of [`Operations::Eject`] + CloseTray = 0x19, + /// Set behavior options + SetOptions = 0x20, + /// Clear behavior options + ClearOptions = 0x21, + /// Set the CD-ROM speed + SelectSpeed = 0x22, + /// Select disc (for juke-boxes) + SelectDisk = 0x23, + /// Check is media changed + MediaChanged = 0x25, + /// Get tray position, etc + DriveStatus = 0x26, + /// Get disc type, etc + DiscStatus = 0x27, + /// Get number of slots + ChangerNslots = 0x28, + /// Lock or unlock door + LockDoor = 0x29, + /// Turn debug messages on/off + Debug = 0x30, + /// Get capabilities + GetCapability = 0x31, + + // Note that scsi/scsi_ioctl.h also uses 0x5382 - 0x5386. + // Future CDROM ioctls should be kept below 0x537F + + /// Set the audio buffer size + /// conflict with SCSI_IOCTL_GET_IDLUN + AudioBufferSize = 0x82, + + // DVD-ROM Specific ioctls + + /// Read structure + DvdReadStructure = 0x90, + /// Write structure + DvdWriteStructure = 0x91, + /// Authentication + DvdAuthenticate = 0x92, + + /// Send a packet to the drive + SendPacket = 0x93, + /// Get next writable block + NextWritable = 0x94, + /// Get last block written on disc + LastWritten = 0x95, + /// Get the timestamp of the last media change + TimedMediaChange = 0x96, +} + +impl Operations { + /// Turns the byte into its full IOCTL representation + pub fn to_full(&self) -> u64 { + let value = self.to_u8().unwrap(); + + ((IOC_BYTE as u64) << 8) + value as u64 + } +} + +/// Drive status possibilities returned by CDROM_DRIVE_STATUS ioctl +#[derive(FromPrimitive, ToPrimitive)] +#[derive(Debug, Clone, Copy)] +pub enum Status { + NoInfo = 0, + NoDisc = 1, + TrayOpen = 2, + DriveNotReady = 3, + DiscOK = 4 +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..21d2688 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,65 @@ +mod constants; +mod structures; + +use std::os::{fd::IntoRawFd, unix::fs::OpenOptionsExt}; +use std::fs::OpenOptions; + +use constants::{Operations, IOC_BYTE}; +use nix::{ioctl_none, ioctl_none_bad, ioctl_readwrite_bad, libc}; + +use nix::libc::c_int; +use num_traits::FromPrimitive as _; +use structures::{Addr, Msf0, ReadAudio}; + +#[macro_use] +extern crate num_derive; + +ioctl_none_bad!(cdrom_stop, Operations::to_full(&Operations::Stop)); +ioctl_none_bad!(cdrom_start, Operations::to_full(&Operations::Start)); +ioctl_none_bad!(cdrom_eject, Operations::to_full(&Operations::Eject)); +ioctl_none_bad!(cdrom_close_tray, Operations::to_full(&Operations::CloseTray)); +ioctl_none_bad!(cdrom_status, Operations::to_full(&Operations::DriveStatus)); +ioctl_readwrite_bad!(cdrom_read_audio, Operations::to_full(&Operations::ReadAudio), structures::ReadAudio); + +fn main() { + const FRAMES: i32 = 75; + const BYTES_PER_FRAME: i32 = 2352; + + let time = Msf0 { + minute: 2, + second: 45, + frame: 0, + }; + + let address = Addr { + msf: time, + }; + + let mut buff = [0u8; FRAMES as usize * BYTES_PER_FRAME as usize]; //Frames per second (75) * bytes per frame (2352) + + let mut ra = ReadAudio { + addr: address, + addr_format: 0x02, + nframes: FRAMES, + buf: buff.as_mut_ptr() + }; + + let cdrom = OpenOptions::new() + .read(true) + .custom_flags(libc::O_NONBLOCK | libc::O_RDONLY) + .open("/dev/sr0") + .unwrap(); + let cdrom_fd: c_int = cdrom.into_raw_fd(); + + unsafe { + let result = constants::Status::from_i32(cdrom_status(cdrom_fd).unwrap()).unwrap(); + dbg!(result); + //dbg!(cdrom_start(cdrom_fd).unwrap_or_default()); + + //std::thread::sleep(std::time::Duration::from_secs(1)); + + dbg!(cdrom_read_audio(cdrom_fd, std::ptr::addr_of_mut!(ra)).unwrap()); + } + + println!("{:02X?}", &buff[0..10]); +} diff --git a/src/structures.rs b/src/structures.rs new file mode 100644 index 0000000..9e9e2bf --- /dev/null +++ b/src/structures.rs @@ -0,0 +1,77 @@ +use std::ffi::c_int; + +/// Address in MSF format +#[repr(C)] +#[derive(Clone, Copy)] +pub struct Msf0 { + pub minute: u8, + pub second: u8, + pub frame: u8, +} + +/// Address in either MSF or logical format +#[repr(C)] +#[derive(Clone, Copy)] +pub union Addr { + pub lba: c_int, + pub msf: Msf0, +} + +/// This struct is used by [`crate::constants::PLAY_MSF`] +#[repr(C)] +#[derive(Clone, Copy)] +pub struct Msf { + /// Start minute + pub min0: u8, + /// Start second + pub sec0: u8, + /// Start frame + pub frame0: u8, + /// End minute + pub min1: u8, + /// End second + pub sec1: u8, + /// End frame + pub frame1: u8, +} + +#[repr(C)] +pub union RawResult { + pub cdrom_msf: Msf, + pub buffer: [u8; 2646], +} + +/// This struct is used by [`crate::constants::PLAY_TRACK_INDEX`] +struct TrackIndex { + /// Start track + trk0: u8, + /// Start index + ind0: u8, + /// End track + trk1: u8, + /// End index + ind1: u8, +} + +/// This struct is used by [`crate::constants::READ_TOC_HEADER`] +struct TocHeader { + trk0: u8, + trk1: u8, +} + +struct VolCtl { + +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct ReadAudio { + /// Frame address + pub addr: Addr, + /// CDROM_LBA or CDROM_MSF + pub addr_format: u8, + /// Number of 2352-byte-frames to read at once + pub nframes: i32, + /// Pointer to frame buffer (size: nframes*2352 bytes) + pub buf: *mut u8, +}