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; |
6 | pub const SNDRV_PCM_MMAP_OFFSET_STATUS: libc::c_uint = 0x80000000; |
7 | pub const SNDRV_PCM_MMAP_OFFSET_CONTROL: libc::c_uint = 0x81000000; |
8 | |
9 | pub const SNDRV_PCM_SYNC_PTR_HWSYNC: libc::c_uint = 1; |
10 | pub const SNDRV_PCM_SYNC_PTR_APPL: libc::c_uint = 2; |
11 | pub const SNDRV_PCM_SYNC_PTR_AVAIL_MIN: libc::c_uint = 4; |
12 | |
13 | // #[repr(C)] |
14 | #[allow (non_camel_case_types)] |
15 | pub type snd_pcm_state_t = libc::c_int; |
16 | |
17 | // #[repr(C)] |
18 | #[allow (non_camel_case_types)] |
19 | pub 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)] |
23 | pub type __kernel_off_t = libc::c_long; |
24 | |
25 | #[repr (C)] |
26 | #[derive (Copy, Clone)] |
27 | pub 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)] |
38 | pub 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)] |
45 | pub 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)] |
54 | pub 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)] |
61 | pub 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)] |
68 | pub 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" ))] |
76 | mod 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 | ))] |
132 | mod 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 | |
158 | pub(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 | |
178 | pub(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 | |
198 | pub fn pagesize() -> usize { |
199 | unsafe { libc::sysconf(name:libc::_SC_PAGESIZE) as usize } |
200 | } |
201 | |