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