xref: /third_party/alsa-lib/src/pcm/pcm_direct.h (revision d5ac70f0)
1d5ac70f0Sopenharmony_ci/*
2d5ac70f0Sopenharmony_ci *  PCM - Direct Stream Mixing
3d5ac70f0Sopenharmony_ci *  Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz>
4d5ac70f0Sopenharmony_ci *
5d5ac70f0Sopenharmony_ci *
6d5ac70f0Sopenharmony_ci *   This library is free software; you can redistribute it and/or modify
7d5ac70f0Sopenharmony_ci *   it under the terms of the GNU Lesser General Public License as
8d5ac70f0Sopenharmony_ci *   published by the Free Software Foundation; either version 2.1 of
9d5ac70f0Sopenharmony_ci *   the License, or (at your option) any later version.
10d5ac70f0Sopenharmony_ci *
11d5ac70f0Sopenharmony_ci *   This program is distributed in the hope that it will be useful,
12d5ac70f0Sopenharmony_ci *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13d5ac70f0Sopenharmony_ci *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14d5ac70f0Sopenharmony_ci *   GNU Lesser General Public License for more details.
15d5ac70f0Sopenharmony_ci *
16d5ac70f0Sopenharmony_ci *   You should have received a copy of the GNU Lesser General Public
17d5ac70f0Sopenharmony_ci *   License along with this library; if not, write to the Free Software
18d5ac70f0Sopenharmony_ci *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19d5ac70f0Sopenharmony_ci *
20d5ac70f0Sopenharmony_ci */
21d5ac70f0Sopenharmony_ci
22d5ac70f0Sopenharmony_ci#include "pcm_local.h"
23d5ac70f0Sopenharmony_ci#include "../timer/timer_local.h"
24d5ac70f0Sopenharmony_ci
25d5ac70f0Sopenharmony_ci#define DIRECT_IPC_SEMS         1
26d5ac70f0Sopenharmony_ci#define DIRECT_IPC_SEM_CLIENT   0
27d5ac70f0Sopenharmony_ci/* Seconds representing in Milli seconds */
28d5ac70f0Sopenharmony_ci#define SEC_TO_MS               1000
29d5ac70f0Sopenharmony_ci/* slave_period time for low latency requirements in ms */
30d5ac70f0Sopenharmony_ci#define LOW_LATENCY_PERIOD_TIME 10
31d5ac70f0Sopenharmony_ci
32d5ac70f0Sopenharmony_ci
33d5ac70f0Sopenharmony_citypedef void (mix_areas_t)(unsigned int size,
34d5ac70f0Sopenharmony_ci			   volatile void *dst, void *src,
35d5ac70f0Sopenharmony_ci			   volatile signed int *sum, size_t dst_step,
36d5ac70f0Sopenharmony_ci			   size_t src_step, size_t sum_step);
37d5ac70f0Sopenharmony_ci
38d5ac70f0Sopenharmony_citypedef void (mix_areas_16_t)(unsigned int size,
39d5ac70f0Sopenharmony_ci			      volatile signed short *dst, signed short *src,
40d5ac70f0Sopenharmony_ci			      volatile signed int *sum, size_t dst_step,
41d5ac70f0Sopenharmony_ci			      size_t src_step, size_t sum_step);
42d5ac70f0Sopenharmony_ci
43d5ac70f0Sopenharmony_citypedef void (mix_areas_32_t)(unsigned int size,
44d5ac70f0Sopenharmony_ci			      volatile signed int *dst, signed int *src,
45d5ac70f0Sopenharmony_ci			      volatile signed int *sum, size_t dst_step,
46d5ac70f0Sopenharmony_ci			      size_t src_step, size_t sum_step);
47d5ac70f0Sopenharmony_ci
48d5ac70f0Sopenharmony_citypedef void (mix_areas_24_t)(unsigned int size,
49d5ac70f0Sopenharmony_ci			      volatile unsigned char *dst, unsigned char *src,
50d5ac70f0Sopenharmony_ci			      volatile signed int *sum, size_t dst_step,
51d5ac70f0Sopenharmony_ci			      size_t src_step, size_t sum_step);
52d5ac70f0Sopenharmony_ci
53d5ac70f0Sopenharmony_citypedef void (mix_areas_u8_t)(unsigned int size,
54d5ac70f0Sopenharmony_ci			      volatile unsigned char *dst, unsigned char *src,
55d5ac70f0Sopenharmony_ci			      volatile signed int *sum, size_t dst_step,
56d5ac70f0Sopenharmony_ci			      size_t src_step, size_t sum_step);
57d5ac70f0Sopenharmony_ci
58d5ac70f0Sopenharmony_citypedef enum snd_pcm_direct_hw_ptr_alignment {
59d5ac70f0Sopenharmony_ci	SND_PCM_HW_PTR_ALIGNMENT_NO = 0,	/* use the hw_ptr as is and do no rounding */
60d5ac70f0Sopenharmony_ci	SND_PCM_HW_PTR_ALIGNMENT_ROUNDUP = 1,	/* round the slave_appl_ptr up to slave_period */
61d5ac70f0Sopenharmony_ci	SND_PCM_HW_PTR_ALIGNMENT_ROUNDDOWN = 2,	/* round slave_hw_ptr and slave_appl_ptr down to slave_period */
62d5ac70f0Sopenharmony_ci	SND_PCM_HW_PTR_ALIGNMENT_AUTO = 3	/* automatic selection */
63d5ac70f0Sopenharmony_ci} snd_pcm_direct_hw_ptr_alignment_t;
64d5ac70f0Sopenharmony_ci
65d5ac70f0Sopenharmony_cistruct slave_params {
66d5ac70f0Sopenharmony_ci	snd_pcm_format_t format;
67d5ac70f0Sopenharmony_ci	int rate;
68d5ac70f0Sopenharmony_ci	int channels;
69d5ac70f0Sopenharmony_ci	int period_time;
70d5ac70f0Sopenharmony_ci	int buffer_time;
71d5ac70f0Sopenharmony_ci	snd_pcm_sframes_t period_size;
72d5ac70f0Sopenharmony_ci	snd_pcm_sframes_t buffer_size;
73d5ac70f0Sopenharmony_ci	unsigned int periods;
74d5ac70f0Sopenharmony_ci};
75d5ac70f0Sopenharmony_ci
76d5ac70f0Sopenharmony_ci/* shared among direct plugin clients - be careful to be 32/64bit compatible! */
77d5ac70f0Sopenharmony_citypedef struct {
78d5ac70f0Sopenharmony_ci	unsigned int magic;			/* magic number */
79d5ac70f0Sopenharmony_ci	char socket_name[256];			/* name of communication socket */
80d5ac70f0Sopenharmony_ci	snd_pcm_type_t type;			/* PCM type (currently only hw) */
81d5ac70f0Sopenharmony_ci	int use_server;
82d5ac70f0Sopenharmony_ci	struct {
83d5ac70f0Sopenharmony_ci		unsigned int format;
84d5ac70f0Sopenharmony_ci		snd_interval_t rate;
85d5ac70f0Sopenharmony_ci		snd_interval_t buffer_size;
86d5ac70f0Sopenharmony_ci		snd_interval_t buffer_time;
87d5ac70f0Sopenharmony_ci		snd_interval_t period_size;
88d5ac70f0Sopenharmony_ci		snd_interval_t period_time;
89d5ac70f0Sopenharmony_ci		snd_interval_t periods;
90d5ac70f0Sopenharmony_ci	} hw;
91d5ac70f0Sopenharmony_ci	struct {
92d5ac70f0Sopenharmony_ci		/* copied to slave PCMs */
93d5ac70f0Sopenharmony_ci		snd_pcm_access_t access;
94d5ac70f0Sopenharmony_ci		snd_pcm_format_t format;
95d5ac70f0Sopenharmony_ci		snd_pcm_subformat_t subformat;
96d5ac70f0Sopenharmony_ci		unsigned int channels;
97d5ac70f0Sopenharmony_ci		unsigned int rate;
98d5ac70f0Sopenharmony_ci		unsigned int period_size;
99d5ac70f0Sopenharmony_ci		unsigned int period_time;
100d5ac70f0Sopenharmony_ci		snd_interval_t periods;
101d5ac70f0Sopenharmony_ci		snd_pcm_tstamp_t tstamp_mode;
102d5ac70f0Sopenharmony_ci		snd_pcm_tstamp_type_t tstamp_type;
103d5ac70f0Sopenharmony_ci		unsigned int period_step;
104d5ac70f0Sopenharmony_ci		unsigned int sleep_min; /* not used */
105d5ac70f0Sopenharmony_ci		unsigned int avail_min;
106d5ac70f0Sopenharmony_ci		unsigned int start_threshold;
107d5ac70f0Sopenharmony_ci		unsigned int stop_threshold;
108d5ac70f0Sopenharmony_ci		unsigned int silence_threshold;
109d5ac70f0Sopenharmony_ci		unsigned int silence_size;
110d5ac70f0Sopenharmony_ci		unsigned int recoveries;	/* no of executed recoveries on slave*/
111d5ac70f0Sopenharmony_ci		unsigned long long boundary;
112d5ac70f0Sopenharmony_ci		unsigned int info;
113d5ac70f0Sopenharmony_ci		unsigned int msbits;
114d5ac70f0Sopenharmony_ci		unsigned int rate_num;
115d5ac70f0Sopenharmony_ci		unsigned int rate_den;
116d5ac70f0Sopenharmony_ci		unsigned int hw_flags;
117d5ac70f0Sopenharmony_ci		unsigned int fifo_size;
118d5ac70f0Sopenharmony_ci		unsigned int buffer_size;
119d5ac70f0Sopenharmony_ci		snd_interval_t buffer_time;
120d5ac70f0Sopenharmony_ci		unsigned int sample_bits;
121d5ac70f0Sopenharmony_ci		unsigned int frame_bits;
122d5ac70f0Sopenharmony_ci	} s;
123d5ac70f0Sopenharmony_ci	union {
124d5ac70f0Sopenharmony_ci		struct {
125d5ac70f0Sopenharmony_ci			unsigned long long chn_mask;
126d5ac70f0Sopenharmony_ci		} dshare;
127d5ac70f0Sopenharmony_ci	} u;
128d5ac70f0Sopenharmony_ci} snd_pcm_direct_share_t;
129d5ac70f0Sopenharmony_ci
130d5ac70f0Sopenharmony_citypedef struct snd_pcm_direct snd_pcm_direct_t;
131d5ac70f0Sopenharmony_ci
132d5ac70f0Sopenharmony_cistruct snd_pcm_direct {
133d5ac70f0Sopenharmony_ci	snd_pcm_type_t type;		/* type (dmix, dsnoop, dshare) */
134d5ac70f0Sopenharmony_ci	key_t ipc_key;			/* IPC key for semaphore and memory */
135d5ac70f0Sopenharmony_ci	mode_t ipc_perm;		/* IPC socket permissions */
136d5ac70f0Sopenharmony_ci	int ipc_gid;			/* IPC socket gid */
137d5ac70f0Sopenharmony_ci	int semid;			/* IPC global semaphore identification */
138d5ac70f0Sopenharmony_ci	int locked[DIRECT_IPC_SEMS];	/* local lock counter */
139d5ac70f0Sopenharmony_ci	int shmid;			/* IPC global shared memory identification */
140d5ac70f0Sopenharmony_ci	snd_pcm_direct_share_t *shmptr;	/* pointer to shared memory area */
141d5ac70f0Sopenharmony_ci	snd_pcm_t *spcm; 		/* slave PCM handle */
142d5ac70f0Sopenharmony_ci	snd_pcm_uframes_t appl_ptr;
143d5ac70f0Sopenharmony_ci	snd_pcm_uframes_t last_appl_ptr;
144d5ac70f0Sopenharmony_ci	snd_pcm_uframes_t hw_ptr;
145d5ac70f0Sopenharmony_ci	snd_pcm_uframes_t avail_max;
146d5ac70f0Sopenharmony_ci	snd_pcm_uframes_t slave_appl_ptr;
147d5ac70f0Sopenharmony_ci	snd_pcm_uframes_t slave_hw_ptr;
148d5ac70f0Sopenharmony_ci	snd_pcm_uframes_t slave_period_size;
149d5ac70f0Sopenharmony_ci	snd_pcm_uframes_t slave_buffer_size;
150d5ac70f0Sopenharmony_ci	snd_pcm_uframes_t slave_boundary;
151d5ac70f0Sopenharmony_ci	int (*sync_ptr)(snd_pcm_t *pcm);
152d5ac70f0Sopenharmony_ci	snd_pcm_state_t state;
153d5ac70f0Sopenharmony_ci	snd_htimestamp_t trigger_tstamp;
154d5ac70f0Sopenharmony_ci	snd_htimestamp_t update_tstamp;
155d5ac70f0Sopenharmony_ci	int server, client;
156d5ac70f0Sopenharmony_ci	int comm_fd;			/* communication file descriptor (socket) */
157d5ac70f0Sopenharmony_ci	int hw_fd;			/* hardware file descriptor */
158d5ac70f0Sopenharmony_ci	struct pollfd timer_fd;
159d5ac70f0Sopenharmony_ci	int poll_fd;
160d5ac70f0Sopenharmony_ci	int tread: 1;
161d5ac70f0Sopenharmony_ci	int timer_need_poll: 1;
162d5ac70f0Sopenharmony_ci	unsigned int timer_events;
163d5ac70f0Sopenharmony_ci	unsigned int timer_ticks;
164d5ac70f0Sopenharmony_ci	int server_fd;
165d5ac70f0Sopenharmony_ci	pid_t server_pid;
166d5ac70f0Sopenharmony_ci	snd_timer_t *timer; 		/* timer used as poll_fd */
167d5ac70f0Sopenharmony_ci	int interleaved;	 	/* we have interleaved buffer */
168d5ac70f0Sopenharmony_ci	int slowptr;			/* use slow but more precise ptr updates */
169d5ac70f0Sopenharmony_ci	int max_periods;		/* max periods (-1 = fixed periods, 0 = max buffer size) */
170d5ac70f0Sopenharmony_ci	int var_periodsize;		/* allow variable period size if max_periods is != -1*/
171d5ac70f0Sopenharmony_ci	unsigned int channels;		/* client's channels */
172d5ac70f0Sopenharmony_ci	unsigned int *bindings;
173d5ac70f0Sopenharmony_ci	unsigned int recoveries;	/* mirror of executed recoveries on slave */
174d5ac70f0Sopenharmony_ci	int direct_memory_access;	/* use arch-optimized buffer RW */
175d5ac70f0Sopenharmony_ci	snd_pcm_direct_hw_ptr_alignment_t hw_ptr_alignment;
176d5ac70f0Sopenharmony_ci	int tstamp_type;		/* cached from conf, can be -1(default) on top of real types */
177d5ac70f0Sopenharmony_ci	union {
178d5ac70f0Sopenharmony_ci		struct {
179d5ac70f0Sopenharmony_ci			int shmid_sum;			/* IPC global sum ring buffer memory identification */
180d5ac70f0Sopenharmony_ci			signed int *sum_buffer;		/* shared sum buffer */
181d5ac70f0Sopenharmony_ci			mix_areas_16_t *mix_areas_16;
182d5ac70f0Sopenharmony_ci			mix_areas_32_t *mix_areas_32;
183d5ac70f0Sopenharmony_ci			mix_areas_24_t *mix_areas_24;
184d5ac70f0Sopenharmony_ci			mix_areas_u8_t *mix_areas_u8;
185d5ac70f0Sopenharmony_ci			mix_areas_16_t *remix_areas_16;
186d5ac70f0Sopenharmony_ci			mix_areas_32_t *remix_areas_32;
187d5ac70f0Sopenharmony_ci			mix_areas_24_t *remix_areas_24;
188d5ac70f0Sopenharmony_ci			mix_areas_u8_t *remix_areas_u8;
189d5ac70f0Sopenharmony_ci			unsigned int use_sem;
190d5ac70f0Sopenharmony_ci		} dmix;
191d5ac70f0Sopenharmony_ci		struct {
192d5ac70f0Sopenharmony_ci			unsigned long long chn_mask;
193d5ac70f0Sopenharmony_ci		} dshare;
194d5ac70f0Sopenharmony_ci	} u;
195d5ac70f0Sopenharmony_ci	void (*server_free)(snd_pcm_direct_t *direct);
196d5ac70f0Sopenharmony_ci};
197d5ac70f0Sopenharmony_ci
198d5ac70f0Sopenharmony_ci/* make local functions really local */
199d5ac70f0Sopenharmony_ci#define snd_pcm_direct_semaphore_create_or_connect \
200d5ac70f0Sopenharmony_ci	snd1_pcm_direct_semaphore_create_or_connect
201d5ac70f0Sopenharmony_ci#define snd_pcm_direct_shm_create_or_connect \
202d5ac70f0Sopenharmony_ci	snd1_pcm_direct_shm_create_or_connect
203d5ac70f0Sopenharmony_ci#define snd_pcm_direct_shm_discard \
204d5ac70f0Sopenharmony_ci	snd1_pcm_direct_shm_discard
205d5ac70f0Sopenharmony_ci#define snd_pcm_direct_server_create \
206d5ac70f0Sopenharmony_ci	snd1_pcm_direct_server_create
207d5ac70f0Sopenharmony_ci#define snd_pcm_direct_server_discard \
208d5ac70f0Sopenharmony_ci	snd1_pcm_direct_server_discard
209d5ac70f0Sopenharmony_ci#define snd_pcm_direct_client_connect \
210d5ac70f0Sopenharmony_ci	snd1_pcm_direct_client_connect
211d5ac70f0Sopenharmony_ci#define snd_pcm_direct_client_discard \
212d5ac70f0Sopenharmony_ci	snd1_pcm_direct_client_discard
213d5ac70f0Sopenharmony_ci#define snd_pcm_direct_initialize_slave \
214d5ac70f0Sopenharmony_ci	snd1_pcm_direct_initialize_slave
215d5ac70f0Sopenharmony_ci#define snd_pcm_direct_initialize_secondary_slave \
216d5ac70f0Sopenharmony_ci	snd1_pcm_direct_initialize_secondary_slave
217d5ac70f0Sopenharmony_ci#define snd_pcm_direct_initialize_poll_fd \
218d5ac70f0Sopenharmony_ci	snd1_pcm_direct_initialize_poll_fd
219d5ac70f0Sopenharmony_ci#define snd_pcm_direct_check_interleave \
220d5ac70f0Sopenharmony_ci	snd1_pcm_direct_check_interleave
221d5ac70f0Sopenharmony_ci#define snd_pcm_direct_parse_bindings \
222d5ac70f0Sopenharmony_ci	snd1_pcm_direct_parse_bindings
223d5ac70f0Sopenharmony_ci#define snd_pcm_direct_nonblock \
224d5ac70f0Sopenharmony_ci	snd1_pcm_direct_nonblock
225d5ac70f0Sopenharmony_ci#define snd_pcm_direct_async \
226d5ac70f0Sopenharmony_ci	snd1_pcm_direct_async
227d5ac70f0Sopenharmony_ci#define snd_pcm_direct_poll_descriptors \
228d5ac70f0Sopenharmony_ci	snd1_pcm_direct_poll_descriptors
229d5ac70f0Sopenharmony_ci#define snd_pcm_direct_poll_revents \
230d5ac70f0Sopenharmony_ci	snd1_pcm_direct_poll_revents
231d5ac70f0Sopenharmony_ci#define snd_pcm_direct_info \
232d5ac70f0Sopenharmony_ci	snd1_pcm_direct_info
233d5ac70f0Sopenharmony_ci#define snd_pcm_direct_hw_refine \
234d5ac70f0Sopenharmony_ci	snd1_pcm_direct_hw_refine
235d5ac70f0Sopenharmony_ci#define snd_pcm_direct_hw_params \
236d5ac70f0Sopenharmony_ci	snd1_pcm_direct_hw_params
237d5ac70f0Sopenharmony_ci#define snd_pcm_direct_hw_free \
238d5ac70f0Sopenharmony_ci	snd1_pcm_direct_hw_free
239d5ac70f0Sopenharmony_ci#define snd_pcm_direct_sw_params \
240d5ac70f0Sopenharmony_ci	snd1_pcm_direct_sw_params
241d5ac70f0Sopenharmony_ci#define snd_pcm_direct_channel_info \
242d5ac70f0Sopenharmony_ci	snd1_pcm_direct_channel_info
243d5ac70f0Sopenharmony_ci#define snd_pcm_direct_mmap \
244d5ac70f0Sopenharmony_ci	snd1_pcm_direct_mmap
245d5ac70f0Sopenharmony_ci#define snd_pcm_direct_munmap \
246d5ac70f0Sopenharmony_ci	snd1_pcm_direct_munmap
247d5ac70f0Sopenharmony_ci#define snd_pcm_direct_prepare \
248d5ac70f0Sopenharmony_ci	snd1_pcm_direct_prepare
249d5ac70f0Sopenharmony_ci#define snd_pcm_direct_resume \
250d5ac70f0Sopenharmony_ci	snd1_pcm_direct_resume
251d5ac70f0Sopenharmony_ci#define snd_pcm_direct_timer_stop \
252d5ac70f0Sopenharmony_ci	snd1_pcm_direct_timer_stop
253d5ac70f0Sopenharmony_ci#define snd_pcm_direct_clear_timer_queue \
254d5ac70f0Sopenharmony_ci	snd1_pcm_direct_clear_timer_queue
255d5ac70f0Sopenharmony_ci#define snd_pcm_direct_set_timer_params \
256d5ac70f0Sopenharmony_ci	snd1_pcm_direct_set_timer_params
257d5ac70f0Sopenharmony_ci#define snd_pcm_direct_open_secondary_client \
258d5ac70f0Sopenharmony_ci	snd1_pcm_direct_open_secondary_client
259d5ac70f0Sopenharmony_ci#define snd_pcm_direct_parse_open_conf \
260d5ac70f0Sopenharmony_ci	snd1_pcm_direct_parse_open_conf
261d5ac70f0Sopenharmony_ci#define snd_pcm_direct_query_chmaps \
262d5ac70f0Sopenharmony_ci	snd1_pcm_direct_query_chmaps
263d5ac70f0Sopenharmony_ci#define snd_pcm_direct_get_chmap \
264d5ac70f0Sopenharmony_ci	snd1_pcm_direct_get_chmap
265d5ac70f0Sopenharmony_ci#define snd_pcm_direct_set_chmap \
266d5ac70f0Sopenharmony_ci	snd1_pcm_direct_set_chmap
267d5ac70f0Sopenharmony_ci#define snd_pcm_direct_reset_slave_ptr \
268d5ac70f0Sopenharmony_ci	snd1_pcm_direct_reset_slave_ptr
269d5ac70f0Sopenharmony_ci#define snd_pcm_direct_check_xrun \
270d5ac70f0Sopenharmony_ci	snd1_pcm_direct_check_xrun
271d5ac70f0Sopenharmony_ci#define snd_pcm_direct_slave_recover \
272d5ac70f0Sopenharmony_ci	snd1_pcm_direct_slave_recover
273d5ac70f0Sopenharmony_ci
274d5ac70f0Sopenharmony_ciint snd_pcm_direct_semaphore_create_or_connect(snd_pcm_direct_t *dmix);
275d5ac70f0Sopenharmony_ci
276d5ac70f0Sopenharmony_cistatic inline int snd_pcm_direct_semaphore_discard(snd_pcm_direct_t *dmix)
277d5ac70f0Sopenharmony_ci{
278d5ac70f0Sopenharmony_ci	if (dmix->semid >= 0) {
279d5ac70f0Sopenharmony_ci		if (semctl(dmix->semid, 0, IPC_RMID, NULL) < 0)
280d5ac70f0Sopenharmony_ci			return -errno;
281d5ac70f0Sopenharmony_ci		dmix->semid = -1;
282d5ac70f0Sopenharmony_ci	}
283d5ac70f0Sopenharmony_ci	return 0;
284d5ac70f0Sopenharmony_ci}
285d5ac70f0Sopenharmony_ci
286d5ac70f0Sopenharmony_cistatic inline int snd_pcm_direct_semaphore_down(snd_pcm_direct_t *dmix, int sem_num)
287d5ac70f0Sopenharmony_ci{
288d5ac70f0Sopenharmony_ci	struct sembuf op[2] = { { sem_num, 0, 0 }, { sem_num, 1, SEM_UNDO } };
289d5ac70f0Sopenharmony_ci	int err = semop(dmix->semid, op, 2);
290d5ac70f0Sopenharmony_ci	if (err == 0)
291d5ac70f0Sopenharmony_ci		dmix->locked[sem_num]++;
292d5ac70f0Sopenharmony_ci	else if (err == -1)
293d5ac70f0Sopenharmony_ci		err = -errno;
294d5ac70f0Sopenharmony_ci	return err;
295d5ac70f0Sopenharmony_ci}
296d5ac70f0Sopenharmony_ci
297d5ac70f0Sopenharmony_cistatic inline int snd_pcm_direct_semaphore_up(snd_pcm_direct_t *dmix, int sem_num)
298d5ac70f0Sopenharmony_ci{
299d5ac70f0Sopenharmony_ci	struct sembuf op = { sem_num, -1, SEM_UNDO | IPC_NOWAIT };
300d5ac70f0Sopenharmony_ci	int err = semop(dmix->semid, &op, 1);
301d5ac70f0Sopenharmony_ci	if (err == 0)
302d5ac70f0Sopenharmony_ci		dmix->locked[sem_num]--;
303d5ac70f0Sopenharmony_ci	else if (err == -1)
304d5ac70f0Sopenharmony_ci		err = -errno;
305d5ac70f0Sopenharmony_ci	return err;
306d5ac70f0Sopenharmony_ci}
307d5ac70f0Sopenharmony_ci
308d5ac70f0Sopenharmony_cistatic inline int snd_pcm_direct_semaphore_final(snd_pcm_direct_t *dmix, int sem_num)
309d5ac70f0Sopenharmony_ci{
310d5ac70f0Sopenharmony_ci	if (dmix->locked[sem_num] != 1) {
311d5ac70f0Sopenharmony_ci		SNDMSG("invalid semaphore count to finalize %d: %d", sem_num, dmix->locked[sem_num]);
312d5ac70f0Sopenharmony_ci		return -EBUSY;
313d5ac70f0Sopenharmony_ci	}
314d5ac70f0Sopenharmony_ci	return snd_pcm_direct_semaphore_up(dmix, sem_num);
315d5ac70f0Sopenharmony_ci}
316d5ac70f0Sopenharmony_ci
317d5ac70f0Sopenharmony_ciint snd_pcm_direct_shm_create_or_connect(snd_pcm_direct_t *dmix);
318d5ac70f0Sopenharmony_ciint snd_pcm_direct_shm_discard(snd_pcm_direct_t *dmix);
319d5ac70f0Sopenharmony_ciint snd_pcm_direct_server_create(snd_pcm_direct_t *dmix);
320d5ac70f0Sopenharmony_ciint snd_pcm_direct_server_discard(snd_pcm_direct_t *dmix);
321d5ac70f0Sopenharmony_ciint snd_pcm_direct_client_connect(snd_pcm_direct_t *dmix);
322d5ac70f0Sopenharmony_ciint snd_pcm_direct_client_discard(snd_pcm_direct_t *dmix);
323d5ac70f0Sopenharmony_ciint snd_pcm_direct_initialize_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, struct slave_params *params);
324d5ac70f0Sopenharmony_ciint snd_pcm_direct_initialize_secondary_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, struct slave_params *params);
325d5ac70f0Sopenharmony_ciint snd_pcm_direct_initialize_poll_fd(snd_pcm_direct_t *dmix);
326d5ac70f0Sopenharmony_ciint snd_pcm_direct_check_interleave(snd_pcm_direct_t *dmix, snd_pcm_t *pcm);
327d5ac70f0Sopenharmony_ciint snd_pcm_direct_parse_bindings(snd_pcm_direct_t *dmix,
328d5ac70f0Sopenharmony_ci				  struct slave_params *params,
329d5ac70f0Sopenharmony_ci				  snd_config_t *cfg);
330d5ac70f0Sopenharmony_ciint snd_pcm_direct_nonblock(snd_pcm_t *pcm, int nonblock);
331d5ac70f0Sopenharmony_ciint snd_pcm_direct_async(snd_pcm_t *pcm, int sig, pid_t pid);
332d5ac70f0Sopenharmony_ciint snd_pcm_direct_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds,
333d5ac70f0Sopenharmony_ci				    unsigned int space);
334d5ac70f0Sopenharmony_ciint snd_pcm_direct_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
335d5ac70f0Sopenharmony_ciint snd_pcm_direct_info(snd_pcm_t *pcm, snd_pcm_info_t * info);
336d5ac70f0Sopenharmony_ciint snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
337d5ac70f0Sopenharmony_ciint snd_pcm_direct_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params);
338d5ac70f0Sopenharmony_ciint snd_pcm_direct_hw_free(snd_pcm_t *pcm);
339d5ac70f0Sopenharmony_ciint snd_pcm_direct_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params);
340d5ac70f0Sopenharmony_ciint snd_pcm_direct_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info);
341d5ac70f0Sopenharmony_ciint snd_pcm_direct_mmap(snd_pcm_t *pcm);
342d5ac70f0Sopenharmony_ciint snd_pcm_direct_munmap(snd_pcm_t *pcm);
343d5ac70f0Sopenharmony_ciint snd_pcm_direct_prepare(snd_pcm_t *pcm);
344d5ac70f0Sopenharmony_ciint snd_pcm_direct_resume(snd_pcm_t *pcm);
345d5ac70f0Sopenharmony_ciint snd_pcm_direct_timer_stop(snd_pcm_direct_t *dmix);
346d5ac70f0Sopenharmony_ciint snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix);
347d5ac70f0Sopenharmony_ciint snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix);
348d5ac70f0Sopenharmony_ciint snd_pcm_direct_open_secondary_client(snd_pcm_t **spcmp, snd_pcm_direct_t *dmix, const char *client_name);
349d5ac70f0Sopenharmony_ci
350d5ac70f0Sopenharmony_cisnd_pcm_chmap_query_t **snd_pcm_direct_query_chmaps(snd_pcm_t *pcm);
351d5ac70f0Sopenharmony_cisnd_pcm_chmap_t *snd_pcm_direct_get_chmap(snd_pcm_t *pcm);
352d5ac70f0Sopenharmony_ciint snd_pcm_direct_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map);
353d5ac70f0Sopenharmony_ciint snd_pcm_direct_slave_recover(snd_pcm_direct_t *direct);
354d5ac70f0Sopenharmony_ciint snd_pcm_direct_check_xrun(snd_pcm_direct_t *direct, snd_pcm_t *pcm);
355d5ac70f0Sopenharmony_ciint snd_timer_async(snd_timer_t *timer, int sig, pid_t pid);
356d5ac70f0Sopenharmony_cistruct timespec snd_pcm_hw_fast_tstamp(snd_pcm_t *pcm);
357d5ac70f0Sopenharmony_civoid snd_pcm_direct_reset_slave_ptr(snd_pcm_t *pcm, snd_pcm_direct_t *dmix, snd_pcm_uframes_t hw_ptr);
358d5ac70f0Sopenharmony_ci
359d5ac70f0Sopenharmony_cistruct snd_pcm_direct_open_conf {
360d5ac70f0Sopenharmony_ci	key_t ipc_key;
361d5ac70f0Sopenharmony_ci	mode_t ipc_perm;
362d5ac70f0Sopenharmony_ci	int ipc_gid;
363d5ac70f0Sopenharmony_ci	int slowptr;
364d5ac70f0Sopenharmony_ci	int max_periods;
365d5ac70f0Sopenharmony_ci	int var_periodsize;
366d5ac70f0Sopenharmony_ci	int direct_memory_access;
367d5ac70f0Sopenharmony_ci	snd_pcm_direct_hw_ptr_alignment_t hw_ptr_alignment;
368d5ac70f0Sopenharmony_ci	int tstamp_type;
369d5ac70f0Sopenharmony_ci	snd_config_t *slave;
370d5ac70f0Sopenharmony_ci	snd_config_t *bindings;
371d5ac70f0Sopenharmony_ci};
372d5ac70f0Sopenharmony_ci
373d5ac70f0Sopenharmony_ciint snd_pcm_direct_parse_open_conf(snd_config_t *root, snd_config_t *conf, int stream, struct snd_pcm_direct_open_conf *rec);
374d5ac70f0Sopenharmony_ci
375d5ac70f0Sopenharmony_ciint _snd_pcm_direct_new(snd_pcm_t **pcmp, snd_pcm_direct_t **_dmix, int type,
376d5ac70f0Sopenharmony_ci			const char *name, struct snd_pcm_direct_open_conf *opts,
377d5ac70f0Sopenharmony_ci			struct slave_params *params, snd_pcm_stream_t stream, int mode);
378