1 /* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  */
5 
6 #ifndef CRAS_SHM_H_
7 #define CRAS_SHM_H_
8 
9 #include <assert.h>
10 #include <stdint.h>
11 #include <sys/mman.h>
12 #include <sys/param.h>
13 
14 #include "cras_types.h"
15 #include "cras_util.h"
16 
17 #define CRAS_NUM_SHM_BUFFERS 2U /* double buffer */
18 #define CRAS_SHM_BUFFERS_MASK (CRAS_NUM_SHM_BUFFERS - 1)
19 
20 /* Configuration of the shm area.
21  *
22  *  used_size - The size in bytes of the sample area being actively used.
23  *  frame_bytes - The size of each frame in bytes.
24  */
25 struct __attribute__((__packed__)) cras_audio_shm_config {
26 	uint32_t used_size;
27 	uint32_t frame_bytes;
28 };
29 
30 /* Structure containing stream metadata shared between client and server.
31  *
32  *  config - Size config data.  A copy of the config shared with clients.
33  *  read_buf_idx - index of the current buffer to read from (0 or 1 if double
34  *    buffered).
35  *  write_buf_idx - index of the current buffer to write to (0 or 1 if double
36  *    buffered).
37  *  read_offset - offset of the next sample to read (one per buffer).
38  *  write_offset - offset of the next sample to write (one per buffer).
39  *  write_in_progress - non-zero when a write is in progress.
40  *  volume_scaler - volume scaling factor (0.0-1.0).
41  *  muted - bool, true if stream should be muted.
42  *  num_overruns - Starting at 0 this is incremented very time data is over
43  *    written because too much accumulated before a read.
44  *  ts - For capture, the time stamp of the next sample at read_index.  For
45  *    playback, this is the time that the next sample written will be played.
46  *    This is only valid in audio callbacks.
47  *  buffer_offset - Offset of each buffer from start of samples area.
48  *                  Valid range: 0 <= buffer_offset <= shm->samples_info.length
49  */
50 struct __attribute__((__packed__)) cras_audio_shm_header {
51 	struct cras_audio_shm_config config;
52 	uint32_t read_buf_idx; /* use buffer A or B */
53 	uint32_t write_buf_idx;
54 	uint32_t read_offset[CRAS_NUM_SHM_BUFFERS];
55 	uint32_t write_offset[CRAS_NUM_SHM_BUFFERS];
56 	int32_t write_in_progress[CRAS_NUM_SHM_BUFFERS];
57 	float volume_scaler;
58 	int32_t mute;
59 	int32_t callback_pending;
60 	uint32_t num_overruns;
61 	struct cras_timespec ts;
62 	uint64_t buffer_offset[CRAS_NUM_SHM_BUFFERS];
63 };
64 
65 /* Returns the number of bytes needed to hold a cras_audio_shm_header. */
cras_shm_header_size()66 static inline uint32_t cras_shm_header_size()
67 {
68 	return sizeof(struct cras_audio_shm_header);
69 }
70 
71 /* Returns the number of bytes needed to hold the samples area for an audio
72  * shm with the given used_size */
cras_shm_calculate_samples_size(uint32_t used_size)73 static inline uint32_t cras_shm_calculate_samples_size(uint32_t used_size)
74 {
75 	return used_size * CRAS_NUM_SHM_BUFFERS;
76 }
77 
78 /* Holds identifiers for a shm segment. All valid cras_shm_info objects will
79  * have an fd and a length, and they may have the name of the shm file as well.
80  *
81  *  fd - File descriptor to access shm (shared between client/server).
82  *  name - Name of the shm area. May be empty.
83  *  length - Size of the shm region.
84  */
85 struct cras_shm_info {
86 	int fd;
87 	char name[NAME_MAX];
88 	size_t length;
89 };
90 
91 /* Initializes a cras_shm_info to be used as the backing shared memory for a
92  * cras_audio_shm.
93  *
94  * shm_name - the name of the shm area to create.
95  * length - the length of the shm area to create.
96  * info_out - pointer where the created cras_shm_info will be stored.
97  */
98 int cras_shm_info_init(const char *shm_name, uint32_t length,
99 		       struct cras_shm_info *info_out);
100 
101 /* Initializes a cras_shm_info to be used as the backing shared memory for a
102  * cras_audio_shm.
103  *
104  * fd - file descriptor for the shm to be used. fd must be closed after
105  *      calling this function.
106  * length - the size of the shm referenced by fd.
107  * info_out - pointer where the created cras_shm_info will be stored.
108  */
109 int cras_shm_info_init_with_fd(int fd, size_t length,
110 			       struct cras_shm_info *info_out);
111 
112 /* Cleans up the resources for a cras_shm_info returned from cras_shm_info_init.
113  *
114  * info - the cras_shm_info to cleanup.
115  */
116 void cras_shm_info_cleanup(struct cras_shm_info *info);
117 
118 /* Structure that holds the config for and a pointer to the audio shm header and
119  * samples area.
120  *
121  *  config - Size config data, kept separate so it can be checked.
122  *  header_info - fd, name, and length of shm containing header.
123  *  header - Shm region containing audio metadata
124  *  samples_info - fd, name, and length of shm containing samples.
125  *  samples - Shm region containing audio data.
126  */
127 struct cras_audio_shm {
128 	struct cras_audio_shm_config config;
129 	struct cras_shm_info header_info;
130 	struct cras_audio_shm_header *header;
131 	struct cras_shm_info samples_info;
132 	uint8_t *samples;
133 };
134 
135 /* Sets up a cras_audio_shm given info about the shared memory to use
136  *
137  * header_info - the underlying shm area to use for the header. The shm
138  *               will be managed by the created cras_audio_shm object.
139  *               The header_info parameter will be returned to an uninitialized
140  *               state, and the client need not call cras_shm_info_destroy.
141  * samples_info - the underlying shm area to use for the samples. The shm
142  *               will be managed by the created cras_audio_shm object.
143  *               The samples_info parameter will be returned to an
144  *               uninitialized state, and the client need not call
145  *               cras_shm_info_destroy.
146  * samples_prot - the mapping protections to use when mapping samples. Allowed
147  *                values are PROT_READ or PROT_WRITE.
148  * shm_out - pointer where the created cras_audio_shm will be stored.
149  *
150  * Returns 0 on success or a negative error code on failure.
151  */
152 int cras_audio_shm_create(struct cras_shm_info *header_info,
153 			  struct cras_shm_info *samples_info, int samples_prot,
154 			  struct cras_audio_shm **shm_out);
155 
156 /* Destroys a cras_audio_shm returned from cras_audio_shm_create.
157  *
158  * shm - the cras_audio_shm to destroy.
159  */
160 void cras_audio_shm_destroy(struct cras_audio_shm *shm);
161 
162 /* Limit a buffer offset to within the samples area size. */
163 static inline unsigned
cras_shm_get_checked_buffer_offset(const struct cras_audio_shm * shm,uint32_t buf_idx)164 cras_shm_get_checked_buffer_offset(const struct cras_audio_shm *shm,
165 				   uint32_t buf_idx)
166 {
167 	unsigned buffer_offset = shm->header->buffer_offset[buf_idx];
168 
169 	/* Cap buffer_offset at the length of the samples area */
170 	return MIN(buffer_offset, shm->samples_info.length);
171 }
172 
173 /* Get a pointer to the buffer at idx. */
cras_shm_buff_for_idx(const struct cras_audio_shm * shm,size_t idx)174 static inline uint8_t *cras_shm_buff_for_idx(const struct cras_audio_shm *shm,
175 					     size_t idx)
176 {
177 	assert_on_compile_is_power_of_2(CRAS_NUM_SHM_BUFFERS);
178 	idx = idx & CRAS_SHM_BUFFERS_MASK;
179 
180 	return shm->samples + cras_shm_get_checked_buffer_offset(shm, idx);
181 }
182 
183 /* Limit a read offset to within the buffer size. */
184 static inline unsigned
cras_shm_get_checked_read_offset(const struct cras_audio_shm * shm,uint32_t buf_idx)185 cras_shm_get_checked_read_offset(const struct cras_audio_shm *shm,
186 				 uint32_t buf_idx)
187 {
188 	unsigned buffer_offset =
189 		cras_shm_get_checked_buffer_offset(shm, buf_idx);
190 	unsigned read_offset = shm->header->read_offset[buf_idx];
191 
192 	/* The read_offset is allowed to be the total size, indicating that the
193 	 * buffer is full. If read pointer is invalid assume it is at the
194 	 * beginning. */
195 	if (read_offset > shm->config.used_size)
196 		return 0;
197 	if (buffer_offset + read_offset > shm->samples_info.length)
198 		return 0;
199 	return read_offset;
200 }
201 
202 /* Limit a write offset to within the buffer size. */
203 static inline unsigned
cras_shm_get_checked_write_offset(const struct cras_audio_shm * shm,uint32_t buf_idx)204 cras_shm_get_checked_write_offset(const struct cras_audio_shm *shm,
205 				  uint32_t buf_idx)
206 {
207 	unsigned write_offset = shm->header->write_offset[buf_idx];
208 	unsigned buffer_offset =
209 		cras_shm_get_checked_buffer_offset(shm, buf_idx);
210 
211 	/* The write_offset is allowed to be the total size, indicating that the
212 	 * buffer is full. If write pointer is past used size, assume it is at
213 	 * used size. */
214 	write_offset = MIN(write_offset, shm->config.used_size);
215 
216 	/* If the buffer offset plus the write offset overruns the samples area,
217 	 * return the longest valid write_offset */
218 	if (buffer_offset + write_offset > shm->samples_info.length)
219 		return shm->samples_info.length - buffer_offset;
220 	return write_offset;
221 }
222 
223 /* Get the number of frames readable in current read buffer */
224 static inline unsigned
cras_shm_get_curr_read_frames(const struct cras_audio_shm * shm)225 cras_shm_get_curr_read_frames(const struct cras_audio_shm *shm)
226 {
227 	unsigned buf_idx = shm->header->read_buf_idx & CRAS_SHM_BUFFERS_MASK;
228 	unsigned read_offset, write_offset;
229 
230 	read_offset = cras_shm_get_checked_read_offset(shm, buf_idx);
231 	write_offset = cras_shm_get_checked_write_offset(shm, buf_idx);
232 
233 	if (read_offset > write_offset)
234 		return 0;
235 	else
236 		return (write_offset - read_offset) / shm->config.frame_bytes;
237 }
238 
239 /* Get the base of the current read buffer. */
240 static inline uint8_t *
cras_shm_get_read_buffer_base(const struct cras_audio_shm * shm)241 cras_shm_get_read_buffer_base(const struct cras_audio_shm *shm)
242 {
243 	unsigned i = shm->header->read_buf_idx & CRAS_SHM_BUFFERS_MASK;
244 	return cras_shm_buff_for_idx(shm, i);
245 }
246 
247 /* Get the base of the current write buffer. */
248 static inline uint8_t *
cras_shm_get_write_buffer_base(const struct cras_audio_shm * shm)249 cras_shm_get_write_buffer_base(const struct cras_audio_shm *shm)
250 {
251 	unsigned i = shm->header->write_buf_idx & CRAS_SHM_BUFFERS_MASK;
252 
253 	return cras_shm_buff_for_idx(shm, i);
254 }
255 
256 /* Get a pointer to the next buffer to write */
257 static inline uint8_t *
cras_shm_get_writeable_frames(const struct cras_audio_shm * shm,unsigned limit_frames,unsigned * frames)258 cras_shm_get_writeable_frames(const struct cras_audio_shm *shm,
259 			      unsigned limit_frames, unsigned *frames)
260 {
261 	unsigned buf_idx = shm->header->write_buf_idx & CRAS_SHM_BUFFERS_MASK;
262 	unsigned write_offset;
263 	const unsigned frame_bytes = shm->config.frame_bytes;
264 	unsigned written;
265 
266 	write_offset = cras_shm_get_checked_write_offset(shm, buf_idx);
267 	written = write_offset / frame_bytes;
268 	if (frames) {
269 		if (limit_frames >= written)
270 			*frames = limit_frames - written;
271 		else
272 			*frames = 0;
273 	}
274 
275 	return cras_shm_buff_for_idx(shm, buf_idx) + write_offset;
276 }
277 
278 /* Get a pointer to the current read buffer plus an offset.  The offset might be
279  * in the next buffer. 'frames' is filled with the number of frames that can be
280  * copied from the returned buffer.
281  */
282 static inline uint8_t *
cras_shm_get_readable_frames(const struct cras_audio_shm * shm,size_t offset,size_t * frames)283 cras_shm_get_readable_frames(const struct cras_audio_shm *shm, size_t offset,
284 			     size_t *frames)
285 {
286 	unsigned buf_idx = shm->header->read_buf_idx & CRAS_SHM_BUFFERS_MASK;
287 	unsigned read_offset, write_offset, final_offset;
288 
289 	assert(frames != NULL);
290 
291 	read_offset = cras_shm_get_checked_read_offset(shm, buf_idx);
292 	write_offset = cras_shm_get_checked_write_offset(shm, buf_idx);
293 	final_offset = read_offset + offset * shm->config.frame_bytes;
294 	if (final_offset >= write_offset) {
295 		final_offset -= write_offset;
296 		assert_on_compile_is_power_of_2(CRAS_NUM_SHM_BUFFERS);
297 		buf_idx = (buf_idx + 1) & CRAS_SHM_BUFFERS_MASK;
298 		write_offset = cras_shm_get_checked_write_offset(shm, buf_idx);
299 	}
300 	if (final_offset >= write_offset) {
301 		/* Past end of samples. */
302 		*frames = 0;
303 		return NULL;
304 	}
305 	*frames = (write_offset - final_offset) / shm->config.frame_bytes;
306 	return cras_shm_buff_for_idx(shm, buf_idx) + final_offset;
307 }
308 
309 /* How many bytes are queued? */
cras_shm_get_bytes_queued(const struct cras_audio_shm * shm)310 static inline size_t cras_shm_get_bytes_queued(const struct cras_audio_shm *shm)
311 {
312 	size_t total, i;
313 	const unsigned used_size = shm->config.used_size;
314 
315 	total = 0;
316 	for (i = 0; i < CRAS_NUM_SHM_BUFFERS; i++) {
317 		unsigned read_offset, write_offset;
318 
319 		read_offset = MIN(shm->header->read_offset[i], used_size);
320 		write_offset = MIN(shm->header->write_offset[i], used_size);
321 
322 		if (write_offset > read_offset)
323 			total += write_offset - read_offset;
324 	}
325 	return total;
326 }
327 
328 /* How many frames are queued? */
cras_shm_get_frames(const struct cras_audio_shm * shm)329 static inline int cras_shm_get_frames(const struct cras_audio_shm *shm)
330 {
331 	size_t bytes;
332 
333 	bytes = cras_shm_get_bytes_queued(shm);
334 	if (bytes % shm->config.frame_bytes != 0)
335 		return -EIO;
336 	return bytes / shm->config.frame_bytes;
337 }
338 
339 /* How many frames in the current buffer? */
340 static inline size_t
cras_shm_get_frames_in_curr_buffer(const struct cras_audio_shm * shm)341 cras_shm_get_frames_in_curr_buffer(const struct cras_audio_shm *shm)
342 {
343 	size_t buf_idx = shm->header->read_buf_idx & CRAS_SHM_BUFFERS_MASK;
344 	unsigned read_offset, write_offset;
345 	const unsigned used_size = shm->config.used_size;
346 
347 	read_offset = MIN(shm->header->read_offset[buf_idx], used_size);
348 	write_offset = MIN(shm->header->write_offset[buf_idx], used_size);
349 
350 	if (write_offset <= read_offset)
351 		return 0;
352 
353 	return (write_offset - read_offset) / shm->config.frame_bytes;
354 }
355 
356 /* Return 1 if there is an empty buffer in the list. */
cras_shm_is_buffer_available(const struct cras_audio_shm * shm)357 static inline int cras_shm_is_buffer_available(const struct cras_audio_shm *shm)
358 {
359 	size_t buf_idx = shm->header->write_buf_idx & CRAS_SHM_BUFFERS_MASK;
360 
361 	return (shm->header->write_offset[buf_idx] == 0);
362 }
363 
364 /* How many are available to be written? */
365 static inline size_t
cras_shm_get_num_writeable(const struct cras_audio_shm * shm)366 cras_shm_get_num_writeable(const struct cras_audio_shm *shm)
367 {
368 	/* Not allowed to write to a buffer twice. */
369 	if (!cras_shm_is_buffer_available(shm))
370 		return 0;
371 
372 	return shm->config.used_size / shm->config.frame_bytes;
373 }
374 
375 /* Flags an overrun if writing would cause one and reset the write offset.
376  * Return 1 if overrun happens, otherwise return 0. */
cras_shm_check_write_overrun(struct cras_audio_shm * shm)377 static inline int cras_shm_check_write_overrun(struct cras_audio_shm *shm)
378 {
379 	int ret = 0;
380 	size_t write_buf_idx =
381 		shm->header->write_buf_idx & CRAS_SHM_BUFFERS_MASK;
382 
383 	if (!shm->header->write_in_progress[write_buf_idx]) {
384 		unsigned int used_size = shm->config.used_size;
385 
386 		if (shm->header->write_offset[write_buf_idx]) {
387 			shm->header->num_overruns++; /* Will over-write unread */
388 			ret = 1;
389 		}
390 
391 		memset(cras_shm_buff_for_idx(shm, write_buf_idx), 0, used_size);
392 
393 		shm->header->write_in_progress[write_buf_idx] = 1;
394 		shm->header->write_offset[write_buf_idx] = 0;
395 	}
396 	return ret;
397 }
398 
399 /* Increment the write pointer for the current buffer. */
cras_shm_buffer_written(struct cras_audio_shm * shm,size_t frames)400 static inline void cras_shm_buffer_written(struct cras_audio_shm *shm,
401 					   size_t frames)
402 {
403 	size_t buf_idx = shm->header->write_buf_idx & CRAS_SHM_BUFFERS_MASK;
404 
405 	if (frames == 0)
406 		return;
407 
408 	shm->header->write_offset[buf_idx] += frames * shm->config.frame_bytes;
409 	shm->header->read_offset[buf_idx] = 0;
410 }
411 
412 /* Returns the number of frames that have been written to the current buffer. */
413 static inline unsigned int
cras_shm_frames_written(const struct cras_audio_shm * shm)414 cras_shm_frames_written(const struct cras_audio_shm *shm)
415 {
416 	size_t buf_idx = shm->header->write_buf_idx & CRAS_SHM_BUFFERS_MASK;
417 
418 	return shm->header->write_offset[buf_idx] / shm->config.frame_bytes;
419 }
420 
421 /* Signals the writing to this buffer is complete and moves to the next one. */
cras_shm_buffer_write_complete(struct cras_audio_shm * shm)422 static inline void cras_shm_buffer_write_complete(struct cras_audio_shm *shm)
423 {
424 	size_t buf_idx = shm->header->write_buf_idx & CRAS_SHM_BUFFERS_MASK;
425 
426 	shm->header->write_in_progress[buf_idx] = 0;
427 
428 	assert_on_compile_is_power_of_2(CRAS_NUM_SHM_BUFFERS);
429 	buf_idx = (buf_idx + 1) & CRAS_SHM_BUFFERS_MASK;
430 	shm->header->write_buf_idx = buf_idx;
431 }
432 
433 /* Set the write pointer for the current buffer and complete the write. */
cras_shm_buffer_written_start(struct cras_audio_shm * shm,size_t frames)434 static inline void cras_shm_buffer_written_start(struct cras_audio_shm *shm,
435 						 size_t frames)
436 {
437 	size_t buf_idx = shm->header->write_buf_idx & CRAS_SHM_BUFFERS_MASK;
438 
439 	shm->header->write_offset[buf_idx] = frames * shm->config.frame_bytes;
440 	shm->header->read_offset[buf_idx] = 0;
441 	cras_shm_buffer_write_complete(shm);
442 }
443 
444 /* Increment the read pointer.  If it goes past the write pointer for this
445  * buffer, move to the next buffer. */
cras_shm_buffer_read(struct cras_audio_shm * shm,size_t frames)446 static inline void cras_shm_buffer_read(struct cras_audio_shm *shm,
447 					size_t frames)
448 {
449 	size_t buf_idx = shm->header->read_buf_idx & CRAS_SHM_BUFFERS_MASK;
450 	size_t remainder;
451 	struct cras_audio_shm_header *header = shm->header;
452 	struct cras_audio_shm_config *config = &shm->config;
453 
454 	if (frames == 0)
455 		return;
456 
457 	header->read_offset[buf_idx] += frames * config->frame_bytes;
458 	if (header->read_offset[buf_idx] >= header->write_offset[buf_idx]) {
459 		remainder = header->read_offset[buf_idx] -
460 			    header->write_offset[buf_idx];
461 		header->read_offset[buf_idx] = 0;
462 		header->write_offset[buf_idx] = 0;
463 		assert_on_compile_is_power_of_2(CRAS_NUM_SHM_BUFFERS);
464 		buf_idx = (buf_idx + 1) & CRAS_SHM_BUFFERS_MASK;
465 		if (remainder < header->write_offset[buf_idx]) {
466 			header->read_offset[buf_idx] = remainder;
467 		} else if (remainder) {
468 			/* Read all of this buffer too. */
469 			header->write_offset[buf_idx] = 0;
470 			buf_idx = (buf_idx + 1) & CRAS_SHM_BUFFERS_MASK;
471 		}
472 		header->read_buf_idx = buf_idx;
473 	}
474 }
475 
476 /* Read from the current buffer. This is similar to cras_shm_buffer_read(), but
477  * it doesn't check for the case we may read from two buffers. */
cras_shm_buffer_read_current(struct cras_audio_shm * shm,size_t frames)478 static inline void cras_shm_buffer_read_current(struct cras_audio_shm *shm,
479 						size_t frames)
480 {
481 	size_t buf_idx = shm->header->read_buf_idx & CRAS_SHM_BUFFERS_MASK;
482 	struct cras_audio_shm_header *header = shm->header;
483 	struct cras_audio_shm_config *config = &shm->config;
484 
485 	header->read_offset[buf_idx] += frames * config->frame_bytes;
486 	if (header->read_offset[buf_idx] >= header->write_offset[buf_idx]) {
487 		header->read_offset[buf_idx] = 0;
488 		header->write_offset[buf_idx] = 0;
489 		buf_idx = (buf_idx + 1) & CRAS_SHM_BUFFERS_MASK;
490 		header->read_buf_idx = buf_idx;
491 	}
492 }
493 
494 /* Sets the volume for the stream.  The volume level is a scaling factor that
495  * will be applied to the stream before mixing. */
cras_shm_set_volume_scaler(struct cras_audio_shm * shm,float volume_scaler)496 static inline void cras_shm_set_volume_scaler(struct cras_audio_shm *shm,
497 					      float volume_scaler)
498 {
499 	volume_scaler = MAX(volume_scaler, 0.0);
500 	shm->header->volume_scaler = MIN(volume_scaler, 1.0);
501 }
502 
503 /* Returns the volume of the stream(0.0-1.0). */
cras_shm_get_volume_scaler(const struct cras_audio_shm * shm)504 static inline float cras_shm_get_volume_scaler(const struct cras_audio_shm *shm)
505 {
506 	return shm->header->volume_scaler;
507 }
508 
509 /* Indicates that the stream should be muted/unmuted */
cras_shm_set_mute(struct cras_audio_shm * shm,size_t mute)510 static inline void cras_shm_set_mute(struct cras_audio_shm *shm, size_t mute)
511 {
512 	shm->header->mute = !!mute;
513 }
514 
515 /* Returns the mute state of the stream.  0 if not muted, non-zero if muted. */
cras_shm_get_mute(const struct cras_audio_shm * shm)516 static inline size_t cras_shm_get_mute(const struct cras_audio_shm *shm)
517 {
518 	return shm->header->mute;
519 }
520 
521 /* Sets the size of a frame in bytes. */
cras_shm_set_frame_bytes(struct cras_audio_shm * shm,unsigned frame_bytes)522 static inline void cras_shm_set_frame_bytes(struct cras_audio_shm *shm,
523 					    unsigned frame_bytes)
524 {
525 	shm->config.frame_bytes = frame_bytes;
526 	if (shm->header)
527 		shm->header->config.frame_bytes = frame_bytes;
528 }
529 
530 /* Returns the size of a frame in bytes. */
cras_shm_frame_bytes(const struct cras_audio_shm * shm)531 static inline unsigned cras_shm_frame_bytes(const struct cras_audio_shm *shm)
532 {
533 	return shm->config.frame_bytes;
534 }
535 
536 /* Sets if a callback is pending with the client. */
cras_shm_set_callback_pending(struct cras_audio_shm * shm,int pending)537 static inline void cras_shm_set_callback_pending(struct cras_audio_shm *shm,
538 						 int pending)
539 {
540 	shm->header->callback_pending = !!pending;
541 }
542 
543 /* Returns non-zero if a callback is pending for this shm region. */
cras_shm_callback_pending(const struct cras_audio_shm * shm)544 static inline int cras_shm_callback_pending(const struct cras_audio_shm *shm)
545 {
546 	return shm->header->callback_pending;
547 }
548 
549 /* Sets the starting offset of a buffer */
cras_shm_set_buffer_offset(struct cras_audio_shm * shm,uint32_t buf_idx,uint32_t offset)550 static inline void cras_shm_set_buffer_offset(struct cras_audio_shm *shm,
551 					      uint32_t buf_idx, uint32_t offset)
552 {
553 	shm->header->buffer_offset[buf_idx] = offset;
554 }
555 
556 /* Sets the used_size of the shm region.  This is the maximum number of bytes
557  * that is exchanged each time a buffer is passed from client to server.
558  *
559  * Also sets the buffer_offsets to default values based on the used size.
560  */
cras_shm_set_used_size(struct cras_audio_shm * shm,unsigned used_size)561 static inline void cras_shm_set_used_size(struct cras_audio_shm *shm,
562 					  unsigned used_size)
563 {
564 	uint32_t i;
565 
566 	shm->config.used_size = used_size;
567 	if (shm->header) {
568 		shm->header->config.used_size = used_size;
569 
570 		for (i = 0; i < CRAS_NUM_SHM_BUFFERS; i++)
571 			cras_shm_set_buffer_offset(shm, i, i * used_size);
572 	}
573 }
574 
575 /* Returns the used size of the shm region in bytes. */
cras_shm_used_size(const struct cras_audio_shm * shm)576 static inline unsigned cras_shm_used_size(const struct cras_audio_shm *shm)
577 {
578 	return shm->config.used_size;
579 }
580 
581 /* Returns the used size of the shm region in frames. */
cras_shm_used_frames(const struct cras_audio_shm * shm)582 static inline unsigned cras_shm_used_frames(const struct cras_audio_shm *shm)
583 {
584 	return shm->config.used_size / shm->config.frame_bytes;
585 }
586 
587 /* Returns the size of the samples shm region. */
cras_shm_samples_size(const struct cras_audio_shm * shm)588 static inline uint64_t cras_shm_samples_size(const struct cras_audio_shm *shm)
589 {
590 	return shm->samples_info.length;
591 }
592 
593 /* Gets the counter of over-runs. */
cras_shm_num_overruns(const struct cras_audio_shm * shm)594 static inline unsigned cras_shm_num_overruns(const struct cras_audio_shm *shm)
595 {
596 	return shm->header->num_overruns;
597 }
598 
599 /* Copy the config from the shm region to the local config.  Used by clients
600  * when initially setting up the region.
601  */
cras_shm_copy_shared_config(struct cras_audio_shm * shm)602 static inline void cras_shm_copy_shared_config(struct cras_audio_shm *shm)
603 {
604 	memcpy(&shm->config, &shm->header->config, sizeof(shm->config));
605 }
606 
607 /* Open a read/write shared memory area with the given name.
608  * Args:
609  *    name - Name of the shared-memory area.
610  *    size - Size of the shared-memory area.
611  * Returns:
612  *    >= 0 file descriptor value, or negative errno value on error.
613  */
614 int cras_shm_open_rw(const char *name, size_t size);
615 
616 /* Reopen an existing shared memory area read-only.
617  * Args:
618  *    name - Name of the shared-memory area.
619  *    fd - Existing file descriptor.
620  * Returns:
621  *    >= 0 new file descriptor value, or negative errno value on error.
622  */
623 int cras_shm_reopen_ro(const char *name, int fd);
624 
625 /* Close and delete a shared memory area.
626  * Args:
627  *    name - Name of the shared-memory area.
628  *    fd - Existing file descriptor.
629  * Returns:
630  *    >= 0 new file descriptor value, or negative errno value on error.
631  */
632 void cras_shm_close_unlink(const char *name, int fd);
633 
634 /*
635  * Configure shared memory for the system state.
636  * Args:
637  *    name - Name of the shared-memory area.
638  *    mmap_size - Amount of shared memor to map.
639  *    rw_fd_out - Filled with the RW fd for the shm region.
640  *    ro_fd_out - Filled with the RO fd for the shm region.
641  * Returns a pointer to the new shared memory region. Or NULL on error.
642  */
643 void *cras_shm_setup(const char *name, size_t mmap_size, int *rw_fd_out,
644 		     int *ro_fd_out);
645 
646 #ifdef CRAS_SELINUX
647 /*
648  * Wrapper around selinux_restorecon(). This is helpful in unit tests because
649  * we can mock out the selinux_restorecon() behaviour there. That is required
650  * because selinux_restorecon() would fail in the unit tests, since there
651  * is no file_contexts file.
652  * Args:
653  *    pathname - Name of the file on which to run restorecon
654  * Returns 0 on success, otherwise -1 and errno is set appropriately.
655  */
656 int cras_selinux_restorecon(const char *pathname);
657 #endif
658 
659 #endif /* CRAS_SHM_H_ */
660