mirror of
https://github.com/Dangoware/cd_reader.git
synced 2025-04-18 09:22:54 -05:00
Initally working!
This commit is contained in:
commit
20965bbafc
6 changed files with 418 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/target
|
109
Cargo.lock
generated
Normal file
109
Cargo.lock
generated
Normal file
|
@ -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"
|
9
Cargo.toml
Normal file
9
Cargo.toml
Normal file
|
@ -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"
|
157
src/constants.rs
Normal file
157
src/constants.rs
Normal file
|
@ -0,0 +1,157 @@
|
|||
//! Read more about the meanings of the below bytes here:
|
||||
//! <https://docs.kernel.org/userspace-api/ioctl/cdrom.html>
|
||||
|
||||
use num_traits::ToPrimitive;
|
||||
|
||||
/// CDROM ioctl byte, from <linux/cdrom.h>
|
||||
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
|
||||
}
|
65
src/main.rs
Normal file
65
src/main.rs
Normal file
|
@ -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]);
|
||||
}
|
77
src/structures.rs
Normal file
77
src/structures.rs
Normal file
|
@ -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,
|
||||
}
|
Loading…
Reference in a new issue