xref: /haiku/src/add-ons/kernel/drivers/audio/echo/multi.cpp (revision 67bce78b48ed6d01b5a8eef89f5694c372b7e0a1)
1 /*
2  * EchoGals/Echo24 BeOS Driver for Echo audio cards
3  *
4  * Copyright (c) 2003, Jerome Duval (jerome.duval@free.fr)
5  *
6  * Original code : BeOS Driver for Intel ICH AC'97 Link interface
7  * Copyright (c) 2002, Marcus Overhagen <marcus@overhagen.de>
8  *
9  * All rights reserved.
10  * Redistribution and use in source and binary forms, with or without modification,
11  * are permitted provided that the following conditions are met:
12  *
13  * - Redistributions of source code must retain the above copyright notice,
14  *   this list of conditions and the following disclaimer.
15  * - Redistributions in binary form must reproduce the above copyright notice,
16  *   this list of conditions and the following disclaimer in the documentation
17  *   and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  */
31 
32 #include <OS.h>
33 #include <MediaDefs.h>
34 #include "debug.h"
35 #include "multi_audio.h"
36 #include "multi.h"
37 
38 //#define DEBUG 1
39 
40 #include "echo.h"
41 #include "util.h"
42 
43 static status_t
44 echo_create_controls_list(multi_dev *multi)
45 {
46 	multi->control_count = 0;
47 	PRINT(("multi->control_count %u\n", multi->control_count));
48 	return B_OK;
49 }
50 
51 static status_t
52 echo_get_mix(echo_dev *card, multi_mix_value_info * MMVI)
53 {
54 	return B_OK;
55 }
56 
57 static status_t
58 echo_set_mix(echo_dev *card, multi_mix_value_info * MMVI)
59 {
60 	return B_OK;
61 }
62 
63 static status_t
64 echo_list_mix_controls(echo_dev *card, multi_mix_control_info * MMCI)
65 {
66 	multi_mix_control	*MMC;
67 	uint32 i;
68 
69 	MMC = MMCI->controls;
70 	if(MMCI->control_count < 24)
71 		return B_ERROR;
72 
73 	if(echo_create_controls_list(&card->multi) < B_OK)
74 		return B_ERROR;
75 	for(i=0; i<card->multi.control_count; i++) {
76 		MMC[i] = card->multi.controls[i].mix_control;
77 	}
78 
79 	MMCI->control_count = card->multi.control_count;
80 	return B_OK;
81 }
82 
83 static status_t
84 echo_list_mix_connections(echo_dev *card, multi_mix_connection_info * data)
85 {
86 	return B_ERROR;
87 }
88 
89 static status_t
90 echo_list_mix_channels(echo_dev *card, multi_mix_channel_info *data)
91 {
92 	return B_ERROR;
93 }
94 
95 /*multi_channel_info chans[] = {
96 {  0, B_MULTI_OUTPUT_CHANNEL, 	B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
97 {  1, B_MULTI_OUTPUT_CHANNEL, 	B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
98 {  2, B_MULTI_OUTPUT_CHANNEL, 	B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
99 {  3, B_MULTI_OUTPUT_CHANNEL, 	B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
100 {  4, B_MULTI_INPUT_CHANNEL, 	B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
101 {  5, B_MULTI_INPUT_CHANNEL, 	B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
102 {  6, B_MULTI_INPUT_CHANNEL, 	B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
103 {  7, B_MULTI_INPUT_CHANNEL, 	B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
104 {  8, B_MULTI_OUTPUT_BUS, 		B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 	B_CHANNEL_MINI_JACK_STEREO },
105 {  9, B_MULTI_OUTPUT_BUS, 		B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
106 {  10, B_MULTI_INPUT_BUS, 		B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 	B_CHANNEL_MINI_JACK_STEREO },
107 {  11, B_MULTI_INPUT_BUS, 		B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
108 };*/
109 
110 /*multi_channel_info chans[] = {
111 {  0, B_MULTI_OUTPUT_CHANNEL, 	B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
112 {  1, B_MULTI_OUTPUT_CHANNEL, 	B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
113 {  2, B_MULTI_OUTPUT_CHANNEL, 	B_CHANNEL_LEFT | B_CHANNEL_SURROUND_BUS, 0 },
114 {  3, B_MULTI_OUTPUT_CHANNEL, 	B_CHANNEL_RIGHT | B_CHANNEL_SURROUND_BUS, 0 },
115 {  4, B_MULTI_OUTPUT_CHANNEL, 	B_CHANNEL_REARLEFT | B_CHANNEL_SURROUND_BUS, 0 },
116 {  5, B_MULTI_OUTPUT_CHANNEL, 	B_CHANNEL_REARRIGHT | B_CHANNEL_SURROUND_BUS, 0 },
117 {  6, B_MULTI_INPUT_CHANNEL, 	B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
118 {  7, B_MULTI_INPUT_CHANNEL, 	B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
119 {  8, B_MULTI_INPUT_CHANNEL, 	B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
120 {  9, B_MULTI_INPUT_CHANNEL, 	B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
121 {  10, B_MULTI_OUTPUT_BUS, 		B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 	B_CHANNEL_MINI_JACK_STEREO },
122 {  11, B_MULTI_OUTPUT_BUS, 		B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
123 {  12, B_MULTI_INPUT_BUS, 		B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 	B_CHANNEL_MINI_JACK_STEREO },
124 {  13, B_MULTI_INPUT_BUS, 		B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
125 };*/
126 
127 
128 static void
129 echo_create_channels_list(multi_dev *multi)
130 {
131 	echo_stream *stream;
132 	int32 mode;
133 	uint32 index, i, designations;
134 	multi_channel_info *chans;
135 	uint32 chan_designations[] = {
136 		B_CHANNEL_LEFT,
137 		B_CHANNEL_RIGHT,
138 		B_CHANNEL_REARLEFT,
139 		B_CHANNEL_REARRIGHT,
140 		B_CHANNEL_CENTER,
141 		B_CHANNEL_SUB
142 	};
143 
144 	chans = multi->chans;
145 	index = 0;
146 
147 	for(mode=ECHO_USE_PLAY; mode!=-1;
148 		mode = (mode == ECHO_USE_PLAY) ? ECHO_USE_RECORD : -1) {
149 		LIST_FOREACH(stream, &((echo_dev*)multi->card)->streams, next) {
150 			if ((stream->use & mode) == 0)
151 				continue;
152 
153 			if(stream->channels == 2)
154 				designations = B_CHANNEL_STEREO_BUS;
155 			else
156 				designations = B_CHANNEL_SURROUND_BUS;
157 
158 			for(i=0; i<stream->channels; i++) {
159 				chans[index].channel_id = index;
160 				chans[index].kind = (mode == ECHO_USE_PLAY) ? B_MULTI_OUTPUT_CHANNEL : B_MULTI_INPUT_CHANNEL;
161 				chans[index].designations = designations | chan_designations[i];
162 				chans[index].connectors = 0;
163 				index++;
164 			}
165 		}
166 
167 		if(mode==ECHO_USE_PLAY) {
168 			multi->output_channel_count = index;
169 		} else {
170 			multi->input_channel_count = index - multi->output_channel_count;
171 		}
172 	}
173 
174 	chans[index].channel_id = index;
175 	chans[index].kind = B_MULTI_OUTPUT_BUS;
176 	chans[index].designations = B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS;
177 	chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO;
178 	index++;
179 
180 	chans[index].channel_id = index;
181 	chans[index].kind = B_MULTI_OUTPUT_BUS;
182 	chans[index].designations = B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS;
183 	chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO;
184 	index++;
185 
186 	multi->output_bus_channel_count = index - multi->output_channel_count
187 		- multi->input_channel_count;
188 
189 	chans[index].channel_id = index;
190 	chans[index].kind = B_MULTI_INPUT_BUS;
191 	chans[index].designations = B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS;
192 	chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO;
193 	index++;
194 
195 	chans[index].channel_id = index;
196 	chans[index].kind = B_MULTI_INPUT_BUS;
197 	chans[index].designations = B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS;
198 	chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO;
199 	index++;
200 
201 	multi->input_bus_channel_count = index - multi->output_channel_count
202 		- multi->input_channel_count - multi->output_bus_channel_count;
203 
204 	multi->aux_bus_channel_count = 0;
205 }
206 
207 
208 static status_t
209 echo_get_description(echo_dev *card, multi_description *data)
210 {
211 	int32 size;
212 
213 	data->interface_version = B_CURRENT_INTERFACE_VERSION;
214 	data->interface_minimum = B_CURRENT_INTERFACE_VERSION;
215 
216 	strncpy(data->friendly_name, card->name, 32);
217 	strcpy(data->vendor_info, AUTHOR);
218 
219 	data->output_channel_count = card->multi.output_channel_count;
220 	data->input_channel_count = card->multi.input_channel_count;
221 	data->output_bus_channel_count = card->multi.output_bus_channel_count;
222 	data->input_bus_channel_count = card->multi.input_bus_channel_count;
223 	data->aux_bus_channel_count = card->multi.aux_bus_channel_count;
224 
225 	size = card->multi.output_channel_count + card->multi.input_channel_count
226 			+ card->multi.output_bus_channel_count + card->multi.input_bus_channel_count
227 			+ card->multi.aux_bus_channel_count;
228 
229 	// for each channel, starting with the first output channel,
230 	// then the second, third..., followed by the first input
231 	// channel, second, third, ..., followed by output bus
232 	// channels and input bus channels and finally auxillary channels,
233 
234 	LOG(("request_channel_count = %d\n",data->request_channel_count));
235 	if (data->request_channel_count >= size) {
236 		LOG(("copying data\n"));
237 		memcpy(data->channels, card->multi.chans, size * sizeof(card->multi.chans[0]));
238 	}
239 
240 	data->output_rates = B_SR_48000;// | B_SR_44100 | B_SR_CVSR;
241 	data->input_rates = B_SR_48000;// | B_SR_44100 | B_SR_CVSR;
242 	//data->output_rates = B_SR_44100;
243 	//data->input_rates = B_SR_44100;
244 	data->min_cvsr_rate = 0;
245 	data->max_cvsr_rate = 48000;
246 	//data->max_cvsr_rate = 44100;
247 
248 	data->output_formats = B_FMT_16BIT;
249 	data->input_formats = B_FMT_16BIT;
250 	data->lock_sources = B_MULTI_LOCK_INTERNAL;
251 	data->timecode_sources = 0;
252 	data->interface_flags = B_MULTI_INTERFACE_PLAYBACK | B_MULTI_INTERFACE_RECORD;
253 	data->start_latency = 3000;
254 
255 	strcpy(data->control_panel,"");
256 
257 	return B_OK;
258 }
259 
260 static status_t
261 echo_get_enabled_channels(echo_dev *card, multi_channel_enable *data)
262 {
263 	B_SET_CHANNEL(data->enable_bits, 0, true);
264 	B_SET_CHANNEL(data->enable_bits, 1, true);
265 	B_SET_CHANNEL(data->enable_bits, 2, true);
266 	B_SET_CHANNEL(data->enable_bits, 3, true);
267 	data->lock_source = B_MULTI_LOCK_INTERNAL;
268 /*
269 	uint32			lock_source;
270 	int32			lock_data;
271 	uint32			timecode_source;
272 	uint32 *		connectors;
273 */
274 	return B_OK;
275 }
276 
277 static status_t
278 echo_set_enabled_channels(echo_dev *card, multi_channel_enable *data)
279 {
280 	PRINT(("set_enabled_channels 0 : %s\n", B_TEST_CHANNEL(data->enable_bits, 0) ? "enabled": "disabled"));
281 	PRINT(("set_enabled_channels 1 : %s\n", B_TEST_CHANNEL(data->enable_bits, 1) ? "enabled": "disabled"));
282 	PRINT(("set_enabled_channels 2 : %s\n", B_TEST_CHANNEL(data->enable_bits, 2) ? "enabled": "disabled"));
283 	PRINT(("set_enabled_channels 3 : %s\n", B_TEST_CHANNEL(data->enable_bits, 3) ? "enabled": "disabled"));
284 	return B_OK;
285 }
286 
287 static status_t
288 echo_get_global_format(echo_dev *card, multi_format_info *data)
289 {
290 	data->output_latency = 0;
291 	data->input_latency = 0;
292 	data->timecode_kind = 0;
293 	data->input.rate = B_SR_48000;
294 	data->input.cvsr = 48000;
295 	data->input.format = B_FMT_16BIT;
296 	data->output.rate = B_SR_48000;
297 	data->output.cvsr = 48000;
298 	data->output.format = B_FMT_16BIT;
299 	/*data->input.rate = B_SR_44100;
300 	data->input.cvsr = 44100;
301 	data->input.format = B_FMT_16BIT;
302 	data->output.rate = B_SR_44100;
303 	data->output.cvsr = 44100;
304 	data->output.format = B_FMT_16BIT;*/
305 	return B_OK;
306 }
307 
308 static status_t
309 echo_get_buffers(echo_dev *card, multi_buffer_list *data)
310 {
311 	int32 i, j, pchannels, rchannels;
312 
313 	LOG(("flags = %#x\n",data->flags));
314 	LOG(("request_playback_buffers = %#x\n",data->request_playback_buffers));
315 	LOG(("request_playback_channels = %#x\n",data->request_playback_channels));
316 	LOG(("request_playback_buffer_size = %#x\n",data->request_playback_buffer_size));
317 	LOG(("request_record_buffers = %#x\n",data->request_record_buffers));
318 	LOG(("request_record_channels = %#x\n",data->request_record_channels));
319 	LOG(("request_record_buffer_size = %#x\n",data->request_record_buffer_size));
320 
321 	pchannels = card->pstream->channels;
322 	rchannels = card->rstream->channels;
323 
324 	if (data->request_playback_buffers < BUFFER_COUNT ||
325 		data->request_playback_channels < (pchannels) ||
326 		data->request_record_buffers < BUFFER_COUNT ||
327 		data->request_record_channels < (rchannels)) {
328 		LOG(("not enough channels/buffers\n"));
329 	}
330 
331 	ASSERT(BUFFER_COUNT == 2);
332 
333 	data->flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD; // XXX ???
334 //	data->flags = 0;
335 
336 	data->return_playback_buffers = BUFFER_COUNT;	/* playback_buffers[b][] */
337 	data->return_playback_channels = pchannels;		/* playback_buffers[][c] */
338 	data->return_playback_buffer_size = BUFFER_FRAMES;		/* frames */
339 
340 	for(i=0; i<BUFFER_COUNT; i++)
341 		for(j=0; j<pchannels; j++)
342 			echo_stream_get_nth_buffer(card->pstream, j, i,
343 				&data->playback_buffers[i][j].base,
344 				&data->playback_buffers[i][j].stride);
345 
346 	data->return_record_buffers = BUFFER_COUNT;
347 	data->return_record_channels = rchannels;
348 	data->return_record_buffer_size = BUFFER_FRAMES;	/* frames */
349 
350 	for(i=0; i<BUFFER_COUNT; i++)
351 		for(j=0; j<rchannels; j++)
352 			echo_stream_get_nth_buffer(card->rstream, j, i,
353 				&data->record_buffers[i][j].base,
354 				&data->record_buffers[i][j].stride);
355 
356 	return B_OK;
357 }
358 
359 
360 void
361 echo_play_inth(void* inthparams)
362 {
363 	echo_stream *stream = (echo_stream *)inthparams;
364 	//int32 count;
365 
366 	//TRACE(("echo_play_inth\n"));
367 
368 	acquire_spinlock(&slock);
369 	stream->real_time = system_time();
370 	stream->frames_count += BUFFER_FRAMES;
371 	stream->buffer_cycle = (stream->trigblk
372 		+ stream->blkmod) % stream->blkmod;
373 	stream->update_needed = true;
374 	release_spinlock(&slock);
375 
376 	//get_sem_count(stream->card->buffer_ready_sem, &count);
377 	//if (count <= 0)
378 		release_sem_etc(stream->card->buffer_ready_sem, 1, B_DO_NOT_RESCHEDULE);
379 }
380 
381 void
382 echo_record_inth(void* inthparams)
383 {
384 	echo_stream *stream = (echo_stream *)inthparams;
385 	//int32 count;
386 
387 	//TRACE(("echo_record_inth\n"));
388 
389 	acquire_spinlock(&slock);
390 	stream->real_time = system_time();
391 	stream->frames_count += BUFFER_FRAMES;
392 	stream->buffer_cycle = (stream->trigblk
393 		+ stream->blkmod) % stream->blkmod;
394 	stream->update_needed = true;
395 	release_spinlock(&slock);
396 
397 	//get_sem_count(stream->card->buffer_ready_sem, &count);
398 	//if (count <= 0)
399 		release_sem_etc(stream->card->buffer_ready_sem, 1, B_DO_NOT_RESCHEDULE);
400 }
401 
402 static status_t
403 echo_buffer_exchange(echo_dev *card, multi_buffer_info *data)
404 {
405 	cpu_status status;
406 	echo_stream *pstream, *rstream;
407 
408 	data->flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD;
409 
410 	if (!(card->pstream->state & ECHO_STATE_STARTED))
411 		echo_stream_start(card->pstream, echo_play_inth, card->pstream);
412 
413 	if (!(card->rstream->state & ECHO_STATE_STARTED))
414 		echo_stream_start(card->rstream, echo_record_inth, card->rstream);
415 
416 	if(acquire_sem_etc(card->buffer_ready_sem, 1, B_RELATIVE_TIMEOUT | B_CAN_INTERRUPT, 50000)
417 		== B_TIMED_OUT) {
418 		LOG(("buffer_exchange timeout ff\n"));
419 	}
420 
421 	status = lock();
422 
423 	LIST_FOREACH(pstream, &card->streams, next) {
424 		if ((pstream->use & ECHO_USE_PLAY) == 0 ||
425 			(pstream->state & ECHO_STATE_STARTED) == 0)
426 			continue;
427 		if(pstream->update_needed)
428 			break;
429 	}
430 
431 	LIST_FOREACH(rstream, &card->streams, next) {
432 		if ((rstream->use & ECHO_USE_RECORD) == 0 ||
433 			(rstream->state & ECHO_STATE_STARTED) == 0)
434 			continue;
435 		if(rstream->update_needed)
436 			break;
437 	}
438 
439 	if(!pstream)
440 		pstream = card->pstream;
441 	if(!rstream)
442 		rstream = card->rstream;
443 
444 	/* do playback */
445 	data->playback_buffer_cycle = pstream->buffer_cycle;
446 	data->played_real_time = pstream->real_time;
447 	data->played_frames_count = pstream->frames_count;
448 	data->_reserved_0 = pstream->first_channel;
449 	pstream->update_needed = false;
450 
451 	/* do record */
452 	data->record_buffer_cycle = rstream->buffer_cycle;
453 	data->recorded_frames_count = rstream->frames_count;
454 	data->recorded_real_time = rstream->real_time;
455 	data->_reserved_1 = rstream->first_channel;
456 	rstream->update_needed = false;
457 	unlock(status);
458 
459 	//TRACE(("buffer_exchange ended\n"));
460 	return B_OK;
461 }
462 
463 static status_t
464 echo_buffer_force_stop(echo_dev *card)
465 {
466 	//echo_voice_halt(card->pvoice);
467 	return B_OK;
468 }
469 
470 static status_t
471 echo_multi_control(void *cookie, uint32 op, void *data, size_t length)
472 {
473 	echo_dev *card = (echo_dev *)cookie;
474 
475     switch (op) {
476 		case B_MULTI_GET_DESCRIPTION:
477 			LOG(("B_MULTI_GET_DESCRIPTION\n"));
478 			return echo_get_description(card, (multi_description *)data);
479 		case B_MULTI_GET_EVENT_INFO:
480 			LOG(("B_MULTI_GET_EVENT_INFO\n"));
481 			return B_ERROR;
482 		case B_MULTI_SET_EVENT_INFO:
483 			LOG(("B_MULTI_SET_EVENT_INFO\n"));
484 			return B_ERROR;
485 		case B_MULTI_GET_EVENT:
486 			LOG(("B_MULTI_GET_EVENT\n"));
487 			return B_ERROR;
488 		case B_MULTI_GET_ENABLED_CHANNELS:
489 			LOG(("B_MULTI_GET_ENABLED_CHANNELS\n"));
490 			return echo_get_enabled_channels(card, (multi_channel_enable *)data);
491 		case B_MULTI_SET_ENABLED_CHANNELS:
492 			LOG(("B_MULTI_SET_ENABLED_CHANNELS\n"));
493 			return echo_set_enabled_channels(card, (multi_channel_enable *)data);
494 		case B_MULTI_GET_GLOBAL_FORMAT:
495 			LOG(("B_MULTI_GET_GLOBAL_FORMAT\n"));
496 			return echo_get_global_format(card, (multi_format_info *)data);
497 		case B_MULTI_SET_GLOBAL_FORMAT:
498 			LOG(("B_MULTI_SET_GLOBAL_FORMAT\n"));
499 			return B_OK; /* XXX BUG! we *MUST* return B_OK, returning B_ERROR will prevent
500 						  * BeOS to accept the format returned in B_MULTI_GET_GLOBAL_FORMAT
501 						  */
502 		case B_MULTI_GET_CHANNEL_FORMATS:
503 			LOG(("B_MULTI_GET_CHANNEL_FORMATS\n"));
504 			return B_ERROR;
505 		case B_MULTI_SET_CHANNEL_FORMATS:	/* only implemented if possible */
506 			LOG(("B_MULTI_SET_CHANNEL_FORMATS\n"));
507 			return B_ERROR;
508 		case B_MULTI_GET_MIX:
509 			LOG(("B_MULTI_GET_MIX\n"));
510 			return echo_get_mix(card, (multi_mix_value_info *)data);
511 		case B_MULTI_SET_MIX:
512 			LOG(("B_MULTI_SET_MIX\n"));
513 			return echo_set_mix(card, (multi_mix_value_info *)data);
514 		case B_MULTI_LIST_MIX_CHANNELS:
515 			LOG(("B_MULTI_LIST_MIX_CHANNELS\n"));
516 			return echo_list_mix_channels(card, (multi_mix_channel_info *)data);
517 		case B_MULTI_LIST_MIX_CONTROLS:
518 			LOG(("B_MULTI_LIST_MIX_CONTROLS\n"));
519 			return echo_list_mix_controls(card, (multi_mix_control_info *)data);
520 		case B_MULTI_LIST_MIX_CONNECTIONS:
521 			LOG(("B_MULTI_LIST_MIX_CONNECTIONS\n"));
522 			return echo_list_mix_connections(card, (multi_mix_connection_info *)data);
523 		case B_MULTI_GET_BUFFERS:			/* Fill out the struct for the first time; doesn't start anything. */
524 			LOG(("B_MULTI_GET_BUFFERS\n"));
525 			return echo_get_buffers(card, (multi_buffer_list*)data);
526 		case B_MULTI_SET_BUFFERS:			/* Set what buffers to use, if the driver supports soft buffers. */
527 			LOG(("B_MULTI_SET_BUFFERS\n"));
528 			return B_ERROR; /* we do not support soft buffers */
529 		case B_MULTI_SET_START_TIME:			/* When to actually start */
530 			LOG(("B_MULTI_SET_START_TIME\n"));
531 			return B_ERROR;
532 		case B_MULTI_BUFFER_EXCHANGE:		/* stop and go are derived from this being called */
533 			//TRACE(("B_MULTI_BUFFER_EXCHANGE\n"));
534 			return echo_buffer_exchange(card, (multi_buffer_info *)data);
535 		case B_MULTI_BUFFER_FORCE_STOP:		/* force stop of playback, nothing in data */
536 			LOG(("B_MULTI_BUFFER_FORCE_STOP\n"));
537 			return echo_buffer_force_stop(card);
538 	}
539 	LOG(("ERROR: unknown multi_control %#x\n",op));
540 	return B_ERROR;
541 }
542 
543 static status_t echo_open(const char *name, uint32 flags, void** cookie);
544 static status_t echo_close(void* cookie);
545 static status_t echo_free(void* cookie);
546 static status_t echo_control(void* cookie, uint32 op, void* arg, size_t len);
547 static status_t echo_read(void* cookie, off_t position, void *buf, size_t* num_bytes);
548 static status_t echo_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes);
549 
550 device_hooks multi_hooks = {
551 	echo_open, 			/* -> open entry point */
552 	echo_close, 			/* -> close entry point */
553 	echo_free,			/* -> free cookie */
554 	echo_control, 		/* -> control entry point */
555 	echo_read,			/* -> read entry point */
556 	echo_write,			/* -> write entry point */
557 	NULL,					/* start select */
558 	NULL,					/* stop select */
559 	NULL,					/* scatter-gather read from the device */
560 	NULL					/* scatter-gather write to the device */
561 };
562 
563 static status_t
564 echo_open(const char *name, uint32 flags, void** cookie)
565 {
566 	echo_dev *card = NULL;
567 	int ix;
568 
569 	LOG(("echo_open()\n"));
570 
571 	for (ix=0; ix<num_cards; ix++) {
572 		if (!strcmp(cards[ix].name, name)) {
573 			card = &cards[ix];
574 		}
575 	}
576 
577 	if(card == NULL) {
578 		LOG(("open() card not found %s\n", name));
579 		for (ix=0; ix<num_cards; ix++) {
580 			LOG(("open() card available %s\n", cards[ix].name));
581 		}
582 		return B_ERROR;
583 	}
584 
585 	LOG(("open() got card\n"));
586 
587 	if(card->pstream !=NULL)
588 		return B_ERROR;
589 	if(card->rstream !=NULL)
590 		return B_ERROR;
591 
592 	*cookie = card;
593 	card->multi.card = card;
594 
595 	LOG(("stream_new\n"));
596 
597 	card->rstream = echo_stream_new(card, ECHO_USE_RECORD, BUFFER_FRAMES, BUFFER_COUNT);
598 	card->pstream = echo_stream_new(card, ECHO_USE_PLAY, BUFFER_FRAMES, BUFFER_COUNT);
599 
600 	card->buffer_ready_sem = create_sem(0, "pbuffer ready");
601 
602 	LOG(("stream_setaudio\n"));
603 
604 	echo_stream_set_audioparms(card->pstream, 2, 16, 48000);
605 	echo_stream_set_audioparms(card->rstream, 2, 16, 48000);
606 
607 	card->pstream->first_channel = 0;
608 	card->rstream->first_channel = 2;
609 
610 	echo_create_channels_list(&card->multi);
611 
612 	return B_OK;
613 }
614 
615 static status_t
616 echo_close(void* cookie)
617 {
618 	//echo_dev *card = cookie;
619 	LOG(("close()\n"));
620 
621 	return B_OK;
622 }
623 
624 static status_t
625 echo_free(void* cookie)
626 {
627 	echo_dev *card = (echo_dev *) cookie;
628 	echo_stream *stream;
629 	LOG(("echo_free()\n"));
630 
631 	if (card->buffer_ready_sem > B_OK)
632 			delete_sem(card->buffer_ready_sem);
633 
634 	LIST_FOREACH(stream, &card->streams, next) {
635 		echo_stream_halt(stream);
636 	}
637 
638 	while(!LIST_EMPTY(&card->streams)) {
639 		echo_stream_delete(LIST_FIRST(&card->streams));
640 	}
641 
642 	return B_OK;
643 }
644 
645 static status_t
646 echo_control(void* cookie, uint32 op, void* arg, size_t len)
647 {
648 	return echo_multi_control(cookie, op, arg, len);
649 }
650 
651 static status_t
652 echo_read(void* cookie, off_t position, void *buf, size_t* num_bytes)
653 {
654 	*num_bytes = 0;				/* tell caller nothing was read */
655 	return B_IO_ERROR;
656 }
657 
658 static status_t
659 echo_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes)
660 {
661 	*num_bytes = 0;				/* tell caller nothing was written */
662 	return B_IO_ERROR;
663 }
664 
665