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 _GNU_SOURCE
7 #define _GNU_SOURCE /* for ppoll and asprintf*/
8 #endif
9
10 #include <pthread.h>
11 #include <poll.h>
12 #include <stdbool.h>
13 #include <stdio.h>
14 #include <sys/param.h>
15 #include <syslog.h>
16
17 #include "audio_thread_log.h"
18 #include "cras_audio_thread_monitor.h"
19 #include "cras_config.h"
20 #include "cras_device_monitor.h"
21 #include "cras_fmt_conv.h"
22 #include "cras_iodev.h"
23 #include "cras_rstream.h"
24 #include "cras_server_metrics.h"
25 #include "cras_system_state.h"
26 #include "cras_types.h"
27 #include "cras_util.h"
28 #include "dev_stream.h"
29 #include "audio_thread.h"
30 #include "utlist.h"
31
32 #define MIN_PROCESS_TIME_US 500 /* 0.5ms - min amount of time to mix/src. */
33 #define SLEEP_FUZZ_FRAMES 10 /* # to consider "close enough" to sleep frames. */
34 #define MIN_READ_WAIT_US 2000 /* 2ms */
35 /*
36 * # to check whether a busyloop event happens
37 */
38 #define MAX_CONTINUOUS_ZERO_SLEEP_COUNT 2
39
40 /*
41 * If the number of continuous zero sleep is equal to this limit, the value
42 * will be recorded immediately. It can ensure all busyloop will be recorded
43 * even if the busyloop does not stop.
44 */
45 #define MAX_CONTINUOUS_ZERO_SLEEP_METRIC_LIMIT 1000
46
47 /* Messages that can be sent from the main context to the audio thread. */
48 enum AUDIO_THREAD_COMMAND {
49 AUDIO_THREAD_ADD_OPEN_DEV,
50 AUDIO_THREAD_RM_OPEN_DEV,
51 AUDIO_THREAD_IS_DEV_OPEN,
52 AUDIO_THREAD_ADD_STREAM,
53 AUDIO_THREAD_DISCONNECT_STREAM,
54 AUDIO_THREAD_STOP,
55 AUDIO_THREAD_DUMP_THREAD_INFO,
56 AUDIO_THREAD_DRAIN_STREAM,
57 AUDIO_THREAD_CONFIG_GLOBAL_REMIX,
58 AUDIO_THREAD_DEV_START_RAMP,
59 AUDIO_THREAD_REMOVE_CALLBACK,
60 AUDIO_THREAD_AEC_DUMP,
61 };
62
63 struct audio_thread_msg {
64 size_t length;
65 enum AUDIO_THREAD_COMMAND id;
66 };
67
68 struct audio_thread_config_global_remix {
69 struct audio_thread_msg header;
70 struct cras_fmt_conv *fmt_conv;
71 };
72
73 struct audio_thread_open_device_msg {
74 struct audio_thread_msg header;
75 struct cras_iodev *dev;
76 };
77
78 struct audio_thread_rm_device_msg {
79 struct audio_thread_msg header;
80 enum CRAS_STREAM_DIRECTION dir;
81 unsigned dev_idx;
82 };
83
84 struct audio_thread_rm_callback_msg {
85 struct audio_thread_msg header;
86 int fd;
87 };
88
89 struct audio_thread_add_rm_stream_msg {
90 struct audio_thread_msg header;
91 struct cras_rstream *stream;
92 struct cras_iodev **devs;
93 unsigned int num_devs;
94 };
95
96 struct audio_thread_dump_debug_info_msg {
97 struct audio_thread_msg header;
98 struct audio_debug_info *info;
99 };
100
101 struct audio_thread_dev_start_ramp_msg {
102 struct audio_thread_msg header;
103 unsigned int dev_idx;
104 enum CRAS_IODEV_RAMP_REQUEST request;
105 };
106
107 struct audio_thread_aec_dump_msg {
108 struct audio_thread_msg header;
109 cras_stream_id_t stream_id;
110 unsigned int start; /* */
111 int fd;
112 };
113
114 /* Audio thread logging. If atlog is successfully created from cras_shm_setup,
115 * then the fds should have valid value. Or audio thread will fallback to use
116 * calloc to create atlog and leave the fds as -1.
117 */
118 struct audio_thread_event_log *atlog;
119 char *atlog_name;
120 int atlog_rw_shm_fd;
121 int atlog_ro_shm_fd;
122
123 static struct iodev_callback_list *iodev_callbacks;
124
125 struct iodev_callback_list {
126 int fd;
127 int events;
128 enum AUDIO_THREAD_EVENTS_CB_TRIGGER trigger;
129 thread_callback cb;
130 void *cb_data;
131 struct pollfd *pollfd;
132 struct iodev_callback_list *prev, *next;
133 };
134
audio_thread_add_events_callback(int fd,thread_callback cb,void * data,int events)135 void audio_thread_add_events_callback(int fd, thread_callback cb, void *data,
136 int events)
137 {
138 struct iodev_callback_list *iodev_cb;
139
140 /* Don't add iodev_cb twice */
141 DL_FOREACH (iodev_callbacks, iodev_cb)
142 if (iodev_cb->fd == fd && iodev_cb->cb_data == data)
143 return;
144
145 iodev_cb = (struct iodev_callback_list *)calloc(1, sizeof(*iodev_cb));
146 iodev_cb->fd = fd;
147 iodev_cb->cb = cb;
148 iodev_cb->cb_data = data;
149 iodev_cb->trigger = TRIGGER_POLL;
150 iodev_cb->events = events;
151
152 DL_APPEND(iodev_callbacks, iodev_cb);
153 }
154
audio_thread_rm_callback(int fd)155 void audio_thread_rm_callback(int fd)
156 {
157 struct iodev_callback_list *iodev_cb;
158
159 DL_FOREACH (iodev_callbacks, iodev_cb) {
160 if (iodev_cb->fd == fd) {
161 DL_DELETE(iodev_callbacks, iodev_cb);
162 free(iodev_cb);
163 return;
164 }
165 }
166 }
167
audio_thread_config_events_callback(int fd,enum AUDIO_THREAD_EVENTS_CB_TRIGGER trigger)168 void audio_thread_config_events_callback(
169 int fd, enum AUDIO_THREAD_EVENTS_CB_TRIGGER trigger)
170 {
171 struct iodev_callback_list *iodev_cb;
172
173 DL_FOREACH (iodev_callbacks, iodev_cb) {
174 if (iodev_cb->fd == fd) {
175 iodev_cb->trigger = trigger;
176 return;
177 }
178 }
179 }
180
181 /* Sends a response (error code) from the audio thread to the main thread.
182 * Indicates that the last message sent to the audio thread has been handled
183 * with an error code of rc.
184 * Args:
185 * thread - thread responding to command.
186 * rc - Result code to send back to the main thread.
187 * Returns:
188 * The number of bytes written to the main thread.
189 */
audio_thread_send_response(struct audio_thread * thread,int rc)190 static int audio_thread_send_response(struct audio_thread *thread, int rc)
191 {
192 return write(thread->to_main_fds[1], &rc, sizeof(rc));
193 }
194
195 /* Reads from a file descriptor until all bytes are read.
196 *
197 * Args:
198 * fd - file descriptor to read
199 * buf - the buffer to be written.
200 * count - the number of bytes to read from fd
201 * Returns:
202 * |count| on success, negative error code on failure.
203 */
read_until_finished(int fd,void * buf,size_t count)204 static int read_until_finished(int fd, void *buf, size_t count)
205 {
206 int nread, count_left = count;
207
208 while (count_left > 0) {
209 nread = read(fd, (uint8_t *)buf + count - count_left,
210 count_left);
211 if (nread < 0) {
212 if (errno == EINTR)
213 continue;
214 else
215 return nread;
216 } else if (nread == 0) {
217 syslog(LOG_ERR, "Pipe has been closed.");
218 return -EPIPE;
219 }
220 count_left -= nread;
221 }
222 return count;
223 }
224
225 /* Reads a command from the main thread. Called from the playback/capture
226 * thread. This will read the next available command from the main thread and
227 * put it in buf.
228 * Args:
229 * thread - thread reading the command.
230 * buf - Message is stored here on return.
231 * max_len - maximum length of message to put into buf.
232 * Returns:
233 * 0 on success, negative error code on failure.
234 */
audio_thread_read_command(struct audio_thread * thread,uint8_t * buf,size_t max_len)235 static int audio_thread_read_command(struct audio_thread *thread, uint8_t *buf,
236 size_t max_len)
237 {
238 int to_read, nread, rc;
239 struct audio_thread_msg *msg = (struct audio_thread_msg *)buf;
240
241 /* Get the length of the message first */
242 nread = read_until_finished(thread->to_thread_fds[0], buf,
243 sizeof(msg->length));
244 if (nread < 0)
245 return nread;
246
247 if (msg->length > max_len)
248 return -ENOMEM;
249
250 to_read = msg->length - sizeof(msg->length);
251 rc = read_until_finished(thread->to_thread_fds[0],
252 &buf[0] + sizeof(msg->length), to_read);
253 if (rc < 0)
254 return rc;
255 return 0;
256 }
257
258 /* Builds an initial buffer to avoid an underrun. Adds min_level of latency. */
fill_odevs_zeros_min_level(struct cras_iodev * odev)259 static void fill_odevs_zeros_min_level(struct cras_iodev *odev)
260 {
261 cras_iodev_fill_odev_zeros(odev, odev->min_buffer_level);
262 }
263
264 /* Handles messages from main thread to add a new active device. */
thread_add_open_dev(struct audio_thread * thread,struct cras_iodev * iodev)265 static int thread_add_open_dev(struct audio_thread *thread,
266 struct cras_iodev *iodev)
267 {
268 struct open_dev *adev;
269
270 DL_SEARCH_SCALAR(thread->open_devs[iodev->direction], adev, dev, iodev);
271 if (adev)
272 return -EEXIST;
273
274 adev = (struct open_dev *)calloc(1, sizeof(*adev));
275 adev->dev = iodev;
276
277 /*
278 * Start output devices by padding the output. This avoids a burst of
279 * audio callbacks when the stream starts
280 */
281 if (iodev->direction == CRAS_STREAM_OUTPUT)
282 fill_odevs_zeros_min_level(iodev);
283
284 ATLOG(atlog, AUDIO_THREAD_DEV_ADDED, iodev->info.idx, 0, 0);
285
286 DL_APPEND(thread->open_devs[iodev->direction], adev);
287
288 return 0;
289 }
290
291 /* Handles messages from the main thread to remove an active device. */
thread_rm_open_dev(struct audio_thread * thread,enum CRAS_STREAM_DIRECTION dir,unsigned int dev_idx)292 static int thread_rm_open_dev(struct audio_thread *thread,
293 enum CRAS_STREAM_DIRECTION dir,
294 unsigned int dev_idx)
295 {
296 struct open_dev *adev =
297 dev_io_find_open_dev(thread->open_devs[dir], dev_idx);
298 if (!adev)
299 return -EINVAL;
300
301 dev_io_rm_open_dev(&thread->open_devs[dir], adev);
302 return 0;
303 }
304
305 /*
306 * Handles message from the main thread to check if an iodev is in the
307 * open dev list.
308 */
thread_is_dev_open(struct audio_thread * thread,struct cras_iodev * iodev)309 static int thread_is_dev_open(struct audio_thread *thread,
310 struct cras_iodev *iodev)
311 {
312 struct open_dev *adev = dev_io_find_open_dev(
313 thread->open_devs[iodev->direction], iodev->info.idx);
314 return !!adev;
315 }
316
317 /*
318 * Handles messages from the main thread to start ramping on a device.
319 * Start ramping in audio thread and set mute/unmute
320 * state on device. This should only be done when
321 * device is running with valid streams.
322 *
323 * 1. Mute -> Unmute: Set device unmute state after
324 * ramping is started.
325 * 2. Unmute -> Mute: Set device mute state after
326 * ramping is done.
327 *
328 * The above transition will be handled by cras_iodev_start_ramp.
329 */
thread_dev_start_ramp(struct audio_thread * thread,unsigned int dev_idx,enum CRAS_IODEV_RAMP_REQUEST request)330 static int thread_dev_start_ramp(struct audio_thread *thread,
331 unsigned int dev_idx,
332 enum CRAS_IODEV_RAMP_REQUEST request)
333 {
334 /* Do nothing if device wasn't already in the active dev list. */
335 struct cras_iodev *iodev;
336 struct open_dev *adev = dev_io_find_open_dev(
337 thread->open_devs[CRAS_STREAM_OUTPUT], dev_idx);
338 if (!adev)
339 return -EINVAL;
340 iodev = adev->dev;
341
342 /*
343 * Checks if a device should start ramping for mute/unmute change.
344 * Device must meet all the conditions:
345 *
346 * - Device has ramp support.
347 * - Device is in normal run state, that is, it must be running with valid
348 * streams.
349 * - Device volume, which considers both system volume and adjusted active
350 * node volume, is not zero. If device volume is zero, all the samples are
351 * suppressed to zero and there is no need to ramp.
352 */
353 if (iodev->ramp &&
354 cras_iodev_state(iodev) == CRAS_IODEV_STATE_NORMAL_RUN &&
355 !cras_iodev_is_zero_volume(iodev))
356 return cras_iodev_start_ramp(iodev, request);
357 else
358 return cras_device_monitor_set_device_mute_state(
359 iodev->info.idx);
360 }
361
362 /* Return non-zero if the stream is attached to any device. */
thread_find_stream(struct audio_thread * thread,struct cras_rstream * rstream)363 static int thread_find_stream(struct audio_thread *thread,
364 struct cras_rstream *rstream)
365 {
366 struct open_dev *open_dev;
367 struct dev_stream *s;
368
369 DL_FOREACH (thread->open_devs[rstream->direction], open_dev) {
370 DL_FOREACH (open_dev->dev->streams, s) {
371 if (s->stream == rstream)
372 return 1;
373 }
374 }
375 return 0;
376 }
377
378 /* Handles the disconnect_stream message from the main thread. */
thread_disconnect_stream(struct audio_thread * thread,struct cras_rstream * stream,struct cras_iodev * dev)379 static int thread_disconnect_stream(struct audio_thread *thread,
380 struct cras_rstream *stream,
381 struct cras_iodev *dev)
382 {
383 int rc;
384
385 if (!thread_find_stream(thread, stream))
386 return 0;
387
388 rc = dev_io_remove_stream(&thread->open_devs[stream->direction], stream,
389 dev);
390
391 return rc;
392 }
393
394 /* Initiates draining of a stream or returns the status of a draining stream.
395 * If the stream has completed draining the thread forfeits ownership and must
396 * never reference it again. Returns the number of milliseconds it will take to
397 * finish draining, a minimum of one ms if any samples remain.
398 */
thread_drain_stream_ms_remaining(struct audio_thread * thread,struct cras_rstream * rstream)399 static int thread_drain_stream_ms_remaining(struct audio_thread *thread,
400 struct cras_rstream *rstream)
401 {
402 int fr_in_buff;
403 struct cras_audio_shm *shm;
404
405 if (rstream->direction != CRAS_STREAM_OUTPUT)
406 return 0;
407
408 shm = cras_rstream_shm(rstream);
409 fr_in_buff = cras_shm_get_frames(shm);
410
411 if (fr_in_buff <= 0)
412 return 0;
413
414 cras_rstream_set_is_draining(rstream, 1);
415
416 return 1 + cras_frames_to_ms(fr_in_buff, rstream->format.frame_rate);
417 }
418
419 /* Handles a request to begin draining and return the amount of time left to
420 * draing a stream.
421 */
thread_drain_stream(struct audio_thread * thread,struct cras_rstream * rstream)422 static int thread_drain_stream(struct audio_thread *thread,
423 struct cras_rstream *rstream)
424 {
425 int ms_left;
426
427 if (!thread_find_stream(thread, rstream))
428 return 0;
429
430 ms_left = thread_drain_stream_ms_remaining(thread, rstream);
431 if (ms_left == 0)
432 dev_io_remove_stream(&thread->open_devs[rstream->direction],
433 rstream, NULL);
434
435 return ms_left;
436 }
437
438 /* Handles the add_stream message from the main thread. */
thread_add_stream(struct audio_thread * thread,struct cras_rstream * stream,struct cras_iodev ** iodevs,unsigned int num_iodevs)439 static int thread_add_stream(struct audio_thread *thread,
440 struct cras_rstream *stream,
441 struct cras_iodev **iodevs,
442 unsigned int num_iodevs)
443 {
444 int rc;
445
446 rc = dev_io_append_stream(&thread->open_devs[CRAS_STREAM_OUTPUT],
447 &thread->open_devs[CRAS_STREAM_INPUT], stream,
448 iodevs, num_iodevs);
449 if (rc < 0)
450 return rc;
451
452 return 0;
453 }
454
455 /* Starts or stops aec dump task. */
thread_set_aec_dump(struct audio_thread * thread,cras_stream_id_t stream_id,unsigned int start,int fd)456 static int thread_set_aec_dump(struct audio_thread *thread,
457 cras_stream_id_t stream_id, unsigned int start,
458 int fd)
459 {
460 struct open_dev *idev_list = thread->open_devs[CRAS_STREAM_INPUT];
461 struct open_dev *adev;
462 struct dev_stream *stream;
463
464 DL_FOREACH (idev_list, adev) {
465 if (!cras_iodev_is_open(adev->dev))
466 continue;
467
468 DL_FOREACH (adev->dev->streams, stream) {
469 if ((stream->stream->apm_list == NULL) ||
470 (stream->stream->stream_id != stream_id))
471 continue;
472
473 cras_apm_list_set_aec_dump(stream->stream->apm_list,
474 adev->dev, start, fd);
475 }
476 }
477 return 0;
478 }
479
480 /* Stop the playback thread */
terminate_pb_thread()481 static void terminate_pb_thread()
482 {
483 pthread_exit(0);
484 }
485
append_dev_dump_info(struct audio_dev_debug_info * di,struct open_dev * adev)486 static void append_dev_dump_info(struct audio_dev_debug_info *di,
487 struct open_dev *adev)
488 {
489 struct cras_audio_format *fmt = adev->dev->format;
490 struct timespec now, time_since;
491 strncpy(di->dev_name, adev->dev->info.name, sizeof(di->dev_name));
492 di->buffer_size = adev->dev->buffer_size;
493 di->min_buffer_level = adev->dev->min_buffer_level;
494 di->min_cb_level = adev->dev->min_cb_level;
495 di->max_cb_level = adev->dev->max_cb_level;
496 di->direction = adev->dev->direction;
497 di->num_underruns = cras_iodev_get_num_underruns(adev->dev);
498 di->num_severe_underruns =
499 cras_iodev_get_num_severe_underruns(adev->dev);
500 di->highest_hw_level = adev->dev->highest_hw_level;
501 di->software_gain_scaler = (adev->dev->direction == CRAS_STREAM_INPUT) ?
502 adev->dev->software_gain_scaler :
503 0.0f;
504
505 clock_gettime(CLOCK_MONOTONIC_RAW, &now);
506 subtract_timespecs(&now, &adev->dev->open_ts, &time_since);
507 di->runtime_sec = time_since.tv_sec;
508 di->runtime_nsec = time_since.tv_nsec;
509 di->longest_wake_sec = adev->longest_wake.tv_sec;
510 di->longest_wake_nsec = adev->longest_wake.tv_nsec;
511
512 if (fmt) {
513 di->frame_rate = fmt->frame_rate;
514 di->num_channels = fmt->num_channels;
515 di->est_rate_ratio = cras_iodev_get_est_rate_ratio(adev->dev);
516 } else {
517 di->frame_rate = 0;
518 di->num_channels = 0;
519 di->est_rate_ratio = 0;
520 }
521 }
522
523 /* Put stream info for the given stream into the info struct. */
append_stream_dump_info(struct audio_debug_info * info,struct dev_stream * stream,unsigned int dev_idx,int index)524 static void append_stream_dump_info(struct audio_debug_info *info,
525 struct dev_stream *stream,
526 unsigned int dev_idx, int index)
527 {
528 struct audio_stream_debug_info *si;
529 struct timespec now, time_since;
530
531 si = &info->streams[index];
532
533 si->stream_id = stream->stream->stream_id;
534 si->dev_idx = dev_idx;
535 si->direction = stream->stream->direction;
536 si->stream_type = stream->stream->stream_type;
537 si->client_type = stream->stream->client_type;
538 si->buffer_frames = stream->stream->buffer_frames;
539 si->cb_threshold = stream->stream->cb_threshold;
540 si->frame_rate = stream->stream->format.frame_rate;
541 si->num_channels = stream->stream->format.num_channels;
542 memcpy(si->channel_layout, stream->stream->format.channel_layout,
543 sizeof(si->channel_layout));
544 si->longest_fetch_sec = stream->stream->longest_fetch_interval.tv_sec;
545 si->longest_fetch_nsec = stream->stream->longest_fetch_interval.tv_nsec;
546 si->num_overruns = cras_shm_num_overruns(stream->stream->shm);
547 si->effects = cras_apm_list_get_effects(stream->stream->apm_list);
548 si->pinned_dev_idx = stream->stream->pinned_dev_idx;
549 si->is_pinned = stream->stream->is_pinned;
550 si->num_missed_cb = stream->stream->num_missed_cb;
551 si->stream_volume = cras_rstream_get_volume_scaler(stream->stream);
552
553 clock_gettime(CLOCK_MONOTONIC_RAW, &now);
554 subtract_timespecs(&now, &stream->stream->start_ts, &time_since);
555 si->runtime_sec = time_since.tv_sec;
556 si->runtime_nsec = time_since.tv_nsec;
557 }
558
559 /* Handle a message sent from main thread to the audio thread.
560 * Returns:
561 * Error code when reading or sending message fails.
562 */
handle_audio_thread_message(struct audio_thread * thread)563 static int handle_audio_thread_message(struct audio_thread *thread)
564 {
565 uint8_t buf[256];
566 struct audio_thread_msg *msg = (struct audio_thread_msg *)buf;
567 int ret = 0;
568 int err;
569
570 err = audio_thread_read_command(thread, buf, 256);
571 if (err < 0)
572 return err;
573
574 ATLOG(atlog, AUDIO_THREAD_PB_MSG, msg->id, 0, 0);
575
576 switch (msg->id) {
577 case AUDIO_THREAD_ADD_STREAM: {
578 struct audio_thread_add_rm_stream_msg *amsg;
579 amsg = (struct audio_thread_add_rm_stream_msg *)msg;
580 ATLOG(atlog, AUDIO_THREAD_WRITE_STREAMS_WAIT,
581 amsg->stream->stream_id, 0, 0);
582 ret = thread_add_stream(thread, amsg->stream, amsg->devs,
583 amsg->num_devs);
584 break;
585 }
586 case AUDIO_THREAD_DISCONNECT_STREAM: {
587 struct audio_thread_add_rm_stream_msg *rmsg;
588
589 rmsg = (struct audio_thread_add_rm_stream_msg *)msg;
590
591 ret = thread_disconnect_stream(thread, rmsg->stream,
592 rmsg->devs[0]);
593 break;
594 }
595 case AUDIO_THREAD_ADD_OPEN_DEV: {
596 struct audio_thread_open_device_msg *rmsg;
597
598 rmsg = (struct audio_thread_open_device_msg *)msg;
599 ret = thread_add_open_dev(thread, rmsg->dev);
600 break;
601 }
602 case AUDIO_THREAD_RM_OPEN_DEV: {
603 struct audio_thread_rm_device_msg *rmsg;
604
605 rmsg = (struct audio_thread_rm_device_msg *)msg;
606 ret = thread_rm_open_dev(thread, rmsg->dir, rmsg->dev_idx);
607 break;
608 }
609 case AUDIO_THREAD_IS_DEV_OPEN: {
610 struct audio_thread_open_device_msg *rmsg;
611
612 rmsg = (struct audio_thread_open_device_msg *)msg;
613 ret = thread_is_dev_open(thread, rmsg->dev);
614 break;
615 }
616 case AUDIO_THREAD_STOP:
617 ret = 0;
618 err = audio_thread_send_response(thread, ret);
619 if (err < 0)
620 return err;
621 terminate_pb_thread();
622 break;
623 case AUDIO_THREAD_DUMP_THREAD_INFO: {
624 struct dev_stream *curr;
625 struct open_dev *adev;
626 struct audio_thread_dump_debug_info_msg *dmsg;
627 struct audio_debug_info *info;
628 unsigned int num_streams = 0;
629 unsigned int num_devs = 0;
630
631 ret = 0;
632 dmsg = (struct audio_thread_dump_debug_info_msg *)msg;
633 info = dmsg->info;
634
635 /* Go through all open devices. */
636 DL_FOREACH (thread->open_devs[CRAS_STREAM_OUTPUT], adev) {
637 append_dev_dump_info(&info->devs[num_devs], adev);
638 if (++num_devs == MAX_DEBUG_DEVS)
639 break;
640 DL_FOREACH (adev->dev->streams, curr) {
641 if (num_streams == MAX_DEBUG_STREAMS)
642 break;
643 append_stream_dump_info(info, curr,
644 adev->dev->info.idx,
645 num_streams++);
646 }
647 }
648 DL_FOREACH (thread->open_devs[CRAS_STREAM_INPUT], adev) {
649 if (num_devs == MAX_DEBUG_DEVS)
650 break;
651 append_dev_dump_info(&info->devs[num_devs], adev);
652 DL_FOREACH (adev->dev->streams, curr) {
653 if (num_streams == MAX_DEBUG_STREAMS)
654 break;
655 append_stream_dump_info(info, curr,
656 adev->dev->info.idx,
657 num_streams++);
658 }
659 ++num_devs;
660 }
661 info->num_devs = num_devs;
662
663 info->num_streams = num_streams;
664
665 memcpy(&info->log, atlog, sizeof(info->log));
666 break;
667 }
668 case AUDIO_THREAD_DRAIN_STREAM: {
669 struct audio_thread_add_rm_stream_msg *rmsg;
670
671 rmsg = (struct audio_thread_add_rm_stream_msg *)msg;
672 ret = thread_drain_stream(thread, rmsg->stream);
673 break;
674 }
675 case AUDIO_THREAD_REMOVE_CALLBACK: {
676 struct audio_thread_rm_callback_msg *rmsg;
677
678 rmsg = (struct audio_thread_rm_callback_msg *)msg;
679 audio_thread_rm_callback(rmsg->fd);
680 break;
681 }
682 case AUDIO_THREAD_CONFIG_GLOBAL_REMIX: {
683 struct audio_thread_config_global_remix *rmsg;
684 void *rsp;
685
686 /* Respond the pointer to the old remix converter, so it can be
687 * freed later in main thread. */
688 rsp = (void *)thread->remix_converter;
689
690 rmsg = (struct audio_thread_config_global_remix *)msg;
691 thread->remix_converter = rmsg->fmt_conv;
692
693 return write(thread->to_main_fds[1], &rsp, sizeof(rsp));
694 }
695 case AUDIO_THREAD_DEV_START_RAMP: {
696 struct audio_thread_dev_start_ramp_msg *rmsg;
697
698 rmsg = (struct audio_thread_dev_start_ramp_msg *)msg;
699 ret = thread_dev_start_ramp(thread, rmsg->dev_idx,
700 rmsg->request);
701 break;
702 }
703 case AUDIO_THREAD_AEC_DUMP: {
704 struct audio_thread_aec_dump_msg *rmsg;
705 rmsg = (struct audio_thread_aec_dump_msg *)msg;
706 ret = thread_set_aec_dump(thread, rmsg->stream_id, rmsg->start,
707 rmsg->fd);
708 break;
709 }
710 default:
711 ret = -EINVAL;
712 break;
713 }
714
715 err = audio_thread_send_response(thread, ret);
716 if (err < 0)
717 return err;
718 return 0;
719 }
720
721 /* Returns the number of active streams plus the number of active devices. */
fill_next_sleep_interval(struct audio_thread * thread,struct timespec * ts)722 static int fill_next_sleep_interval(struct audio_thread *thread,
723 struct timespec *ts)
724 {
725 struct timespec min_ts;
726 struct timespec now;
727 int ret;
728
729 ts->tv_sec = 0;
730 ts->tv_nsec = 0;
731 /* Limit the sleep time to 20 seconds. */
732 min_ts.tv_sec = 20;
733 min_ts.tv_nsec = 0;
734 clock_gettime(CLOCK_MONOTONIC_RAW, &now);
735 add_timespecs(&min_ts, &now);
736 ret = dev_io_next_output_wake(&thread->open_devs[CRAS_STREAM_OUTPUT],
737 &min_ts);
738 ret += dev_io_next_input_wake(&thread->open_devs[CRAS_STREAM_INPUT],
739 &min_ts);
740 if (timespec_after(&min_ts, &now))
741 subtract_timespecs(&min_ts, &now, ts);
742
743 return ret;
744 }
745
add_pollfd(struct audio_thread * thread,int fd,int events)746 static struct pollfd *add_pollfd(struct audio_thread *thread, int fd,
747 int events)
748 {
749 thread->pollfds[thread->num_pollfds].fd = fd;
750 thread->pollfds[thread->num_pollfds].events = events;
751 thread->num_pollfds++;
752 if (thread->num_pollfds >= thread->pollfds_size) {
753 thread->pollfds_size *= 2;
754 thread->pollfds = (struct pollfd *)realloc(
755 thread->pollfds,
756 sizeof(*thread->pollfds) * thread->pollfds_size);
757 return NULL;
758 }
759
760 return &thread->pollfds[thread->num_pollfds - 1];
761 }
762
763 static int continuous_zero_sleep_count = 0;
764 static unsigned busyloop_count = 0;
765
766 /*
767 * Logs the number of busyloop during one audio thread running state
768 * (wait_ts != NULL).
769 */
log_busyloop(struct timespec * wait_ts)770 static void log_busyloop(struct timespec *wait_ts)
771 {
772 static struct timespec start_time;
773 static bool started = false;
774 struct timespec diff, now;
775
776 /* If wait_ts is NULL, there is no stream running. */
777 if (wait_ts && !started) {
778 started = true;
779 busyloop_count = 0;
780 clock_gettime(CLOCK_MONOTONIC_RAW, &start_time);
781 } else if (!wait_ts && started) {
782 started = false;
783 clock_gettime(CLOCK_MONOTONIC_RAW, &now);
784 subtract_timespecs(&now, &start_time, &diff);
785 cras_server_metrics_busyloop(&diff, busyloop_count);
786 }
787 }
788
check_busyloop(struct timespec * wait_ts)789 static void check_busyloop(struct timespec *wait_ts)
790 {
791 if (wait_ts->tv_sec == 0 && wait_ts->tv_nsec == 0) {
792 continuous_zero_sleep_count++;
793 if (continuous_zero_sleep_count ==
794 MAX_CONTINUOUS_ZERO_SLEEP_COUNT) {
795 busyloop_count++;
796 cras_audio_thread_event_busyloop();
797 }
798 if (continuous_zero_sleep_count ==
799 MAX_CONTINUOUS_ZERO_SLEEP_METRIC_LIMIT)
800 cras_server_metrics_busyloop_length(
801 continuous_zero_sleep_count);
802
803 } else {
804 if (continuous_zero_sleep_count >=
805 MAX_CONTINUOUS_ZERO_SLEEP_COUNT &&
806 continuous_zero_sleep_count <
807 MAX_CONTINUOUS_ZERO_SLEEP_METRIC_LIMIT)
808 cras_server_metrics_busyloop_length(
809 continuous_zero_sleep_count);
810 continuous_zero_sleep_count = 0;
811 }
812 }
813
814 /* For playback, fill the audio buffer when needed, for capture, pull out
815 * samples when they are ready.
816 * This thread will attempt to run at a high priority to allow for low latency
817 * streams. This thread sleeps while the device plays back or captures audio,
818 * it will wake up as little as it can while avoiding xruns. It can also be
819 * woken by sending it a message using the "audio_thread_post_message" function.
820 */
audio_io_thread(void * arg)821 static void *audio_io_thread(void *arg)
822 {
823 struct audio_thread *thread = (struct audio_thread *)arg;
824 struct open_dev *adev;
825 struct dev_stream *curr;
826 struct timespec ts;
827 int msg_fd;
828 int rc;
829
830 msg_fd = thread->to_thread_fds[0];
831
832 /* Attempt to get realtime scheduling */
833 if (cras_set_rt_scheduling(CRAS_SERVER_RT_THREAD_PRIORITY) == 0)
834 cras_set_thread_priority(CRAS_SERVER_RT_THREAD_PRIORITY);
835
836 thread->pollfds[0].fd = msg_fd;
837 thread->pollfds[0].events = POLLIN;
838
839 while (1) {
840 struct timespec *wait_ts;
841 struct iodev_callback_list *iodev_cb;
842 int non_empty;
843
844 wait_ts = NULL;
845 thread->num_pollfds = 1;
846
847 /* device opened */
848 dev_io_run(&thread->open_devs[CRAS_STREAM_OUTPUT],
849 &thread->open_devs[CRAS_STREAM_INPUT],
850 thread->remix_converter);
851
852 non_empty = dev_io_check_non_empty_state_transition(
853 thread->open_devs[CRAS_STREAM_OUTPUT]);
854
855 if (fill_next_sleep_interval(thread, &ts))
856 wait_ts = &ts;
857
858 restart_poll_loop:
859 thread->num_pollfds = 1;
860
861 DL_FOREACH (iodev_callbacks, iodev_cb) {
862 if (iodev_cb->trigger != TRIGGER_POLL) {
863 iodev_cb->pollfd = NULL;
864 continue;
865 }
866 iodev_cb->pollfd = add_pollfd(thread, iodev_cb->fd,
867 iodev_cb->events);
868 if (!iodev_cb->pollfd)
869 goto restart_poll_loop;
870 }
871
872 /* TODO(dgreid) - once per rstream not per dev_stream */
873 DL_FOREACH (thread->open_devs[CRAS_STREAM_OUTPUT], adev) {
874 DL_FOREACH (adev->dev->streams, curr) {
875 int fd = dev_stream_poll_stream_fd(curr);
876 if (fd < 0)
877 continue;
878 if (!add_pollfd(thread, fd, POLLIN))
879 goto restart_poll_loop;
880 }
881 }
882 DL_FOREACH (thread->open_devs[CRAS_STREAM_INPUT], adev) {
883 DL_FOREACH (adev->dev->streams, curr) {
884 int fd = dev_stream_poll_stream_fd(curr);
885 if (fd < 0)
886 continue;
887 if (!add_pollfd(thread, fd, POLLIN))
888 goto restart_poll_loop;
889 }
890 }
891
892 log_busyloop(wait_ts);
893
894 ATLOG(atlog, AUDIO_THREAD_SLEEP, wait_ts ? wait_ts->tv_sec : 0,
895 wait_ts ? wait_ts->tv_nsec : 0, non_empty);
896 if (wait_ts)
897 check_busyloop(wait_ts);
898
899 /* Sync atlog with shared memory. */
900 __sync_synchronize();
901 atlog->sync_write_pos = atlog->write_pos;
902
903 rc = ppoll(thread->pollfds, thread->num_pollfds, wait_ts, NULL);
904 ATLOG(atlog, AUDIO_THREAD_WAKE, rc, 0, 0);
905
906 /* Handle callbacks registered by TRIGGER_WAKEUP */
907 DL_FOREACH (iodev_callbacks, iodev_cb) {
908 if (iodev_cb->trigger == TRIGGER_WAKEUP) {
909 ATLOG(atlog, AUDIO_THREAD_IODEV_CB, 0, 0, 0);
910 iodev_cb->cb(iodev_cb->cb_data, 0);
911 }
912 }
913
914 /* If there's no pollfd ready to handle. */
915 if (rc <= 0)
916 continue;
917
918 if (thread->pollfds[0].revents & POLLIN) {
919 rc = handle_audio_thread_message(thread);
920 if (rc < 0)
921 syslog(LOG_ERR, "handle message %d", rc);
922 }
923
924 DL_FOREACH (iodev_callbacks, iodev_cb) {
925 if (iodev_cb->pollfd &&
926 iodev_cb->pollfd->revents & iodev_cb->events) {
927 ATLOG(atlog, AUDIO_THREAD_IODEV_CB,
928 iodev_cb->pollfd->revents,
929 iodev_cb->events, 0);
930 iodev_cb->cb(iodev_cb->cb_data,
931 iodev_cb->pollfd->revents);
932 }
933 }
934 }
935
936 return NULL;
937 }
938
939 /* Write a message to the playback thread and wait for an ack, This keeps these
940 * operations synchronous for the main server thread. For instance when the
941 * RM_STREAM message is sent, the stream can be deleted after the function
942 * returns. Making this synchronous also allows the thread to return an error
943 * code that can be handled by the caller.
944 * Args:
945 * thread - thread to receive message.
946 * msg - The message to send.
947 * Returns:
948 * A return code from the message handler in the thread.
949 */
audio_thread_post_message(struct audio_thread * thread,struct audio_thread_msg * msg)950 static int audio_thread_post_message(struct audio_thread *thread,
951 struct audio_thread_msg *msg)
952 {
953 int err, rsp;
954
955 err = write(thread->to_thread_fds[1], msg, msg->length);
956 if (err < 0) {
957 syslog(LOG_ERR, "Failed to post message to thread.");
958 return err;
959 }
960 /* Synchronous action, wait for response. */
961 err = read_until_finished(thread->to_main_fds[0], &rsp, sizeof(rsp));
962 if (err < 0) {
963 syslog(LOG_ERR, "Failed to read reply from thread.");
964 return err;
965 }
966
967 return rsp;
968 }
969
init_open_device_msg(struct audio_thread_open_device_msg * msg,enum AUDIO_THREAD_COMMAND id,struct cras_iodev * dev)970 static void init_open_device_msg(struct audio_thread_open_device_msg *msg,
971 enum AUDIO_THREAD_COMMAND id,
972 struct cras_iodev *dev)
973 {
974 memset(msg, 0, sizeof(*msg));
975 msg->header.id = id;
976 msg->header.length = sizeof(*msg);
977 msg->dev = dev;
978 }
979
init_rm_device_msg(struct audio_thread_rm_device_msg * msg,enum CRAS_STREAM_DIRECTION dir,unsigned int dev_idx)980 static void init_rm_device_msg(struct audio_thread_rm_device_msg *msg,
981 enum CRAS_STREAM_DIRECTION dir,
982 unsigned int dev_idx)
983 {
984 memset(msg, 0, sizeof(*msg));
985 msg->header.id = AUDIO_THREAD_RM_OPEN_DEV;
986 msg->header.length = sizeof(*msg);
987 msg->dir = dir;
988 msg->dev_idx = dev_idx;
989 }
990
init_add_rm_stream_msg(struct audio_thread_add_rm_stream_msg * msg,enum AUDIO_THREAD_COMMAND id,struct cras_rstream * stream,struct cras_iodev ** devs,unsigned int num_devs)991 static void init_add_rm_stream_msg(struct audio_thread_add_rm_stream_msg *msg,
992 enum AUDIO_THREAD_COMMAND id,
993 struct cras_rstream *stream,
994 struct cras_iodev **devs,
995 unsigned int num_devs)
996 {
997 memset(msg, 0, sizeof(*msg));
998 msg->header.id = id;
999 msg->header.length = sizeof(*msg);
1000 msg->stream = stream;
1001 msg->devs = devs;
1002 msg->num_devs = num_devs;
1003 }
1004
1005 static void
init_dump_debug_info_msg(struct audio_thread_dump_debug_info_msg * msg,struct audio_debug_info * info)1006 init_dump_debug_info_msg(struct audio_thread_dump_debug_info_msg *msg,
1007 struct audio_debug_info *info)
1008 {
1009 memset(msg, 0, sizeof(*msg));
1010 msg->header.id = AUDIO_THREAD_DUMP_THREAD_INFO;
1011 msg->header.length = sizeof(*msg);
1012 msg->info = info;
1013 }
1014
1015 static void
init_config_global_remix_msg(struct audio_thread_config_global_remix * msg)1016 init_config_global_remix_msg(struct audio_thread_config_global_remix *msg)
1017 {
1018 memset(msg, 0, sizeof(*msg));
1019 msg->header.id = AUDIO_THREAD_CONFIG_GLOBAL_REMIX;
1020 msg->header.length = sizeof(*msg);
1021 }
1022
1023 static void
init_device_start_ramp_msg(struct audio_thread_dev_start_ramp_msg * msg,enum AUDIO_THREAD_COMMAND id,unsigned int dev_idx,enum CRAS_IODEV_RAMP_REQUEST request)1024 init_device_start_ramp_msg(struct audio_thread_dev_start_ramp_msg *msg,
1025 enum AUDIO_THREAD_COMMAND id, unsigned int dev_idx,
1026 enum CRAS_IODEV_RAMP_REQUEST request)
1027 {
1028 memset(msg, 0, sizeof(*msg));
1029 msg->header.id = id;
1030 msg->header.length = sizeof(*msg);
1031 msg->dev_idx = dev_idx;
1032 msg->request = request;
1033 }
1034
1035 /* Exported Interface */
1036
audio_thread_event_log_shm_fd()1037 int audio_thread_event_log_shm_fd()
1038 {
1039 return atlog_ro_shm_fd;
1040 }
1041
audio_thread_add_stream(struct audio_thread * thread,struct cras_rstream * stream,struct cras_iodev ** devs,unsigned int num_devs)1042 int audio_thread_add_stream(struct audio_thread *thread,
1043 struct cras_rstream *stream,
1044 struct cras_iodev **devs, unsigned int num_devs)
1045 {
1046 struct audio_thread_add_rm_stream_msg msg;
1047
1048 assert(thread && stream);
1049
1050 if (!thread->started)
1051 return -EINVAL;
1052
1053 init_add_rm_stream_msg(&msg, AUDIO_THREAD_ADD_STREAM, stream, devs,
1054 num_devs);
1055 return audio_thread_post_message(thread, &msg.header);
1056 }
1057
audio_thread_disconnect_stream(struct audio_thread * thread,struct cras_rstream * stream,struct cras_iodev * dev)1058 int audio_thread_disconnect_stream(struct audio_thread *thread,
1059 struct cras_rstream *stream,
1060 struct cras_iodev *dev)
1061 {
1062 struct audio_thread_add_rm_stream_msg msg;
1063
1064 assert(thread && stream);
1065
1066 init_add_rm_stream_msg(&msg, AUDIO_THREAD_DISCONNECT_STREAM, stream,
1067 &dev, 0);
1068 return audio_thread_post_message(thread, &msg.header);
1069 }
1070
audio_thread_drain_stream(struct audio_thread * thread,struct cras_rstream * stream)1071 int audio_thread_drain_stream(struct audio_thread *thread,
1072 struct cras_rstream *stream)
1073 {
1074 struct audio_thread_add_rm_stream_msg msg;
1075
1076 assert(thread && stream);
1077
1078 init_add_rm_stream_msg(&msg, AUDIO_THREAD_DRAIN_STREAM, stream, NULL,
1079 0);
1080 return audio_thread_post_message(thread, &msg.header);
1081 }
1082
audio_thread_dump_thread_info(struct audio_thread * thread,struct audio_debug_info * info)1083 int audio_thread_dump_thread_info(struct audio_thread *thread,
1084 struct audio_debug_info *info)
1085 {
1086 struct audio_thread_dump_debug_info_msg msg;
1087
1088 init_dump_debug_info_msg(&msg, info);
1089 return audio_thread_post_message(thread, &msg.header);
1090 }
1091
audio_thread_set_aec_dump(struct audio_thread * thread,cras_stream_id_t stream_id,unsigned int start,int fd)1092 int audio_thread_set_aec_dump(struct audio_thread *thread,
1093 cras_stream_id_t stream_id, unsigned int start,
1094 int fd)
1095 {
1096 struct audio_thread_aec_dump_msg msg;
1097
1098 memset(&msg, 0, sizeof(msg));
1099 msg.header.id = AUDIO_THREAD_AEC_DUMP;
1100 msg.header.length = sizeof(msg);
1101 msg.stream_id = stream_id;
1102 msg.start = start;
1103 msg.fd = fd;
1104 return audio_thread_post_message(thread, &msg.header);
1105 }
1106
audio_thread_rm_callback_sync(struct audio_thread * thread,int fd)1107 int audio_thread_rm_callback_sync(struct audio_thread *thread, int fd)
1108 {
1109 struct audio_thread_rm_callback_msg msg;
1110
1111 memset(&msg, 0, sizeof(msg));
1112 msg.header.id = AUDIO_THREAD_REMOVE_CALLBACK;
1113 msg.header.length = sizeof(msg);
1114 msg.fd = fd;
1115
1116 return audio_thread_post_message(thread, &msg.header);
1117 }
1118
audio_thread_config_global_remix(struct audio_thread * thread,unsigned int num_channels,const float * coefficient)1119 int audio_thread_config_global_remix(struct audio_thread *thread,
1120 unsigned int num_channels,
1121 const float *coefficient)
1122 {
1123 int err;
1124 int identity_remix = 1;
1125 unsigned int i, j;
1126 struct audio_thread_config_global_remix msg;
1127 void *rsp;
1128
1129 init_config_global_remix_msg(&msg);
1130
1131 /* Check if the coefficients represent an identity matrix for remix
1132 * conversion, which means no remix at all. If so then leave the
1133 * converter as NULL. */
1134 for (i = 0; i < num_channels; i++) {
1135 if (coefficient[i * num_channels + i] != 1.0f) {
1136 identity_remix = 0;
1137 break;
1138 }
1139 for (j = i + 1; j < num_channels; j++) {
1140 if (coefficient[i * num_channels + j] != 0 ||
1141 coefficient[j * num_channels + i] != 0) {
1142 identity_remix = 0;
1143 break;
1144 }
1145 }
1146 }
1147
1148 if (!identity_remix) {
1149 msg.fmt_conv = cras_channel_remix_conv_create(num_channels,
1150 coefficient);
1151 if (NULL == msg.fmt_conv)
1152 return -ENOMEM;
1153 }
1154
1155 err = write(thread->to_thread_fds[1], &msg, msg.header.length);
1156 if (err < 0) {
1157 syslog(LOG_ERR, "Failed to post message to thread.");
1158 return err;
1159 }
1160 /* Synchronous action, wait for response. */
1161 err = read_until_finished(thread->to_main_fds[0], &rsp, sizeof(rsp));
1162 if (err < 0) {
1163 syslog(LOG_ERR, "Failed to read reply from thread.");
1164 return err;
1165 }
1166
1167 if (rsp)
1168 cras_fmt_conv_destroy((struct cras_fmt_conv **)&rsp);
1169 return 0;
1170 }
1171
audio_thread_create()1172 struct audio_thread *audio_thread_create()
1173 {
1174 int rc;
1175 struct audio_thread *thread;
1176
1177 thread = (struct audio_thread *)calloc(1, sizeof(*thread));
1178 if (!thread)
1179 return NULL;
1180
1181 thread->to_thread_fds[0] = -1;
1182 thread->to_thread_fds[1] = -1;
1183 thread->to_main_fds[0] = -1;
1184 thread->to_main_fds[1] = -1;
1185
1186 /* Two way pipes for communication with the device's audio thread. */
1187 rc = pipe(thread->to_thread_fds);
1188 if (rc < 0) {
1189 syslog(LOG_ERR, "Failed to pipe");
1190 free(thread);
1191 return NULL;
1192 }
1193 rc = pipe(thread->to_main_fds);
1194 if (rc < 0) {
1195 syslog(LOG_ERR, "Failed to pipe");
1196 free(thread);
1197 return NULL;
1198 }
1199
1200 if (asprintf(&atlog_name, "/ATlog-%d", getpid()) < 0) {
1201 syslog(LOG_ERR, "Failed to generate ATlog name.");
1202 exit(-1);
1203 }
1204
1205 atlog = audio_thread_event_log_init(atlog_name);
1206
1207 thread->pollfds_size = 32;
1208 thread->pollfds = (struct pollfd *)malloc(sizeof(*thread->pollfds) *
1209 thread->pollfds_size);
1210
1211 return thread;
1212 }
1213
audio_thread_add_open_dev(struct audio_thread * thread,struct cras_iodev * dev)1214 int audio_thread_add_open_dev(struct audio_thread *thread,
1215 struct cras_iodev *dev)
1216 {
1217 struct audio_thread_open_device_msg msg;
1218
1219 assert(thread && dev);
1220
1221 if (!thread->started)
1222 return -EINVAL;
1223
1224 init_open_device_msg(&msg, AUDIO_THREAD_ADD_OPEN_DEV, dev);
1225 return audio_thread_post_message(thread, &msg.header);
1226 }
1227
audio_thread_rm_open_dev(struct audio_thread * thread,enum CRAS_STREAM_DIRECTION dir,unsigned int dev_idx)1228 int audio_thread_rm_open_dev(struct audio_thread *thread,
1229 enum CRAS_STREAM_DIRECTION dir,
1230 unsigned int dev_idx)
1231 {
1232 struct audio_thread_rm_device_msg msg;
1233
1234 assert(thread);
1235 if (!thread->started)
1236 return -EINVAL;
1237
1238 init_rm_device_msg(&msg, dir, dev_idx);
1239 return audio_thread_post_message(thread, &msg.header);
1240 }
1241
audio_thread_is_dev_open(struct audio_thread * thread,struct cras_iodev * dev)1242 int audio_thread_is_dev_open(struct audio_thread *thread,
1243 struct cras_iodev *dev)
1244 {
1245 struct audio_thread_open_device_msg msg;
1246
1247 if (!dev)
1248 return 0;
1249
1250 init_open_device_msg(&msg, AUDIO_THREAD_IS_DEV_OPEN, dev);
1251 return audio_thread_post_message(thread, &msg.header);
1252 }
1253
audio_thread_dev_start_ramp(struct audio_thread * thread,unsigned int dev_idx,enum CRAS_IODEV_RAMP_REQUEST request)1254 int audio_thread_dev_start_ramp(struct audio_thread *thread,
1255 unsigned int dev_idx,
1256 enum CRAS_IODEV_RAMP_REQUEST request)
1257 {
1258 struct audio_thread_dev_start_ramp_msg msg;
1259
1260 assert(thread);
1261
1262 if (!thread->started)
1263 return -EINVAL;
1264
1265 init_device_start_ramp_msg(&msg, AUDIO_THREAD_DEV_START_RAMP, dev_idx,
1266 request);
1267 return audio_thread_post_message(thread, &msg.header);
1268 }
1269
audio_thread_start(struct audio_thread * thread)1270 int audio_thread_start(struct audio_thread *thread)
1271 {
1272 int rc;
1273
1274 rc = pthread_create(&thread->tid, NULL, audio_io_thread, thread);
1275 if (rc) {
1276 syslog(LOG_ERR, "Failed pthread_create");
1277 return rc;
1278 }
1279
1280 thread->started = 1;
1281
1282 return 0;
1283 }
1284
audio_thread_destroy(struct audio_thread * thread)1285 void audio_thread_destroy(struct audio_thread *thread)
1286 {
1287 if (thread->started) {
1288 struct audio_thread_msg msg;
1289
1290 msg.id = AUDIO_THREAD_STOP;
1291 msg.length = sizeof(msg);
1292 audio_thread_post_message(thread, &msg);
1293 pthread_join(thread->tid, NULL);
1294 }
1295
1296 free(thread->pollfds);
1297
1298 audio_thread_event_log_deinit(atlog, atlog_name);
1299 free(atlog_name);
1300
1301 if (thread->to_thread_fds[0] != -1) {
1302 close(thread->to_thread_fds[0]);
1303 close(thread->to_thread_fds[1]);
1304 }
1305 if (thread->to_main_fds[0] != -1) {
1306 close(thread->to_main_fds[0]);
1307 close(thread->to_main_fds[1]);
1308 }
1309
1310 if (thread->remix_converter)
1311 cras_fmt_conv_destroy(&thread->remix_converter);
1312
1313 free(thread);
1314 }
1315