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