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 uint32_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 int cras_audio_shm_create(struct cras_shm_info *header_info,
151 struct cras_shm_info *samples_info, int samples_prot,
152 struct cras_audio_shm **shm_out);
153
154 /* Destroys a cras_audio_shm returned from cras_audio_shm_create.
155 *
156 * shm - the cras_audio_shm to destroy.
157 */
158 void cras_audio_shm_destroy(struct cras_audio_shm *shm);
159
160 /* Limit a buffer offset to within the samples area size. */
161 static inline unsigned
cras_shm_get_checked_buffer_offset(const struct cras_audio_shm * shm,uint32_t buf_idx)162 cras_shm_get_checked_buffer_offset(const struct cras_audio_shm *shm,
163 uint32_t buf_idx)
164 {
165 unsigned buffer_offset = shm->header->buffer_offset[buf_idx];
166
167 /* Cap buffer_offset at the length of the samples area */
168 return MIN(buffer_offset, shm->samples_info.length);
169 }
170
171 /* Get a pointer to the buffer at idx. */
cras_shm_buff_for_idx(const struct cras_audio_shm * shm,size_t idx)172 static inline uint8_t *cras_shm_buff_for_idx(const struct cras_audio_shm *shm,
173 size_t idx)
174 {
175 assert_on_compile_is_power_of_2(CRAS_NUM_SHM_BUFFERS);
176 idx = idx & CRAS_SHM_BUFFERS_MASK;
177
178 return shm->samples + cras_shm_get_checked_buffer_offset(shm, idx);
179 }
180
181 /* Limit a read offset to within the buffer size. */
182 static inline unsigned
cras_shm_get_checked_read_offset(const struct cras_audio_shm * shm,uint32_t buf_idx)183 cras_shm_get_checked_read_offset(const struct cras_audio_shm *shm,
184 uint32_t buf_idx)
185 {
186 unsigned buffer_offset =
187 cras_shm_get_checked_buffer_offset(shm, buf_idx);
188 unsigned read_offset = shm->header->read_offset[buf_idx];
189
190 /* The read_offset is allowed to be the total size, indicating that the
191 * buffer is full. If read pointer is invalid assume it is at the
192 * beginning. */
193 if (read_offset > shm->config.used_size)
194 return 0;
195 if (buffer_offset + read_offset > shm->samples_info.length)
196 return 0;
197 return read_offset;
198 }
199
200 /* Limit a write offset to within the buffer size. */
201 static inline unsigned
cras_shm_get_checked_write_offset(const struct cras_audio_shm * shm,uint32_t buf_idx)202 cras_shm_get_checked_write_offset(const struct cras_audio_shm *shm,
203 uint32_t buf_idx)
204 {
205 unsigned write_offset = shm->header->write_offset[buf_idx];
206 unsigned buffer_offset =
207 cras_shm_get_checked_buffer_offset(shm, buf_idx);
208
209 /* The write_offset is allowed to be the total size, indicating that the
210 * buffer is full. If write pointer is past used size, assume it is at
211 * used size. */
212 write_offset = MIN(write_offset, shm->config.used_size);
213
214 /* If the buffer offset plus the write offset overruns the samples area,
215 * return the longest valid write_offset */
216 if (buffer_offset + write_offset > shm->samples_info.length)
217 return shm->samples_info.length - buffer_offset;
218 return write_offset;
219 }
220
221 /* Get the number of frames readable in current read buffer */
222 static inline unsigned
cras_shm_get_curr_read_frames(const struct cras_audio_shm * shm)223 cras_shm_get_curr_read_frames(const struct cras_audio_shm *shm)
224 {
225 unsigned buf_idx = shm->header->read_buf_idx & CRAS_SHM_BUFFERS_MASK;
226 unsigned read_offset, write_offset;
227
228 read_offset = cras_shm_get_checked_read_offset(shm, buf_idx);
229 write_offset = cras_shm_get_checked_write_offset(shm, buf_idx);
230
231 if (read_offset > write_offset)
232 return 0;
233 else
234 return (write_offset - read_offset) / shm->config.frame_bytes;
235 }
236
237 /* Get the base of the current read buffer. */
238 static inline uint8_t *
cras_shm_get_read_buffer_base(const struct cras_audio_shm * shm)239 cras_shm_get_read_buffer_base(const struct cras_audio_shm *shm)
240 {
241 unsigned i = shm->header->read_buf_idx & CRAS_SHM_BUFFERS_MASK;
242 return cras_shm_buff_for_idx(shm, i);
243 }
244
245 /* Get the base of the current write buffer. */
246 static inline uint8_t *
cras_shm_get_write_buffer_base(const struct cras_audio_shm * shm)247 cras_shm_get_write_buffer_base(const struct cras_audio_shm *shm)
248 {
249 unsigned i = shm->header->write_buf_idx & CRAS_SHM_BUFFERS_MASK;
250
251 return cras_shm_buff_for_idx(shm, i);
252 }
253
254 /* Get a pointer to the next buffer to write */
255 static inline uint8_t *
cras_shm_get_writeable_frames(const struct cras_audio_shm * shm,unsigned limit_frames,unsigned * frames)256 cras_shm_get_writeable_frames(const struct cras_audio_shm *shm,
257 unsigned limit_frames, unsigned *frames)
258 {
259 unsigned buf_idx = shm->header->write_buf_idx & CRAS_SHM_BUFFERS_MASK;
260 unsigned write_offset;
261 const unsigned frame_bytes = shm->config.frame_bytes;
262 unsigned written;
263
264 write_offset = cras_shm_get_checked_write_offset(shm, buf_idx);
265 written = write_offset / frame_bytes;
266 if (frames) {
267 if (limit_frames >= written)
268 *frames = limit_frames - written;
269 else
270 *frames = 0;
271 }
272
273 return cras_shm_buff_for_idx(shm, buf_idx) + write_offset;
274 }
275
276 /* Get a pointer to the current read buffer plus an offset. The offset might be
277 * in the next buffer. 'frames' is filled with the number of frames that can be
278 * copied from the returned buffer.
279 */
280 static inline uint8_t *
cras_shm_get_readable_frames(const struct cras_audio_shm * shm,size_t offset,size_t * frames)281 cras_shm_get_readable_frames(const struct cras_audio_shm *shm, size_t offset,
282 size_t *frames)
283 {
284 unsigned buf_idx = shm->header->read_buf_idx & CRAS_SHM_BUFFERS_MASK;
285 unsigned read_offset, write_offset, final_offset;
286
287 assert(frames != NULL);
288
289 read_offset = cras_shm_get_checked_read_offset(shm, buf_idx);
290 write_offset = cras_shm_get_checked_write_offset(shm, buf_idx);
291 final_offset = read_offset + offset * shm->config.frame_bytes;
292 if (final_offset >= write_offset) {
293 final_offset -= write_offset;
294 assert_on_compile_is_power_of_2(CRAS_NUM_SHM_BUFFERS);
295 buf_idx = (buf_idx + 1) & CRAS_SHM_BUFFERS_MASK;
296 write_offset = cras_shm_get_checked_write_offset(shm, buf_idx);
297 }
298 if (final_offset >= write_offset) {
299 /* Past end of samples. */
300 *frames = 0;
301 return NULL;
302 }
303 *frames = (write_offset - final_offset) / shm->config.frame_bytes;
304 return cras_shm_buff_for_idx(shm, buf_idx) + final_offset;
305 }
306
307 /* How many bytes are queued? */
cras_shm_get_bytes_queued(const struct cras_audio_shm * shm)308 static inline size_t cras_shm_get_bytes_queued(const struct cras_audio_shm *shm)
309 {
310 size_t total, i;
311 const unsigned used_size = shm->config.used_size;
312
313 total = 0;
314 for (i = 0; i < CRAS_NUM_SHM_BUFFERS; i++) {
315 unsigned read_offset, write_offset;
316
317 read_offset = MIN(shm->header->read_offset[i], used_size);
318 write_offset = MIN(shm->header->write_offset[i], used_size);
319
320 if (write_offset > read_offset)
321 total += write_offset - read_offset;
322 }
323 return total;
324 }
325
326 /* How many frames are queued? */
cras_shm_get_frames(const struct cras_audio_shm * shm)327 static inline int cras_shm_get_frames(const struct cras_audio_shm *shm)
328 {
329 size_t bytes;
330
331 bytes = cras_shm_get_bytes_queued(shm);
332 if (bytes % shm->config.frame_bytes != 0)
333 return -EIO;
334 return bytes / shm->config.frame_bytes;
335 }
336
337 /* How many frames in the current buffer? */
338 static inline size_t
cras_shm_get_frames_in_curr_buffer(const struct cras_audio_shm * shm)339 cras_shm_get_frames_in_curr_buffer(const struct cras_audio_shm *shm)
340 {
341 size_t buf_idx = shm->header->read_buf_idx & CRAS_SHM_BUFFERS_MASK;
342 unsigned read_offset, write_offset;
343 const unsigned used_size = shm->config.used_size;
344
345 read_offset = MIN(shm->header->read_offset[buf_idx], used_size);
346 write_offset = MIN(shm->header->write_offset[buf_idx], used_size);
347
348 if (write_offset <= read_offset)
349 return 0;
350
351 return (write_offset - read_offset) / shm->config.frame_bytes;
352 }
353
354 /* Return 1 if there is an empty buffer in the list. */
cras_shm_is_buffer_available(const struct cras_audio_shm * shm)355 static inline int cras_shm_is_buffer_available(const struct cras_audio_shm *shm)
356 {
357 size_t buf_idx = shm->header->write_buf_idx & CRAS_SHM_BUFFERS_MASK;
358
359 return (shm->header->write_offset[buf_idx] == 0);
360 }
361
362 /* How many are available to be written? */
363 static inline size_t
cras_shm_get_num_writeable(const struct cras_audio_shm * shm)364 cras_shm_get_num_writeable(const struct cras_audio_shm *shm)
365 {
366 /* Not allowed to write to a buffer twice. */
367 if (!cras_shm_is_buffer_available(shm))
368 return 0;
369
370 return shm->config.used_size / shm->config.frame_bytes;
371 }
372
373 /* Flags an overrun if writing would cause one and reset the write offset.
374 * Return 1 if overrun happens, otherwise return 0. */
cras_shm_check_write_overrun(struct cras_audio_shm * shm)375 static inline int cras_shm_check_write_overrun(struct cras_audio_shm *shm)
376 {
377 int ret = 0;
378 size_t write_buf_idx =
379 shm->header->write_buf_idx & CRAS_SHM_BUFFERS_MASK;
380
381 if (!shm->header->write_in_progress[write_buf_idx]) {
382 unsigned int used_size = shm->config.used_size;
383
384 if (shm->header->write_offset[write_buf_idx]) {
385 shm->header->num_overruns++; /* Will over-write unread */
386 ret = 1;
387 }
388
389 memset(cras_shm_buff_for_idx(shm, write_buf_idx), 0, used_size);
390
391 shm->header->write_in_progress[write_buf_idx] = 1;
392 shm->header->write_offset[write_buf_idx] = 0;
393 }
394 return ret;
395 }
396
397 /* Increment the write pointer for the current buffer. */
cras_shm_buffer_written(struct cras_audio_shm * shm,size_t frames)398 static inline void cras_shm_buffer_written(struct cras_audio_shm *shm,
399 size_t frames)
400 {
401 size_t buf_idx = shm->header->write_buf_idx & CRAS_SHM_BUFFERS_MASK;
402
403 if (frames == 0)
404 return;
405
406 shm->header->write_offset[buf_idx] += frames * shm->config.frame_bytes;
407 shm->header->read_offset[buf_idx] = 0;
408 }
409
410 /* Returns the number of frames that have been written to the current buffer. */
411 static inline unsigned int
cras_shm_frames_written(const struct cras_audio_shm * shm)412 cras_shm_frames_written(const struct cras_audio_shm *shm)
413 {
414 size_t buf_idx = shm->header->write_buf_idx & CRAS_SHM_BUFFERS_MASK;
415
416 return shm->header->write_offset[buf_idx] / shm->config.frame_bytes;
417 }
418
419 /* Signals the writing to this buffer is complete and moves to the next one. */
cras_shm_buffer_write_complete(struct cras_audio_shm * shm)420 static inline void cras_shm_buffer_write_complete(struct cras_audio_shm *shm)
421 {
422 size_t buf_idx = shm->header->write_buf_idx & CRAS_SHM_BUFFERS_MASK;
423
424 shm->header->write_in_progress[buf_idx] = 0;
425
426 assert_on_compile_is_power_of_2(CRAS_NUM_SHM_BUFFERS);
427 buf_idx = (buf_idx + 1) & CRAS_SHM_BUFFERS_MASK;
428 shm->header->write_buf_idx = buf_idx;
429 }
430
431 /* 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)432 static inline void cras_shm_buffer_written_start(struct cras_audio_shm *shm,
433 size_t frames)
434 {
435 size_t buf_idx = shm->header->write_buf_idx & CRAS_SHM_BUFFERS_MASK;
436
437 shm->header->write_offset[buf_idx] = frames * shm->config.frame_bytes;
438 shm->header->read_offset[buf_idx] = 0;
439 cras_shm_buffer_write_complete(shm);
440 }
441
442 /* Increment the read pointer. If it goes past the write pointer for this
443 * buffer, move to the next buffer. */
cras_shm_buffer_read(struct cras_audio_shm * shm,size_t frames)444 static inline void cras_shm_buffer_read(struct cras_audio_shm *shm,
445 size_t frames)
446 {
447 size_t buf_idx = shm->header->read_buf_idx & CRAS_SHM_BUFFERS_MASK;
448 size_t remainder;
449 struct cras_audio_shm_header *header = shm->header;
450 struct cras_audio_shm_config *config = &shm->config;
451
452 if (frames == 0)
453 return;
454
455 header->read_offset[buf_idx] += frames * config->frame_bytes;
456 if (header->read_offset[buf_idx] >= header->write_offset[buf_idx]) {
457 remainder = header->read_offset[buf_idx] -
458 header->write_offset[buf_idx];
459 header->read_offset[buf_idx] = 0;
460 header->write_offset[buf_idx] = 0;
461 assert_on_compile_is_power_of_2(CRAS_NUM_SHM_BUFFERS);
462 buf_idx = (buf_idx + 1) & CRAS_SHM_BUFFERS_MASK;
463 if (remainder < header->write_offset[buf_idx]) {
464 header->read_offset[buf_idx] = remainder;
465 } else if (remainder) {
466 /* Read all of this buffer too. */
467 header->write_offset[buf_idx] = 0;
468 buf_idx = (buf_idx + 1) & CRAS_SHM_BUFFERS_MASK;
469 }
470 header->read_buf_idx = buf_idx;
471 }
472 }
473
474 /* Read from the current buffer. This is similar to cras_shm_buffer_read(), but
475 * 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)476 static inline void cras_shm_buffer_read_current(struct cras_audio_shm *shm,
477 size_t frames)
478 {
479 size_t buf_idx = shm->header->read_buf_idx & CRAS_SHM_BUFFERS_MASK;
480 struct cras_audio_shm_header *header = shm->header;
481 struct cras_audio_shm_config *config = &shm->config;
482
483 header->read_offset[buf_idx] += frames * config->frame_bytes;
484 if (header->read_offset[buf_idx] >= header->write_offset[buf_idx]) {
485 header->read_offset[buf_idx] = 0;
486 header->write_offset[buf_idx] = 0;
487 buf_idx = (buf_idx + 1) & CRAS_SHM_BUFFERS_MASK;
488 header->read_buf_idx = buf_idx;
489 }
490 }
491
492 /* Sets the volume for the stream. The volume level is a scaling factor that
493 * will be applied to the stream before mixing. */
cras_shm_set_volume_scaler(struct cras_audio_shm * shm,float volume_scaler)494 static inline void cras_shm_set_volume_scaler(struct cras_audio_shm *shm,
495 float volume_scaler)
496 {
497 volume_scaler = MAX(volume_scaler, 0.0);
498 shm->header->volume_scaler = MIN(volume_scaler, 1.0);
499 }
500
501 /* Returns the volume of the stream(0.0-1.0). */
cras_shm_get_volume_scaler(const struct cras_audio_shm * shm)502 static inline float cras_shm_get_volume_scaler(const struct cras_audio_shm *shm)
503 {
504 return shm->header->volume_scaler;
505 }
506
507 /* Indicates that the stream should be muted/unmuted */
cras_shm_set_mute(struct cras_audio_shm * shm,size_t mute)508 static inline void cras_shm_set_mute(struct cras_audio_shm *shm, size_t mute)
509 {
510 shm->header->mute = !!mute;
511 }
512
513 /* 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)514 static inline size_t cras_shm_get_mute(const struct cras_audio_shm *shm)
515 {
516 return shm->header->mute;
517 }
518
519 /* Sets the size of a frame in bytes. */
cras_shm_set_frame_bytes(struct cras_audio_shm * shm,unsigned frame_bytes)520 static inline void cras_shm_set_frame_bytes(struct cras_audio_shm *shm,
521 unsigned frame_bytes)
522 {
523 shm->config.frame_bytes = frame_bytes;
524 if (shm->header)
525 shm->header->config.frame_bytes = frame_bytes;
526 }
527
528 /* Returns the size of a frame in bytes. */
cras_shm_frame_bytes(const struct cras_audio_shm * shm)529 static inline unsigned cras_shm_frame_bytes(const struct cras_audio_shm *shm)
530 {
531 return shm->config.frame_bytes;
532 }
533
534 /* Sets if a callback is pending with the client. */
cras_shm_set_callback_pending(struct cras_audio_shm * shm,int pending)535 static inline void cras_shm_set_callback_pending(struct cras_audio_shm *shm,
536 int pending)
537 {
538 shm->header->callback_pending = !!pending;
539 }
540
541 /* Returns non-zero if a callback is pending for this shm region. */
cras_shm_callback_pending(const struct cras_audio_shm * shm)542 static inline int cras_shm_callback_pending(const struct cras_audio_shm *shm)
543 {
544 return shm->header->callback_pending;
545 }
546
547 /* Sets the starting offset of a buffer */
cras_shm_set_buffer_offset(struct cras_audio_shm * shm,uint32_t buf_idx,uint32_t offset)548 static inline void cras_shm_set_buffer_offset(struct cras_audio_shm *shm,
549 uint32_t buf_idx, uint32_t offset)
550 {
551 shm->header->buffer_offset[buf_idx] = offset;
552 }
553
554 /* Sets the used_size of the shm region. This is the maximum number of bytes
555 * that is exchanged each time a buffer is passed from client to server.
556 *
557 * Also sets the buffer_offsets to default values based on the used size.
558 */
cras_shm_set_used_size(struct cras_audio_shm * shm,unsigned used_size)559 static inline void cras_shm_set_used_size(struct cras_audio_shm *shm,
560 unsigned used_size)
561 {
562 uint32_t i;
563
564 shm->config.used_size = used_size;
565 if (shm->header)
566 shm->header->config.used_size = used_size;
567
568 for (i = 0; i < CRAS_NUM_SHM_BUFFERS; i++)
569 cras_shm_set_buffer_offset(shm, i, i * used_size);
570 }
571
572 /* Returns the used size of the shm region in bytes. */
cras_shm_used_size(const struct cras_audio_shm * shm)573 static inline unsigned cras_shm_used_size(const struct cras_audio_shm *shm)
574 {
575 return shm->config.used_size;
576 }
577
578 /* Returns the used size of the shm region in frames. */
cras_shm_used_frames(const struct cras_audio_shm * shm)579 static inline unsigned cras_shm_used_frames(const struct cras_audio_shm *shm)
580 {
581 return shm->config.used_size / shm->config.frame_bytes;
582 }
583
584 /* Returns the size of the samples shm region. */
cras_shm_samples_size(const struct cras_audio_shm * shm)585 static inline unsigned cras_shm_samples_size(const struct cras_audio_shm *shm)
586 {
587 return shm->samples_info.length;
588 }
589
590 /* Gets the counter of over-runs. */
cras_shm_num_overruns(const struct cras_audio_shm * shm)591 static inline unsigned cras_shm_num_overruns(const struct cras_audio_shm *shm)
592 {
593 return shm->header->num_overruns;
594 }
595
596 /* Copy the config from the shm region to the local config. Used by clients
597 * when initially setting up the region.
598 */
cras_shm_copy_shared_config(struct cras_audio_shm * shm)599 static inline void cras_shm_copy_shared_config(struct cras_audio_shm *shm)
600 {
601 memcpy(&shm->config, &shm->header->config, sizeof(shm->config));
602 }
603
604 /* Open a read/write shared memory area with the given name.
605 * Args:
606 * name - Name of the shared-memory area.
607 * size - Size of the shared-memory area.
608 * Returns:
609 * >= 0 file descriptor value, or negative errno value on error.
610 */
611 int cras_shm_open_rw(const char *name, size_t size);
612
613 /* Reopen an existing shared memory area read-only.
614 * Args:
615 * name - Name of the shared-memory area.
616 * fd - Existing file descriptor.
617 * Returns:
618 * >= 0 new file descriptor value, or negative errno value on error.
619 */
620 int cras_shm_reopen_ro(const char *name, int fd);
621
622 /* Close and delete a shared memory area.
623 * Args:
624 * name - Name of the shared-memory area.
625 * fd - Existing file descriptor.
626 * Returns:
627 * >= 0 new file descriptor value, or negative errno value on error.
628 */
629 void cras_shm_close_unlink(const char *name, int fd);
630
631 /*
632 * Configure shared memory for the system state.
633 * Args:
634 * name - Name of the shared-memory area.
635 * mmap_size - Amount of shared memor to map.
636 * rw_fd_out - Filled with the RW fd for the shm region.
637 * ro_fd_out - Filled with the RO fd for the shm region.
638 * Returns a pointer to the new shared memory region. Or NULL on error.
639 */
640 void *cras_shm_setup(const char *name, size_t mmap_size, int *rw_fd_out,
641 int *ro_fd_out);
642
643 #ifdef CRAS_SELINUX
644 /*
645 * Wrapper around selinux_restorecon(). This is helpful in unit tests because
646 * we can mock out the selinux_restorecon() behaviour there. That is required
647 * because selinux_restorecon() would fail in the unit tests, since there
648 * is no file_contexts file.
649 * Args:
650 * pathname - Name of the file on which to run restorecon
651 * Returns 0 on success, otherwise -1 and errno is set appropriately.
652 */
653 int cras_selinux_restorecon(const char *pathname);
654 #endif
655
656 #endif /* CRAS_SHM_H_ */
657