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 #include <pthread.h>
7 #include <sys/param.h>
8 #include <syslog.h>
9 
10 #include "cras_audio_area.h"
11 #include "cras_config.h"
12 #include "cras_iodev.h"
13 #include "cras_iodev_list.h"
14 #include "cras_rstream.h"
15 #include "cras_types.h"
16 #include "utlist.h"
17 
18 #define EMPTY_BUFFER_SIZE (16 * 1024)
19 #define EMPTY_FRAME_SIZE 4
20 #define EMPTY_FRAMES (EMPTY_BUFFER_SIZE / EMPTY_FRAME_SIZE)
21 
22 static size_t empty_supported_rates[] = {
23 	44100, 48000, 0
24 };
25 
26 static size_t empty_supported_channel_counts[] = {
27 	1, 2, 0
28 };
29 
30 static snd_pcm_format_t empty_supported_formats[] = {
31 	SND_PCM_FORMAT_S16_LE,
32 	SND_PCM_FORMAT_S24_LE,
33 	SND_PCM_FORMAT_S32_LE,
34 	SND_PCM_FORMAT_S24_3LE,
35 	0
36 };
37 
38 struct empty_iodev {
39 	struct cras_iodev base;
40 	int open;
41 	uint8_t *audio_buffer;
42 	unsigned int buffer_level;
43 	struct timespec last_buffer_access;
44 };
45 
46 /* Current level of the audio buffer.  This is made up based on what has been
47  * read/written and how long it has been since then.  Simulates audio hardware
48  * running at the given sample rate.
49  */
current_level(const struct cras_iodev * iodev)50 static unsigned int current_level(const struct cras_iodev *iodev)
51 {
52 	struct empty_iodev *empty_iodev = (struct empty_iodev *)iodev;
53 	unsigned int frames, frames_since_last;
54 
55 	if (iodev->active_node->type == CRAS_NODE_TYPE_HOTWORD)
56 		return 0;
57 
58 	frames = empty_iodev->buffer_level;
59 	frames_since_last = cras_frames_since_time(
60 			&empty_iodev->last_buffer_access,
61 			iodev->format->frame_rate);
62 
63 	if (iodev->direction == CRAS_STREAM_INPUT)
64 		return (frames + frames_since_last) % EMPTY_FRAMES;
65 
66 	/* output */
67 	if (frames <= frames_since_last)
68 		return 0;
69 	return frames - frames_since_last;
70 }
71 
72 /*
73  * iodev callbacks.
74  */
75 
frames_queued(const struct cras_iodev * iodev,struct timespec * tstamp)76 static int frames_queued(const struct cras_iodev *iodev,
77 			 struct timespec *tstamp)
78 {
79 	clock_gettime(CLOCK_MONOTONIC_RAW, tstamp);
80 	return current_level(iodev);
81 }
82 
delay_frames(const struct cras_iodev * iodev)83 static int delay_frames(const struct cras_iodev *iodev)
84 {
85 	return 0;
86 }
87 
close_dev(struct cras_iodev * iodev)88 static int close_dev(struct cras_iodev *iodev)
89 {
90 	struct empty_iodev *empty_iodev = (struct empty_iodev *)iodev;
91 
92 	empty_iodev->open = 0;
93 	free(empty_iodev->audio_buffer);
94 	empty_iodev->audio_buffer = NULL;
95 	cras_iodev_free_audio_area(iodev);
96 	return 0;
97 }
98 
configure_dev(struct cras_iodev * iodev)99 static int configure_dev(struct cras_iodev *iodev)
100 {
101 	struct empty_iodev *empty_iodev = (struct empty_iodev *)iodev;
102 
103 	if (iodev->format == NULL)
104 		return -EINVAL;
105 
106 	cras_iodev_init_audio_area(iodev, iodev->format->num_channels);
107 	empty_iodev->open = 1;
108 	empty_iodev->audio_buffer = calloc(1, EMPTY_BUFFER_SIZE);
109 	empty_iodev->buffer_level = 0;
110 
111 	clock_gettime(CLOCK_MONOTONIC_RAW, &empty_iodev->last_buffer_access);
112 
113 	return 0;
114 }
115 
get_buffer(struct cras_iodev * iodev,struct cras_audio_area ** area,unsigned * frames)116 static int get_buffer(struct cras_iodev *iodev,
117 		      struct cras_audio_area **area,
118 		      unsigned *frames)
119 {
120 	struct empty_iodev *empty_iodev = (struct empty_iodev *)iodev;
121 	unsigned int avail, current;
122 
123 	if (iodev->direction == CRAS_STREAM_OUTPUT) {
124 		avail = EMPTY_FRAMES - current_level(iodev);
125 		*frames = MIN(*frames, avail);
126 	} else {
127 		current = current_level(iodev);
128 		*frames = MIN(*frames, current);
129 	}
130 
131 	iodev->area->frames = *frames;
132 	cras_audio_area_config_buf_pointers(iodev->area, iodev->format,
133 			empty_iodev->audio_buffer);
134 	*area = iodev->area;
135 	return 0;
136 }
137 
put_buffer(struct cras_iodev * iodev,unsigned frames)138 static int put_buffer(struct cras_iodev *iodev, unsigned frames)
139 {
140 	struct empty_iodev *empty_iodev = (struct empty_iodev *)iodev;
141 
142 	empty_iodev->buffer_level = current_level(iodev);
143 
144 	clock_gettime(CLOCK_MONOTONIC_RAW, &empty_iodev->last_buffer_access);
145 
146 	if (iodev->direction == CRAS_STREAM_OUTPUT) {
147 		empty_iodev->buffer_level += frames;
148 		empty_iodev->buffer_level %= EMPTY_FRAMES;
149 	} else {
150 		/* Input */
151 		if (empty_iodev->buffer_level > frames)
152 			empty_iodev->buffer_level -= frames;
153 		else
154 			empty_iodev->buffer_level = 0;
155 	}
156 
157 	return 0;
158 }
159 
flush_buffer(struct cras_iodev * iodev)160 static int flush_buffer(struct cras_iodev *iodev)
161 {
162 	struct empty_iodev *empty_iodev = (struct empty_iodev *)iodev;
163 
164 	empty_iodev->buffer_level = current_level(iodev);
165 	if (iodev->direction == CRAS_STREAM_INPUT) {
166 		empty_iodev->buffer_level = 0;
167 		clock_gettime(CLOCK_MONOTONIC_RAW,
168 			      &empty_iodev->last_buffer_access);
169 	}
170 	return 0;
171 }
172 
update_active_node(struct cras_iodev * iodev,unsigned node_idx,unsigned dev_enabled)173 static void update_active_node(struct cras_iodev *iodev, unsigned node_idx,
174 			       unsigned dev_enabled)
175 {
176 }
177 
178 /*
179  * Exported Interface.
180  */
181 
empty_iodev_create(enum CRAS_STREAM_DIRECTION direction,enum CRAS_NODE_TYPE node_type)182 struct cras_iodev *empty_iodev_create(enum CRAS_STREAM_DIRECTION direction,
183 				      enum CRAS_NODE_TYPE node_type)
184 {
185 	struct empty_iodev *empty_iodev;
186 	struct cras_iodev *iodev;
187 	struct cras_ionode *node;
188 
189 	if (direction != CRAS_STREAM_INPUT && direction != CRAS_STREAM_OUTPUT)
190 		return NULL;
191 
192 	empty_iodev = calloc(1, sizeof(*empty_iodev));
193 	if (empty_iodev == NULL)
194 		return NULL;
195 	iodev = &empty_iodev->base;
196 	iodev->direction = direction;
197 
198 	iodev->supported_rates = empty_supported_rates;
199 	iodev->supported_channel_counts = empty_supported_channel_counts;
200 	iodev->supported_formats = empty_supported_formats;
201 	iodev->buffer_size = EMPTY_FRAMES;
202 
203 	iodev->configure_dev = configure_dev;
204 	iodev->close_dev = close_dev;
205 	iodev->frames_queued = frames_queued;
206 	iodev->delay_frames = delay_frames;
207 	iodev->get_buffer = get_buffer;
208 	iodev->put_buffer = put_buffer;
209 	iodev->flush_buffer = flush_buffer;
210 	iodev->update_active_node = update_active_node;
211 	iodev->no_stream = cras_iodev_default_no_stream_playback;
212 
213 	/* Create a dummy ionode */
214 	node = (struct cras_ionode *)calloc(1, sizeof(*node));
215 	node->dev = iodev;
216 	node->type = node_type;
217 	node->volume = 100;
218 	strcpy(node->name, "(default)");
219 	cras_iodev_add_node(iodev, node);
220 	cras_iodev_set_active_node(iodev, node);
221 
222 	/* Finally add it to the appropriate iodev list. */
223 	if (direction == CRAS_STREAM_INPUT) {
224 		if (node->type == CRAS_NODE_TYPE_HOTWORD) {
225 			snprintf(iodev->info.name,
226 				 ARRAY_SIZE(iodev->info.name),
227 				 "Silent hotword device.");
228 			iodev->info.name[ARRAY_SIZE(iodev->info.name) - 1] =
229 				'\0';
230 			iodev->info.idx = SILENT_HOTWORD_DEVICE;
231 		} else {
232 			snprintf(iodev->info.name,
233 				 ARRAY_SIZE(iodev->info.name),
234 				 "Silent record device.");
235 			iodev->info.name[ARRAY_SIZE(iodev->info.name) - 1] =
236 				'\0';
237 			iodev->info.idx = SILENT_RECORD_DEVICE;
238 		}
239 	} else {
240 		snprintf(iodev->info.name,
241 			 ARRAY_SIZE(iodev->info.name),
242 			 "Silent playback device.");
243 		iodev->info.name[ARRAY_SIZE(iodev->info.name) - 1] = '\0';
244 		iodev->info.idx = SILENT_PLAYBACK_DEVICE;
245 	}
246 
247 	return iodev;
248 }
249 
empty_iodev_destroy(struct cras_iodev * iodev)250 void empty_iodev_destroy(struct cras_iodev *iodev)
251 {
252 	struct empty_iodev *empty_iodev = (struct empty_iodev *)iodev;
253 
254 	if (iodev->direction == CRAS_STREAM_INPUT)
255 		cras_iodev_list_rm_input(iodev);
256 	else
257 		cras_iodev_list_rm_output(iodev);
258 	free(iodev->active_node);
259 	cras_iodev_free_resources(iodev);
260 	free(empty_iodev);
261 }
262