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 <driver_settings.h> 33 #include <OS.h> 34 #include <MediaDefs.h> 35 #include "debug.h" 36 #include "hmulti_audio.h" 37 #include "multi.h" 38 39 //#define DEBUG 1 40 41 #include "echo.h" 42 #include "util.h" 43 44 typedef enum { 45 B_MIX_GAIN = 1 << 0, 46 B_MIX_MUTE = 1 << 1, 47 B_MIX_NOMINAL = 1 << 2 48 } mixer_type; 49 50 typedef struct { 51 uint8 channels; 52 uint8 bitsPerSample; 53 uint32 sample_rate; 54 uint32 buffer_frames; 55 int32 buffer_count; 56 } echo_settings; 57 58 echo_settings current_settings = { 59 2, // channels 60 16, // bits per sample 61 48000, // sample rate 62 512, // buffer frames 63 2 // buffer count 64 }; 65 66 67 static void 68 echo_channel_get_mix(void *card, MIXER_AUDIO_CHANNEL channel, int32 type, float *values) { 69 echo_dev *dev = (echo_dev*) card; 70 MIXER_MULTI_FUNCTION multi_function[2]; 71 PMIXER_FUNCTION function = multi_function[0].MixerFunction; 72 INT32 size = ComputeMixerMultiFunctionSize(2); 73 function[0].Channel = channel; 74 function[1].Channel = channel; 75 function[1].Channel.wChannel++; 76 switch (type) { 77 case B_MIX_GAIN: 78 function[0].iFunction = function[1].iFunction = MXF_GET_LEVEL; 79 break; 80 case B_MIX_MUTE: 81 function[0].iFunction = function[1].iFunction = MXF_GET_MUTE; 82 break; 83 case B_MIX_NOMINAL: 84 function[0].iFunction = function[1].iFunction = MXF_GET_NOMINAL; 85 break; 86 } 87 88 multi_function[0].iCount = 2; 89 dev->pEG->ProcessMixerMultiFunction(multi_function, size); 90 91 if (function[0].RtnStatus == ECHOSTATUS_OK) { 92 if (type == B_MIX_GAIN) { 93 values[0] = (float)function[0].Data.iLevel / 256; 94 values[1] = (float)function[1].Data.iLevel / 256; 95 } else if (type == B_MIX_MUTE) { 96 values[0] = function[0].Data.bMuteOn ? 1.0 : 0.0; 97 } else { 98 values[0] = function[0].Data.iNominal == 4 ? 1.0 : 0.0; 99 } 100 PRINT(("echo_channel_get_mix iLevel: %ld, %d, %ld\n", function[0].Data.iLevel, 101 channel.wChannel, channel.dwType)); 102 } 103 104 } 105 106 107 static void 108 echo_channel_set_mix(void *card, MIXER_AUDIO_CHANNEL channel, int32 type, float *values) { 109 echo_dev *dev = (echo_dev*) card; 110 MIXER_MULTI_FUNCTION multi_function[2]; 111 PMIXER_FUNCTION function = multi_function[0].MixerFunction; 112 INT32 size = ComputeMixerMultiFunctionSize(2); 113 function[0].Channel = channel; 114 function[1].Channel = channel; 115 function[1].Channel.wChannel++; 116 if (type == B_MIX_GAIN) { 117 function[0].Data.iLevel = (int)(values[0] * 256); 118 function[0].iFunction = MXF_SET_LEVEL; 119 function[1].Data.iLevel = (int)(values[1] * 256); 120 function[1].iFunction = MXF_SET_LEVEL; 121 } else if (type == B_MIX_MUTE) { 122 function[0].Data.bMuteOn = values[0] == 1.0; 123 function[0].iFunction = MXF_SET_MUTE; 124 function[1].Data.bMuteOn = values[0] == 1.0; 125 function[1].iFunction = MXF_SET_MUTE; 126 } else { 127 function[0].Data.iNominal = values[0] == 1.0 ? 4 : -10; 128 function[0].iFunction = MXF_SET_NOMINAL; 129 function[1].Data.iNominal = values[0] == 1.0 ? 4 : -10; 130 function[1].iFunction = MXF_SET_NOMINAL; 131 } 132 133 multi_function[0].iCount = 2; 134 dev->pEG->ProcessMixerMultiFunction(multi_function, size); 135 136 if (function[0].RtnStatus == ECHOSTATUS_OK) { 137 PRINT(("echo_channel_set_mix OK: %ld, %d, %ld\n", function[0].Data.iLevel, 138 channel.wChannel, channel.dwType)); 139 } 140 141 } 142 143 144 static int32 145 echo_create_group_control(multi_dev *multi, uint32 *index, int32 parent, 146 enum strind_id string, const char* name) { 147 uint32 i = *index; 148 (*index)++; 149 multi->controls[i].mix_control.id = MULTI_CONTROL_FIRSTID + i; 150 multi->controls[i].mix_control.parent = parent; 151 multi->controls[i].mix_control.flags = B_MULTI_MIX_GROUP; 152 multi->controls[i].mix_control.master = MULTI_CONTROL_MASTERID; 153 multi->controls[i].mix_control.string = string; 154 if (name) 155 strcpy(multi->controls[i].mix_control.name, name); 156 157 return multi->controls[i].mix_control.id; 158 } 159 160 static void 161 echo_create_channel_control(multi_dev *multi, uint32 *index, int32 parent, int32 string, 162 MIXER_AUDIO_CHANNEL channel, bool nominal) { 163 uint32 i = *index, id; 164 multi_mixer_control control; 165 166 control.mix_control.master = MULTI_CONTROL_MASTERID; 167 control.mix_control.parent = parent; 168 control.channel = channel; 169 control.get = &echo_channel_get_mix; 170 control.set = &echo_channel_set_mix; 171 control.mix_control.gain.min_gain = -128; 172 control.mix_control.gain.max_gain = 6; 173 control.mix_control.gain.granularity = 0.5; 174 175 control.mix_control.id = MULTI_CONTROL_FIRSTID + i; 176 control.mix_control.flags = B_MULTI_MIX_ENABLE; 177 control.mix_control.string = S_MUTE; 178 control.type = B_MIX_MUTE; 179 multi->controls[i] = control; 180 i++; 181 182 control.mix_control.id = MULTI_CONTROL_FIRSTID + i; 183 control.mix_control.flags = B_MULTI_MIX_GAIN; 184 control.mix_control.string = S_null; 185 control.type = B_MIX_GAIN; 186 strcpy(control.mix_control.name, "Gain"); 187 multi->controls[i] = control; 188 id = control.mix_control.id; 189 i++; 190 191 // second channel 192 control.mix_control.id = MULTI_CONTROL_FIRSTID + i; 193 control.mix_control.master = id; 194 multi->controls[i] = control; 195 i++; 196 197 // nominal level (+4/-10) 198 if (nominal) { 199 control.mix_control.id = MULTI_CONTROL_FIRSTID + i; 200 control.mix_control.master = MULTI_CONTROL_MASTERID; 201 control.mix_control.flags = B_MULTI_MIX_ENABLE; 202 control.mix_control.string = S_null; 203 control.type = B_MIX_NOMINAL; 204 strcpy(control.mix_control.name, "+4dB"); 205 multi->controls[i] = control; 206 i++; 207 } 208 209 *index = i; 210 } 211 212 213 static status_t 214 echo_create_controls_list(multi_dev *multi) 215 { 216 uint32 i = 0, index = 0, parent, parent2; 217 echo_dev *card = (echo_dev*)multi->card; 218 219 parent = echo_create_group_control(multi, &index, 0, S_OUTPUT, NULL); 220 221 MIXER_AUDIO_CHANNEL channel; 222 channel.wCardId = 0; 223 channel.dwType = ECHO_BUS_OUT; 224 for (i = 0; i < card->caps.wNumBussesOut / 2; i++) { 225 channel.wChannel = i * 2; 226 parent2 = echo_create_group_control(multi, &index, parent, S_null, "Output"); 227 228 echo_create_channel_control(multi, &index, parent2, 0, channel, 229 card->caps.dwBusOutCaps[i*2] & ECHOCAPS_NOMINAL_LEVEL); 230 } 231 232 parent = echo_create_group_control(multi, &index, 0, S_INPUT, NULL); 233 234 channel.dwType = ECHO_BUS_IN; 235 for (i = 0; i < card->caps.wNumBussesIn / 2; i++) { 236 channel.wChannel = i * 2; 237 238 parent2 = echo_create_group_control(multi, &index, parent, S_null, "Input"); 239 240 echo_create_channel_control(multi, &index, parent2, 0, channel, 241 card->caps.dwBusInCaps[i*2] & ECHOCAPS_NOMINAL_LEVEL); 242 } 243 244 multi->control_count = index; 245 PRINT(("multi->control_count %lu\n", multi->control_count)); 246 return B_OK; 247 } 248 249 static status_t 250 echo_get_mix(echo_dev *card, multi_mix_value_info * mmvi) 251 { 252 int32 i; 253 uint32 id; 254 multi_mixer_control *control = NULL; 255 for (i = 0; i < mmvi->item_count; i++) { 256 id = mmvi->values[i].id - MULTI_CONTROL_FIRSTID; 257 if (id < 0 || id >= card->multi.control_count) { 258 PRINT(("echo_get_mix : invalid control id requested : %li\n", id)); 259 continue; 260 } 261 control = &card->multi.controls[id]; 262 263 if (control->mix_control.flags & B_MULTI_MIX_GAIN) { 264 if (control->get) { 265 float values[2]; 266 control->get(card, control->channel, control->type, values); 267 if (control->mix_control.master == MULTI_CONTROL_MASTERID) 268 mmvi->values[i].gain = values[0]; 269 else 270 mmvi->values[i].gain = values[1]; 271 } 272 } 273 274 if (control->mix_control.flags & B_MULTI_MIX_ENABLE && control->get) { 275 float values[1]; 276 control->get(card, control->channel, control->type, values); 277 mmvi->values[i].enable = (values[0] == 1.0); 278 } 279 280 if (control->mix_control.flags & B_MULTI_MIX_MUX && control->get) { 281 float values[1]; 282 control->get(card, control->channel, control->type, values); 283 mmvi->values[i].mux = (int32)values[0]; 284 } 285 } 286 return B_OK; 287 } 288 289 290 static status_t 291 echo_set_mix(echo_dev *card, multi_mix_value_info * mmvi) 292 { 293 int32 i; 294 uint32 id; 295 multi_mixer_control *control = NULL; 296 for (i = 0; i < mmvi->item_count; i++) { 297 id = mmvi->values[i].id - MULTI_CONTROL_FIRSTID; 298 if (id < 0 || id >= card->multi.control_count) { 299 PRINT(("echo_set_mix : invalid control id requested : %li\n", id)); 300 continue; 301 } 302 control = &card->multi.controls[id]; 303 304 if (control->mix_control.flags & B_MULTI_MIX_GAIN) { 305 multi_mixer_control *control2 = NULL; 306 if (i+1<mmvi->item_count) { 307 id = mmvi->values[i + 1].id - MULTI_CONTROL_FIRSTID; 308 if (id < 0 || id >= card->multi.control_count) { 309 PRINT(("echo_set_mix : invalid control id requested : %li\n", id)); 310 } else { 311 control2 = &card->multi.controls[id]; 312 if (control2->mix_control.master != control->mix_control.id) 313 control2 = NULL; 314 } 315 } 316 317 if (control->set) { 318 float values[2]; 319 values[0] = 0.0; 320 values[1] = 0.0; 321 322 if (control->mix_control.master == MULTI_CONTROL_MASTERID) 323 values[0] = mmvi->values[i].gain; 324 else 325 values[1] = mmvi->values[i].gain; 326 327 if (control2 && control2->mix_control.master != MULTI_CONTROL_MASTERID) 328 values[1] = mmvi->values[i+1].gain; 329 330 control->set(card, control->channel, control->type, values); 331 } 332 333 if (control2) 334 i++; 335 } 336 337 if (control->mix_control.flags & B_MULTI_MIX_ENABLE && control->set) { 338 float values[1]; 339 340 values[0] = mmvi->values[i].enable ? 1.0 : 0.0; 341 control->set(card, control->channel, control->type, values); 342 } 343 344 if (control->mix_control.flags & B_MULTI_MIX_MUX && control->set) { 345 float values[1]; 346 347 values[0] = (float)mmvi->values[i].mux; 348 control->set(card, control->channel, control->type, values); 349 } 350 } 351 return B_OK; 352 } 353 354 355 static status_t 356 echo_list_mix_controls(echo_dev *card, multi_mix_control_info * mmci) 357 { 358 multi_mix_control *mmc; 359 uint32 i; 360 361 mmc = mmci->controls; 362 if (mmci->control_count < 24) 363 return B_ERROR; 364 365 if (echo_create_controls_list(&card->multi) < B_OK) 366 return B_ERROR; 367 for (i = 0; i < card->multi.control_count; i++) { 368 mmc[i] = card->multi.controls[i].mix_control; 369 } 370 371 mmci->control_count = card->multi.control_count; 372 return B_OK; 373 } 374 375 376 static status_t 377 echo_list_mix_connections(echo_dev* card, multi_mix_connection_info* data) 378 { 379 return B_ERROR; 380 } 381 382 383 static status_t 384 echo_list_mix_channels(echo_dev *card, multi_mix_channel_info *data) 385 { 386 return B_ERROR; 387 } 388 389 /*multi_channel_info chans[] = { 390 { 0, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 391 { 1, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 392 { 2, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 393 { 3, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 394 { 4, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 395 { 5, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 396 { 6, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 397 { 7, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 398 { 8, B_MULTI_OUTPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 399 { 9, B_MULTI_OUTPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 400 { 10, B_MULTI_INPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 401 { 11, B_MULTI_INPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 402 };*/ 403 404 /*multi_channel_info chans[] = { 405 { 0, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 406 { 1, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 407 { 2, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_SURROUND_BUS, 0 }, 408 { 3, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_SURROUND_BUS, 0 }, 409 { 4, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_REARLEFT | B_CHANNEL_SURROUND_BUS, 0 }, 410 { 5, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_REARRIGHT | B_CHANNEL_SURROUND_BUS, 0 }, 411 { 6, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 412 { 7, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 413 { 8, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 414 { 9, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 415 { 10, B_MULTI_OUTPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 416 { 11, B_MULTI_OUTPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 417 { 12, B_MULTI_INPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 418 { 13, B_MULTI_INPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 419 };*/ 420 421 422 static void 423 echo_create_channels_list(multi_dev *multi) 424 { 425 echo_stream *stream; 426 int32 mode; 427 uint32 index, i, designations; 428 multi_channel_info *chans; 429 uint32 chan_designations[] = { 430 B_CHANNEL_LEFT, 431 B_CHANNEL_RIGHT, 432 B_CHANNEL_REARLEFT, 433 B_CHANNEL_REARRIGHT, 434 B_CHANNEL_CENTER, 435 B_CHANNEL_SUB 436 }; 437 438 chans = multi->chans; 439 index = 0; 440 441 for (mode=ECHO_USE_PLAY; mode!=-1; 442 mode = (mode == ECHO_USE_PLAY) ? ECHO_USE_RECORD : -1) { 443 LIST_FOREACH(stream, &((echo_dev*)multi->card)->streams, next) { 444 if ((stream->use & mode) == 0) 445 continue; 446 447 if (stream->channels == 2) 448 designations = B_CHANNEL_STEREO_BUS; 449 else 450 designations = B_CHANNEL_SURROUND_BUS; 451 452 for (i = 0; i < stream->channels; i++) { 453 chans[index].channel_id = index; 454 chans[index].kind = (mode == ECHO_USE_PLAY) ? B_MULTI_OUTPUT_CHANNEL : B_MULTI_INPUT_CHANNEL; 455 chans[index].designations = designations | chan_designations[i]; 456 chans[index].connectors = 0; 457 index++; 458 } 459 } 460 461 if (mode==ECHO_USE_PLAY) { 462 multi->output_channel_count = index; 463 } else { 464 multi->input_channel_count = index - multi->output_channel_count; 465 } 466 } 467 468 chans[index].channel_id = index; 469 chans[index].kind = B_MULTI_OUTPUT_BUS; 470 chans[index].designations = B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS; 471 chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO; 472 index++; 473 474 chans[index].channel_id = index; 475 chans[index].kind = B_MULTI_OUTPUT_BUS; 476 chans[index].designations = B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS; 477 chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO; 478 index++; 479 480 multi->output_bus_channel_count = index - multi->output_channel_count 481 - multi->input_channel_count; 482 483 chans[index].channel_id = index; 484 chans[index].kind = B_MULTI_INPUT_BUS; 485 chans[index].designations = B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS; 486 chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO; 487 index++; 488 489 chans[index].channel_id = index; 490 chans[index].kind = B_MULTI_INPUT_BUS; 491 chans[index].designations = B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS; 492 chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO; 493 index++; 494 495 multi->input_bus_channel_count = index - multi->output_channel_count 496 - multi->input_channel_count - multi->output_bus_channel_count; 497 498 multi->aux_bus_channel_count = 0; 499 } 500 501 502 static status_t 503 echo_get_description(echo_dev *card, multi_description *data) 504 { 505 int32 size; 506 507 data->interface_version = B_CURRENT_INTERFACE_VERSION; 508 data->interface_minimum = B_CURRENT_INTERFACE_VERSION; 509 510 strncpy(data->friendly_name, card->caps.szName, sizeof(data->friendly_name)); 511 strncpy(data->vendor_info, AUTHOR, sizeof(data->vendor_info)); 512 513 data->output_channel_count = card->multi.output_channel_count; 514 data->input_channel_count = card->multi.input_channel_count; 515 data->output_bus_channel_count = card->multi.output_bus_channel_count; 516 data->input_bus_channel_count = card->multi.input_bus_channel_count; 517 data->aux_bus_channel_count = card->multi.aux_bus_channel_count; 518 519 size = card->multi.output_channel_count + card->multi.input_channel_count 520 + card->multi.output_bus_channel_count + card->multi.input_bus_channel_count 521 + card->multi.aux_bus_channel_count; 522 523 // for each channel, starting with the first output channel, 524 // then the second, third..., followed by the first input 525 // channel, second, third, ..., followed by output bus 526 // channels and input bus channels and finally auxillary channels, 527 528 LOG(("request_channel_count = %d\n",data->request_channel_count)); 529 if (data->request_channel_count >= size) { 530 LOG(("copying data\n")); 531 memcpy(data->channels, card->multi.chans, size * sizeof(card->multi.chans[0])); 532 } 533 534 switch (current_settings.sample_rate) { 535 case 192000: data->output_rates = data->input_rates = B_SR_192000; break; 536 case 96000: data->output_rates = data->input_rates = B_SR_96000; break; 537 case 48000: data->output_rates = data->input_rates = B_SR_48000; break; 538 case 44100: data->output_rates = data->input_rates = B_SR_44100; break; 539 } 540 data->min_cvsr_rate = 0; 541 data->max_cvsr_rate = 48000; 542 543 switch (current_settings.bitsPerSample) { 544 case 8: data->output_formats = data->input_formats = B_FMT_8BIT_U; break; 545 case 16: data->output_formats = data->input_formats = B_FMT_16BIT; break; 546 case 24: data->output_formats = data->input_formats = B_FMT_24BIT; break; 547 case 32: data->output_formats = data->input_formats = B_FMT_32BIT; break; 548 } 549 data->lock_sources = B_MULTI_LOCK_INTERNAL; 550 data->timecode_sources = 0; 551 data->interface_flags = B_MULTI_INTERFACE_PLAYBACK | B_MULTI_INTERFACE_RECORD; 552 data->start_latency = 3000; 553 554 strcpy(data->control_panel, ""); 555 556 return B_OK; 557 } 558 559 560 static status_t 561 echo_get_enabled_channels(echo_dev *card, multi_channel_enable *data) 562 { 563 B_SET_CHANNEL(data->enable_bits, 0, true); 564 B_SET_CHANNEL(data->enable_bits, 1, true); 565 B_SET_CHANNEL(data->enable_bits, 2, true); 566 B_SET_CHANNEL(data->enable_bits, 3, true); 567 data->lock_source = B_MULTI_LOCK_INTERNAL; 568 /* 569 uint32 lock_source; 570 int32 lock_data; 571 uint32 timecode_source; 572 uint32 * connectors; 573 */ 574 return B_OK; 575 } 576 577 578 static status_t 579 echo_set_enabled_channels(echo_dev *card, multi_channel_enable *data) 580 { 581 PRINT(("set_enabled_channels 0 : %s\n", B_TEST_CHANNEL(data->enable_bits, 0) ? "enabled": "disabled")); 582 PRINT(("set_enabled_channels 1 : %s\n", B_TEST_CHANNEL(data->enable_bits, 1) ? "enabled": "disabled")); 583 PRINT(("set_enabled_channels 2 : %s\n", B_TEST_CHANNEL(data->enable_bits, 2) ? "enabled": "disabled")); 584 PRINT(("set_enabled_channels 3 : %s\n", B_TEST_CHANNEL(data->enable_bits, 3) ? "enabled": "disabled")); 585 return B_OK; 586 } 587 588 589 static status_t 590 echo_get_global_format(echo_dev *card, multi_format_info *data) 591 { 592 data->output_latency = 0; 593 data->input_latency = 0; 594 data->timecode_kind = 0; 595 switch (current_settings.sample_rate) { 596 case 192000: data->output.rate = data->input.rate = B_SR_192000; break; 597 case 96000: data->output.rate = data->input.rate = B_SR_96000; break; 598 case 48000: data->output.rate = data->input.rate = B_SR_48000; break; 599 case 44100: data->output.rate = data->input.rate = B_SR_44100; break; 600 } 601 switch (current_settings.bitsPerSample) { 602 case 8: data->input.format = data->output.format = B_FMT_8BIT_U; break; 603 case 16: data->input.format = data->output.format = B_FMT_16BIT; break; 604 case 24: data->input.format = data->output.format = B_FMT_24BIT; break; 605 case 32: data->input.format = data->output.format = B_FMT_32BIT; break; 606 } 607 data->input.cvsr = data->output.cvsr = current_settings.sample_rate; 608 return B_OK; 609 } 610 611 612 static status_t 613 echo_get_buffers(echo_dev *card, multi_buffer_list *data) 614 { 615 int32 i, j, channels; 616 echo_stream *stream; 617 618 LOG(("flags = %#x\n",data->flags)); 619 LOG(("request_playback_buffers = %#x\n",data->request_playback_buffers)); 620 LOG(("request_playback_channels = %#x\n",data->request_playback_channels)); 621 LOG(("request_playback_buffer_size = %#x\n",data->request_playback_buffer_size)); 622 LOG(("request_record_buffers = %#x\n",data->request_record_buffers)); 623 LOG(("request_record_channels = %#x\n",data->request_record_channels)); 624 LOG(("request_record_buffer_size = %#x\n",data->request_record_buffer_size)); 625 626 if (data->request_playback_buffers < current_settings.buffer_count || 627 data->request_record_buffers < current_settings.buffer_count) { 628 LOG(("not enough channels/buffers\n")); 629 } 630 631 ASSERT(current_settings.buffer_count == 2); 632 633 data->flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD; // XXX ??? 634 635 data->return_playback_buffers = current_settings.buffer_count; /* playback_buffers[b][] */ 636 data->return_playback_channels = 0; /* playback_buffers[][c] */ 637 data->return_playback_buffer_size = current_settings.buffer_frames; /* frames */ 638 639 LIST_FOREACH(stream, &card->streams, next) { 640 if ((stream->use & ECHO_USE_PLAY) == 0) 641 continue; 642 LOG(("get_buffers pipe %d\n", stream->pipe)); 643 channels = data->return_playback_channels; 644 data->return_playback_channels += stream->channels; 645 if (data->request_playback_channels < data->return_playback_channels) { 646 LOG(("not enough channels\n")); 647 } 648 for (i = 0; i < current_settings.buffer_count; i++) 649 for (j=0; j<stream->channels; j++) 650 echo_stream_get_nth_buffer(stream, j, i, 651 &data->playback_buffers[i][channels+j].base, 652 &data->playback_buffers[i][channels+j].stride); 653 } 654 655 data->return_record_buffers = current_settings.buffer_count; 656 data->return_record_channels = 0; 657 data->return_record_buffer_size = current_settings.buffer_frames; /* frames */ 658 659 LIST_FOREACH(stream, &card->streams, next) { 660 if ((stream->use & ECHO_USE_PLAY) != 0) 661 continue; 662 LOG(("get_buffers pipe %d\n", stream->pipe)); 663 channels = data->return_record_channels; 664 data->return_record_channels += stream->channels; 665 if (data->request_record_channels < data->return_record_channels) { 666 LOG(("not enough channels\n")); 667 } 668 for (i = 0; i < current_settings.buffer_count; i++) 669 for (j=0; j<stream->channels; j++) 670 echo_stream_get_nth_buffer(stream, j, i, 671 &data->record_buffers[i][channels+j].base, 672 &data->record_buffers[i][channels+j].stride); 673 } 674 675 return B_OK; 676 } 677 678 679 void 680 echo_play_inth(void* inthparams) 681 { 682 echo_stream *stream = (echo_stream *)inthparams; 683 //int32 count; 684 685 //TRACE(("echo_play_inth\n")); 686 687 acquire_spinlock(&slock); 688 stream->real_time = system_time(); 689 stream->frames_count += current_settings.buffer_frames; 690 stream->buffer_cycle = (stream->trigblk 691 + stream->blkmod) % stream->blkmod; 692 stream->update_needed = true; 693 release_spinlock(&slock); 694 695 //get_sem_count(stream->card->buffer_ready_sem, &count); 696 //if (count <= 0) 697 release_sem_etc(stream->card->buffer_ready_sem, 1, B_DO_NOT_RESCHEDULE); 698 } 699 700 701 void 702 echo_record_inth(void* inthparams) 703 { 704 echo_stream *stream = (echo_stream *)inthparams; 705 //int32 count; 706 707 //TRACE(("echo_record_inth\n")); 708 709 acquire_spinlock(&slock); 710 stream->real_time = system_time(); 711 stream->frames_count += current_settings.buffer_frames; 712 stream->buffer_cycle = (stream->trigblk 713 + stream->blkmod - 1) % stream->blkmod; 714 stream->update_needed = true; 715 release_spinlock(&slock); 716 717 //get_sem_count(stream->card->buffer_ready_sem, &count); 718 //if (count <= 0) 719 release_sem_etc(stream->card->buffer_ready_sem, 1, B_DO_NOT_RESCHEDULE); 720 } 721 722 723 static status_t 724 echo_buffer_exchange(echo_dev *card, multi_buffer_info *data) 725 { 726 cpu_status status; 727 echo_stream *pstream, *rstream, *stream; 728 multi_buffer_info buffer_info; 729 730 #ifdef __HAIKU__ 731 if (user_memcpy(&buffer_info, data, sizeof(buffer_info)) < B_OK) 732 return B_BAD_ADDRESS; 733 #else 734 memcpy(&buffer_info, data, sizeof(buffer_info)); 735 #endif 736 737 buffer_info.flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD; 738 739 LIST_FOREACH(stream, &card->streams, next) { 740 if ((stream->state & ECHO_STATE_STARTED) != 0) 741 continue; 742 echo_stream_start(stream, 743 ((stream->use & ECHO_USE_PLAY) == 0) ? echo_record_inth : echo_play_inth, stream); 744 } 745 746 if (acquire_sem_etc(card->buffer_ready_sem, 1, B_RELATIVE_TIMEOUT | B_CAN_INTERRUPT, 50000) 747 == B_TIMED_OUT) { 748 LOG(("buffer_exchange timeout ff\n")); 749 } 750 751 status = lock(); 752 753 LIST_FOREACH(pstream, &card->streams, next) { 754 if ((pstream->use & ECHO_USE_PLAY) == 0 || 755 (pstream->state & ECHO_STATE_STARTED) == 0) 756 continue; 757 if (pstream->update_needed) 758 break; 759 } 760 761 LIST_FOREACH(rstream, &card->streams, next) { 762 if ((rstream->use & ECHO_USE_RECORD) == 0 || 763 (rstream->state & ECHO_STATE_STARTED) == 0) 764 continue; 765 if (rstream->update_needed) 766 break; 767 } 768 769 if (!pstream) 770 pstream = card->pstream; 771 if (!rstream) 772 rstream = card->rstream; 773 774 /* do playback */ 775 buffer_info.playback_buffer_cycle = pstream->buffer_cycle; 776 buffer_info.played_real_time = pstream->real_time; 777 buffer_info.played_frames_count = pstream->frames_count; 778 buffer_info._reserved_0 = pstream->first_channel; 779 pstream->update_needed = false; 780 781 /* do record */ 782 buffer_info.record_buffer_cycle = rstream->buffer_cycle; 783 buffer_info.recorded_frames_count = rstream->frames_count; 784 buffer_info.recorded_real_time = rstream->real_time; 785 buffer_info._reserved_1 = rstream->first_channel; 786 rstream->update_needed = false; 787 unlock(status); 788 789 #ifdef __HAIKU__ 790 if (user_memcpy(data, &buffer_info, sizeof(buffer_info)) < B_OK) 791 return B_BAD_ADDRESS; 792 #else 793 memcpy(data, &buffer_info, sizeof(buffer_info)); 794 #endif 795 796 //TRACE(("buffer_exchange ended\n")); 797 return B_OK; 798 } 799 800 801 static status_t 802 echo_buffer_force_stop(echo_dev *card) 803 { 804 //echo_voice_halt(card->pvoice); 805 return B_OK; 806 } 807 808 809 static status_t 810 echo_multi_control(void *cookie, uint32 op, void *data, size_t length) 811 { 812 echo_dev *card = (echo_dev *)cookie; 813 814 #ifdef CARDBUS 815 // Check 816 if (card->plugged == false) { 817 LOG(("device %s unplugged\n", card->name)); 818 return B_ERROR; 819 } 820 #endif 821 822 switch (op) { 823 case B_MULTI_GET_DESCRIPTION: 824 LOG(("B_MULTI_GET_DESCRIPTION\n")); 825 return echo_get_description(card, (multi_description *)data); 826 case B_MULTI_GET_EVENT_INFO: 827 LOG(("B_MULTI_GET_EVENT_INFO\n")); 828 return B_ERROR; 829 case B_MULTI_SET_EVENT_INFO: 830 LOG(("B_MULTI_SET_EVENT_INFO\n")); 831 return B_ERROR; 832 case B_MULTI_GET_EVENT: 833 LOG(("B_MULTI_GET_EVENT\n")); 834 return B_ERROR; 835 case B_MULTI_GET_ENABLED_CHANNELS: 836 LOG(("B_MULTI_GET_ENABLED_CHANNELS\n")); 837 return echo_get_enabled_channels(card, (multi_channel_enable *)data); 838 case B_MULTI_SET_ENABLED_CHANNELS: 839 LOG(("B_MULTI_SET_ENABLED_CHANNELS\n")); 840 return echo_set_enabled_channels(card, (multi_channel_enable *)data); 841 case B_MULTI_GET_GLOBAL_FORMAT: 842 LOG(("B_MULTI_GET_GLOBAL_FORMAT\n")); 843 return echo_get_global_format(card, (multi_format_info *)data); 844 case B_MULTI_SET_GLOBAL_FORMAT: 845 LOG(("B_MULTI_SET_GLOBAL_FORMAT\n")); 846 return B_OK; /* XXX BUG! we *MUST* return B_OK, returning B_ERROR will prevent 847 * BeOS to accept the format returned in B_MULTI_GET_GLOBAL_FORMAT 848 */ 849 case B_MULTI_GET_CHANNEL_FORMATS: 850 LOG(("B_MULTI_GET_CHANNEL_FORMATS\n")); 851 return B_ERROR; 852 case B_MULTI_SET_CHANNEL_FORMATS: /* only implemented if possible */ 853 LOG(("B_MULTI_SET_CHANNEL_FORMATS\n")); 854 return B_ERROR; 855 case B_MULTI_GET_MIX: 856 LOG(("B_MULTI_GET_MIX\n")); 857 return echo_get_mix(card, (multi_mix_value_info *)data); 858 case B_MULTI_SET_MIX: 859 LOG(("B_MULTI_SET_MIX\n")); 860 return echo_set_mix(card, (multi_mix_value_info *)data); 861 case B_MULTI_LIST_MIX_CHANNELS: 862 LOG(("B_MULTI_LIST_MIX_CHANNELS\n")); 863 return echo_list_mix_channels(card, (multi_mix_channel_info *)data); 864 case B_MULTI_LIST_MIX_CONTROLS: 865 LOG(("B_MULTI_LIST_MIX_CONTROLS\n")); 866 return echo_list_mix_controls(card, (multi_mix_control_info *)data); 867 case B_MULTI_LIST_MIX_CONNECTIONS: 868 LOG(("B_MULTI_LIST_MIX_CONNECTIONS\n")); 869 return echo_list_mix_connections(card, (multi_mix_connection_info *)data); 870 case B_MULTI_GET_BUFFERS: /* Fill out the struct for the first time; doesn't start anything. */ 871 LOG(("B_MULTI_GET_BUFFERS\n")); 872 return echo_get_buffers(card, (multi_buffer_list*)data); 873 case B_MULTI_SET_BUFFERS: /* Set what buffers to use, if the driver supports soft buffers. */ 874 LOG(("B_MULTI_SET_BUFFERS\n")); 875 return B_ERROR; /* we do not support soft buffers */ 876 case B_MULTI_SET_START_TIME: /* When to actually start */ 877 LOG(("B_MULTI_SET_START_TIME\n")); 878 return B_ERROR; 879 case B_MULTI_BUFFER_EXCHANGE: /* stop and go are derived from this being called */ 880 //TRACE(("B_MULTI_BUFFER_EXCHANGE\n")); 881 return echo_buffer_exchange(card, (multi_buffer_info *)data); 882 case B_MULTI_BUFFER_FORCE_STOP: /* force stop of playback, nothing in data */ 883 LOG(("B_MULTI_BUFFER_FORCE_STOP\n")); 884 return echo_buffer_force_stop(card); 885 } 886 LOG(("ERROR: unknown multi_control %#x\n",op)); 887 return B_ERROR; 888 } 889 890 891 static status_t echo_open(const char *name, uint32 flags, void** cookie); 892 static status_t echo_close(void* cookie); 893 static status_t echo_free(void* cookie); 894 static status_t echo_control(void* cookie, uint32 op, void* arg, size_t len); 895 static status_t echo_read(void* cookie, off_t position, void *buf, size_t* num_bytes); 896 static status_t echo_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes); 897 898 899 device_hooks multi_hooks = { 900 echo_open, /* -> open entry point */ 901 echo_close, /* -> close entry point */ 902 echo_free, /* -> free cookie */ 903 echo_control, /* -> control entry point */ 904 echo_read, /* -> read entry point */ 905 echo_write, /* -> write entry point */ 906 NULL, /* start select */ 907 NULL, /* stop select */ 908 NULL, /* scatter-gather read from the device */ 909 NULL /* scatter-gather write to the device */ 910 }; 911 912 913 static status_t 914 echo_open(const char *name, uint32 flags, void** cookie) 915 { 916 echo_dev *card = NULL; 917 int i, first_record_channel; 918 echo_stream *stream = NULL; 919 920 LOG(("echo_open()\n")); 921 922 #ifdef CARDBUS 923 LIST_FOREACH(card, &devices, next) { 924 if (!strcmp(card->name, name)) { 925 break; 926 } 927 } 928 #else 929 for (i = 0; i < num_cards; i++) { 930 if (!strcmp(cards[i].name, name)) { 931 card = &cards[i]; 932 } 933 } 934 #endif 935 936 if (card == NULL) { 937 LOG(("open() card not found %s\n", name)); 938 #ifdef CARDBUS 939 LIST_FOREACH(card, &devices, next) { 940 LOG(("open() card available %s\n", card->name)); 941 } 942 #else 943 for (int ix=0; ix<num_cards; ix++) { 944 LOG(("open() card available %s\n", cards[ix].name)); 945 } 946 #endif 947 return B_ERROR; 948 } 949 950 #ifdef CARDBUS 951 if (card->plugged == false) { 952 LOG(("device %s unplugged\n", name)); 953 return B_ERROR; 954 } 955 #endif 956 957 LOG(("open() got card\n")); 958 959 if (card->pstream != NULL) 960 return B_ERROR; 961 if (card->rstream != NULL) 962 return B_ERROR; 963 964 *cookie = card; 965 card->multi.card = card; 966 #ifdef CARDBUS 967 card->opened = true; 968 #endif 969 970 void *settings_handle; 971 // get driver settings 972 settings_handle = load_driver_settings ("echo.settings"); 973 if (settings_handle != NULL) { 974 const char* item; 975 char* end; 976 uint32 value; 977 978 item = get_driver_parameter (settings_handle, "channels", NULL, NULL); 979 if (item) { 980 value = strtoul (item, &end, 0); 981 if (*end == '\0') current_settings.channels = value; 982 } 983 PRINT(("channels %u\n", current_settings.channels)); 984 985 item = get_driver_parameter (settings_handle, "bitsPerSample", NULL, NULL); 986 if (item) { 987 value = strtoul (item, &end, 0); 988 if (*end == '\0') current_settings.bitsPerSample = value; 989 } 990 PRINT(("bitsPerSample %u\n", current_settings.bitsPerSample)); 991 992 item = get_driver_parameter (settings_handle, "sample_rate", NULL, NULL); 993 if (item) { 994 value = strtoul (item, &end, 0); 995 if (*end == '\0') current_settings.sample_rate = value; 996 } 997 PRINT(("sample_rate %lu\n", current_settings.sample_rate)); 998 999 item = get_driver_parameter (settings_handle, "buffer_frames", NULL, NULL); 1000 if (item) { 1001 value = strtoul (item, &end, 0); 1002 if (*end == '\0') current_settings.buffer_frames = value; 1003 } 1004 PRINT(("buffer_frames %lu\n", current_settings.buffer_frames)); 1005 1006 item = get_driver_parameter (settings_handle, "buffer_count", NULL, NULL); 1007 if (item) { 1008 value = strtoul (item, &end, 0); 1009 if (*end == '\0') current_settings.buffer_count = value; 1010 } 1011 PRINT(("buffer_count %lu\n", current_settings.buffer_count)); 1012 1013 unload_driver_settings (settings_handle); 1014 } 1015 1016 LOG(("creating play streams\n")); 1017 1018 i = card->caps.wNumPipesOut - 2; 1019 first_record_channel = card->caps.wNumPipesOut; 1020 #ifdef ECHO3G_FAMILY 1021 if (current_settings.sample_rate > 50000) { 1022 i = card->caps.wFirstDigitalBusOut; 1023 first_record_channel = card->caps.wFirstDigitalBusOut + 2; 1024 } 1025 #endif 1026 1027 for (; i >=0 ; i-=2) { 1028 stream = echo_stream_new(card, ECHO_USE_PLAY, current_settings.buffer_frames, current_settings.buffer_count); 1029 if (!card->pstream) 1030 card->pstream = stream; 1031 echo_stream_set_audioparms(stream, current_settings.channels, 1032 current_settings.bitsPerSample, current_settings.sample_rate, i); 1033 stream->first_channel = i; 1034 } 1035 1036 LOG(("creating record streams\n")); 1037 i = card->caps.wNumPipesIn - 2; 1038 #ifdef ECHO3G_FAMILY 1039 if (current_settings.sample_rate > 50000) { 1040 i = card->caps.wFirstDigitalBusIn; 1041 } 1042 #endif 1043 1044 for (; i >= 0; i-=2) { 1045 stream = echo_stream_new(card, ECHO_USE_RECORD, current_settings.buffer_frames, current_settings.buffer_count); 1046 if (!card->rstream) 1047 card->rstream = stream; 1048 echo_stream_set_audioparms(stream, current_settings.channels, 1049 current_settings.bitsPerSample, current_settings.sample_rate, i); 1050 stream->first_channel = i + first_record_channel; 1051 } 1052 1053 card->buffer_ready_sem = create_sem(0, "pbuffer ready"); 1054 1055 LOG(("creating channels list\n")); 1056 echo_create_channels_list(&card->multi); 1057 1058 return B_OK; 1059 } 1060 1061 1062 static status_t 1063 echo_close(void* cookie) 1064 { 1065 LOG(("close()\n")); 1066 #ifdef CARDBUS 1067 echo_dev *card = (echo_dev *) cookie; 1068 card->opened = false; 1069 #endif 1070 1071 return B_OK; 1072 } 1073 1074 1075 static status_t 1076 echo_free(void* cookie) 1077 { 1078 echo_dev *card = (echo_dev *) cookie; 1079 echo_stream *stream; 1080 LOG(("echo_free()\n")); 1081 1082 if (card->buffer_ready_sem > B_OK) 1083 delete_sem(card->buffer_ready_sem); 1084 1085 LIST_FOREACH(stream, &card->streams, next) { 1086 echo_stream_halt(stream); 1087 } 1088 1089 while(!LIST_EMPTY(&card->streams)) { 1090 echo_stream_delete(LIST_FIRST(&card->streams)); 1091 } 1092 1093 card->pstream = NULL; 1094 card->rstream = NULL; 1095 1096 return B_OK; 1097 } 1098 1099 1100 static status_t 1101 echo_control(void* cookie, uint32 op, void* arg, size_t len) 1102 { 1103 return echo_multi_control(cookie, op, arg, len); 1104 } 1105 1106 1107 static status_t 1108 echo_read(void* cookie, off_t position, void *buf, size_t* num_bytes) 1109 { 1110 *num_bytes = 0; /* tell caller nothing was read */ 1111 return B_IO_ERROR; 1112 } 1113 1114 1115 static status_t 1116 echo_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes) 1117 { 1118 *num_bytes = 0; /* tell caller nothing was written */ 1119 return B_IO_ERROR; 1120 } 1121