1//! Some definitions from the kernel headers
2
3#![allow(non_camel_case_types)]
4
5// const SNDRV_PCM_MMAP_OFFSET_DATA: c_uint = 0x00000000;
6pub const SNDRV_PCM_MMAP_OFFSET_STATUS: libc::c_uint = 0x80000000;
7pub const SNDRV_PCM_MMAP_OFFSET_CONTROL: libc::c_uint = 0x81000000;
8
9pub const SNDRV_PCM_SYNC_PTR_HWSYNC: libc::c_uint = 1;
10pub const SNDRV_PCM_SYNC_PTR_APPL: libc::c_uint = 2;
11pub const SNDRV_PCM_SYNC_PTR_AVAIL_MIN: libc::c_uint = 4;
12
13// #[repr(C)]
14#[allow(non_camel_case_types)]
15pub type snd_pcm_state_t = libc::c_int;
16
17// #[repr(C)]
18#[allow(non_camel_case_types)]
19pub type snd_pcm_uframes_t = libc::c_ulong;
20
21// I think?! Not sure how this will work with X32 ABI?!
22#[allow(non_camel_case_types)]
23pub type __kernel_off_t = libc::c_long;
24
25#[repr(C)]
26#[derive(Copy, Clone)]
27pub struct snd_pcm_mmap_status {
28 pub state: snd_pcm_state_t, /* RO: state - SNDRV_PCM_STATE_XXXX */
29 pub pad1: libc::c_int, /* Needed for 64 bit alignment */
30 pub hw_ptr: snd_pcm_uframes_t, /* RO: hw ptr (0...boundary-1) */
31 pub tstamp: libc::timespec, /* Timestamp */
32 pub suspended_state: snd_pcm_state_t, /* RO: suspended stream state */
33 pub audio_tstamp: libc::timespec, /* from sample counter or wall clock */
34}
35
36#[repr(C)]
37#[derive(Debug, Copy, Clone)]
38pub struct snd_pcm_mmap_control {
39 pub appl_ptr: snd_pcm_uframes_t, /* RW: appl ptr (0...boundary-1) */
40 pub avail_min: snd_pcm_uframes_t, /* RW: min available frames for wakeup */
41}
42
43#[repr(C)]
44#[derive(Debug)]
45pub struct snd_pcm_channel_info {
46 pub channel: libc::c_uint,
47 pub offset: __kernel_off_t, /* mmap offset */
48 pub first: libc::c_uint, /* offset to first sample in bits */
49 pub step: libc::c_uint, /* samples distance in bits */
50}
51
52#[repr(C)]
53#[derive(Copy, Clone)]
54pub union snd_pcm_mmap_status_r {
55 pub status: snd_pcm_mmap_status,
56 pub reserved: [libc::c_uchar; 64],
57}
58
59#[repr(C)]
60#[derive(Copy, Clone)]
61pub union snd_pcm_mmap_control_r {
62 pub control: snd_pcm_mmap_control,
63 pub reserved: [libc::c_uchar; 64],
64}
65
66#[repr(C)]
67#[derive(Copy, Clone)]
68pub struct snd_pcm_sync_ptr {
69 pub flags: libc::c_uint,
70 pub s: snd_pcm_mmap_status_r,
71 pub c: snd_pcm_mmap_control_r,
72}
73
74/// See <https://github.com/nix-rust/nix/blob/197f55b3ccbce3273bf6ce119d1a8541b5df5d66/src/sys/ioctl/linux.rs>
75#[cfg(any(target_os = "linux", target_os = "android"))]
76mod ioctl_helpers {
77 #[cfg(any(target_os = "android", target_env = "musl"))]
78 pub(super) type ioctl_num_type = libc::c_int;
79 #[cfg(not(any(target_os = "android", target_env = "musl")))]
80 pub(super) type ioctl_num_type = libc::c_ulong;
81
82 pub(super) const READ: ioctl_num_type = 2;
83 #[cfg(not(any(
84 target_arch = "mips",
85 target_arch = "mips32r6",
86 target_arch = "mips64",
87 target_arch = "mips64r6",
88 target_arch = "powerpc",
89 target_arch = "powerpc64",
90 target_arch = "sparc64"
91 )))]
92 pub(super) const WRITE: ioctl_num_type = 1;
93 #[cfg(any(
94 target_arch = "mips",
95 target_arch = "mips32r6",
96 target_arch = "mips64",
97 target_arch = "mips64r6",
98 target_arch = "powerpc",
99 target_arch = "powerpc64",
100 target_arch = "sparc64"
101 ))]
102 pub(super) const WRITE: ioctl_num_type = 4;
103
104 const NRSHIFT: ioctl_num_type = 0;
105 const TYPESHIFT: ioctl_num_type = NRSHIFT + 8 /* NRBITS */;
106 const SIZESHIFT: ioctl_num_type = TYPESHIFT + 8 /* TYPEBITS */;
107 const DIRSHIFT: ioctl_num_type = SIZESHIFT + 13 /* SIZEBITS */;
108
109 /// Replication of the [`nix::ioc!`](https://github.com/nix-rust/nix/blob/197f55b3ccbce3273bf6ce119d1a8541b5df5d66/src/sys/ioctl/linux.rs#L78-L96)
110 pub(super) const fn make_request(
111 dir: ioctl_num_type,
112 typ: u8,
113 nr: u8,
114 size: usize,
115 ) -> ioctl_num_type {
116 dir << DIRSHIFT
117 | (typ as ioctl_num_type) << TYPESHIFT
118 | (nr as ioctl_num_type) << NRSHIFT
119 | (size as ioctl_num_type) << SIZESHIFT
120 }
121}
122
123/// See <https://github.com/nix-rust/nix/blob/197f55b3ccbce3273bf6ce119d1a8541b5df5d66/src/sys/ioctl/bsd.rs>
124#[cfg(any(
125 target_os = "dragonfly",
126 target_os = "freebsd",
127 target_os = "netbsd",
128 target_os = "openbsd",
129 target_os = "solaris",
130 target_os = "illumos"
131))]
132mod ioctl_helpers {
133 #[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
134 pub(super) type ioctl_num_type = libc::c_ulong;
135 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
136 pub(super) type ioctl_num_type = libc::c_int;
137
138 #[allow(overflowing_literals)]
139 pub(super) const READ: ioctl_num_type = 0x4000_0000;
140 #[allow(overflowing_literals)]
141 pub(super) const WRITE: ioctl_num_type = 0x8000_0000;
142
143 const IOCPARM_MASK: ioctl_num_type = 0x1fff;
144
145 /// Replication of [`nix::ioc!`](https://github.com/nix-rust/nix/blob/197f55b3ccbce3273bf6ce119d1a8541b5df5d66/src/sys/ioctl/bsd.rs#L31-L42)
146 pub(super) const fn make_request(
147 dir: ioctl_num_type,
148 typ: u8,
149 nr: u8,
150 size: usize,
151 ) -> ioctl_num_type {
152 dir | ((size as ioctl_num_type) & IOCPARM_MASK) << 16
153 | (typ as ioctl_num_type) << 8
154 | nr as ioctl_num_type
155 }
156}
157
158pub(crate) unsafe fn sndrv_pcm_ioctl_channel_info(
159 fd: libc::c_int,
160 data: *mut snd_pcm_channel_info,
161) -> Result<(), crate::Error> {
162 const REQUEST: ioctl_helpers::ioctl_num_type = ioctl_helpers::make_request(
163 dir:ioctl_helpers::READ,
164 typ:b'A',
165 nr:0x32,
166 size:std::mem::size_of::<snd_pcm_channel_info>(),
167 );
168
169 unsafe {
170 if libc::ioctl(fd, REQUEST, data) == -1 {
171 Err(crate::Error::last(func:"SNDRV_PCM_IOCTL_CHANNEL_INFO"))
172 } else {
173 Ok(())
174 }
175 }
176}
177
178pub(crate) unsafe fn sndrv_pcm_ioctl_sync_ptr(
179 fd: libc::c_int,
180 data: *mut snd_pcm_sync_ptr,
181) -> Result<(), crate::Error> {
182 const REQUEST: ioctl_helpers::ioctl_num_type = ioctl_helpers::make_request(
183 dir:ioctl_helpers::READ | ioctl_helpers::WRITE,
184 typ:b'A',
185 nr:0x23,
186 size:std::mem::size_of::<snd_pcm_sync_ptr>(),
187 );
188
189 unsafe {
190 if libc::ioctl(fd, REQUEST, data) == -1 {
191 Err(crate::Error::last(func:"SNDRV_PCM_IOCTL_SYNC_PTR"))
192 } else {
193 Ok(())
194 }
195 }
196}
197
198pub fn pagesize() -> usize {
199 unsafe { libc::sysconf(name:libc::_SC_PAGESIZE) as usize }
200}
201