1 /* 2 * Driver for USB Audio Device Class devices. 3 * Copyright (c) 2009-13 S.Zharski <imker@gmx.li> 4 * Distributed under the terms of the MIT license. 5 * 6 */ 7 8 9 #include "Device.h" 10 11 #include <kernel.h> 12 #include <usb/USB_audio.h> 13 14 #include "Driver.h" 15 #include "Settings.h" 16 17 18 Device::Device(usb_device device) 19 : 20 fStatus(B_ERROR), 21 fOpen(false), 22 fRemoved(false), 23 fDevice(device), 24 fNonBlocking(false), 25 fAudioControl(this), 26 fBuffersReadySem(-1) 27 { 28 const usb_device_descriptor* deviceDescriptor 29 = gUSBModule->get_device_descriptor(device); 30 31 if (deviceDescriptor == NULL) { 32 TRACE(ERR, "Error of getting USB device descriptor.\n"); 33 return; 34 } 35 36 fVendorID = deviceDescriptor->vendor_id; 37 fProductID = deviceDescriptor->product_id; 38 fUSBVersion = deviceDescriptor->usb_version; 39 40 fBuffersReadySem = create_sem(0, DRIVER_NAME "_buffers_ready"); 41 if (fBuffersReadySem < B_OK) { 42 TRACE(ERR, "Error of creating ready " 43 "buffers semaphore:%#010x\n", fBuffersReadySem); 44 return; 45 } 46 47 if (_SetupEndpoints() != B_OK) 48 return; 49 50 // must be set in derived class constructor 51 fStatus = B_OK; 52 } 53 54 55 Device::~Device() 56 { 57 for (Vector<Stream*>::Iterator I = fStreams.Begin(); 58 I != fStreams.End(); I++) 59 delete *I; 60 61 fStreams.MakeEmpty(); 62 63 if (fBuffersReadySem > B_OK) 64 delete_sem(fBuffersReadySem); 65 } 66 67 68 status_t 69 Device::Open(uint32 flags) 70 { 71 if (fOpen) 72 return B_BUSY; 73 if (fRemoved) 74 return B_ERROR; 75 76 status_t result = StartDevice(); 77 if (result != B_OK) 78 return result; 79 80 // TODO: are we need this??? 81 fNonBlocking = (flags & O_NONBLOCK) == O_NONBLOCK; 82 fOpen = true; 83 return result; 84 } 85 86 87 status_t 88 Device::Close() 89 { 90 if (fRemoved) { 91 fOpen = false; 92 return B_OK; 93 } 94 95 for (int i = 0; i < fStreams.Count(); i++) 96 fStreams[i]->Stop(); 97 98 fOpen = false; 99 100 return StopDevice(); 101 } 102 103 104 status_t 105 Device::Free() 106 { 107 return B_OK; 108 } 109 110 111 status_t 112 Device::Read(uint8* buffer, size_t* numBytes) 113 { 114 *numBytes = 0; 115 return B_IO_ERROR; 116 } 117 118 119 status_t 120 Device::Write(const uint8* buffer, size_t* numBytes) 121 { 122 *numBytes = 0; 123 return B_IO_ERROR; 124 } 125 126 127 status_t 128 Device::Control(uint32 op, void* buffer, size_t length) 129 { 130 switch (op) { 131 case B_MULTI_GET_DESCRIPTION: 132 { 133 multi_description description; 134 multi_channel_info channels[16]; 135 multi_channel_info* originalChannels; 136 137 if (user_memcpy(&description, buffer, sizeof(multi_description)) 138 != B_OK) 139 return B_BAD_ADDRESS; 140 141 originalChannels = description.channels; 142 description.channels = channels; 143 if (description.request_channel_count > 16) 144 description.request_channel_count = 16; 145 146 status_t status = _MultiGetDescription(&description); 147 if (status != B_OK) 148 return status; 149 150 description.channels = originalChannels; 151 if (user_memcpy(buffer, &description, sizeof(multi_description)) 152 != B_OK) 153 return B_BAD_ADDRESS; 154 return user_memcpy(originalChannels, channels, 155 sizeof(multi_channel_info) * description.request_channel_count); 156 } 157 case B_MULTI_GET_EVENT_INFO: 158 TRACE(ERR, "B_MULTI_GET_EVENT_INFO n/i\n"); 159 return B_ERROR; 160 161 case B_MULTI_SET_EVENT_INFO: 162 TRACE(ERR, "B_MULTI_SET_EVENT_INFO n/i\n"); 163 return B_ERROR; 164 165 case B_MULTI_GET_EVENT: 166 TRACE(ERR, "B_MULTI_GET_EVENT n/i\n"); 167 return B_ERROR; 168 169 case B_MULTI_GET_ENABLED_CHANNELS: 170 { 171 multi_channel_enable enable; 172 uint32 enable_bits; 173 uchar* orig_enable_bits; 174 175 if (user_memcpy(&enable, buffer, sizeof(enable)) != B_OK 176 || !IS_USER_ADDRESS(enable.enable_bits)) { 177 return B_BAD_ADDRESS; 178 } 179 180 orig_enable_bits = enable.enable_bits; 181 enable.enable_bits = (uchar*)&enable_bits; 182 status_t status = _MultiGetEnabledChannels(&enable); 183 if (status != B_OK) 184 return status; 185 186 enable.enable_bits = orig_enable_bits; 187 if (user_memcpy(enable.enable_bits, &enable_bits, 188 sizeof(enable_bits)) != B_OK 189 || user_memcpy(buffer, &enable, 190 sizeof(multi_channel_enable)) != B_OK) { 191 return B_BAD_ADDRESS; 192 } 193 194 return B_OK; 195 } 196 case B_MULTI_SET_ENABLED_CHANNELS: 197 { 198 multi_channel_enable enable; 199 uint32 enable_bits; 200 uchar* orig_enable_bits; 201 202 if (user_memcpy(&enable, buffer, sizeof(enable)) != B_OK 203 || !IS_USER_ADDRESS(enable.enable_bits)) { 204 return B_BAD_ADDRESS; 205 } 206 207 orig_enable_bits = enable.enable_bits; 208 enable.enable_bits = (uchar*)&enable_bits; 209 status_t status = _MultiSetEnabledChannels(&enable); 210 if (status != B_OK) 211 return status; 212 213 enable.enable_bits = orig_enable_bits; 214 if (user_memcpy(enable.enable_bits, &enable_bits, 215 sizeof(enable_bits)) < B_OK 216 || user_memcpy(buffer, &enable, sizeof(multi_channel_enable)) 217 < B_OK) { 218 return B_BAD_ADDRESS; 219 } 220 221 return B_OK; 222 } 223 case B_MULTI_GET_GLOBAL_FORMAT: 224 { 225 multi_format_info info; 226 if (user_memcpy(&info, buffer, sizeof(multi_format_info)) != B_OK) 227 return B_BAD_ADDRESS; 228 229 status_t status = _MultiGetGlobalFormat(&info); 230 if (status != B_OK) 231 return status; 232 if (user_memcpy(buffer, &info, sizeof(multi_format_info)) != B_OK) 233 return B_BAD_ADDRESS; 234 return B_OK; 235 } 236 case B_MULTI_SET_GLOBAL_FORMAT: 237 { 238 multi_format_info info; 239 if (user_memcpy(&info, buffer, sizeof(multi_format_info)) != B_OK) 240 return B_BAD_ADDRESS; 241 242 status_t status = _MultiSetGlobalFormat(&info); 243 if (status != B_OK) 244 return status; 245 return user_memcpy(buffer, &info, sizeof(multi_format_info)); 246 } 247 case B_MULTI_GET_CHANNEL_FORMATS: 248 TRACE(ERR, "B_MULTI_GET_CHANNEL_FORMATS n/i\n"); 249 return B_ERROR; 250 251 case B_MULTI_SET_CHANNEL_FORMATS: 252 TRACE(ERR, "B_MULTI_SET_CHANNEL_FORMATS n/i\n"); 253 return B_ERROR; 254 255 case B_MULTI_GET_MIX: 256 case B_MULTI_SET_MIX: { 257 multi_mix_value_info info; 258 if (user_memcpy(&info, buffer, sizeof(multi_mix_value_info)) != B_OK) 259 return B_BAD_ADDRESS; 260 261 multi_mix_value* originalValues = info.values; 262 size_t mixValueSize = info.item_count * sizeof(multi_mix_value); 263 multi_mix_value* values = (multi_mix_value*)alloca(mixValueSize); 264 if (user_memcpy(values, info.values, mixValueSize) != B_OK) 265 return B_BAD_ADDRESS; 266 info.values = values; 267 268 status_t status; 269 if (op == B_MULTI_GET_MIX) 270 status = _MultiGetMix(&info); 271 else 272 status = _MultiSetMix(&info); 273 if (status != B_OK) 274 return status; 275 // the multi_mix_value_info is not modified 276 return user_memcpy(originalValues, values, mixValueSize); 277 } 278 279 case B_MULTI_LIST_MIX_CHANNELS: 280 TRACE(ERR, "B_MULTI_LIST_MIX_CHANNELS n/i\n"); 281 return B_ERROR; 282 283 case B_MULTI_LIST_MIX_CONTROLS: 284 { 285 multi_mix_control_info info; 286 multi_mix_control* original_controls; 287 size_t allocSize; 288 multi_mix_control *controls; 289 290 if (user_memcpy(&info, buffer, sizeof(multi_mix_control_info)) 291 != B_OK) { 292 return B_BAD_ADDRESS; 293 } 294 295 original_controls = info.controls; 296 allocSize = sizeof(multi_mix_control) * info.control_count; 297 controls = (multi_mix_control *)malloc(allocSize); 298 if (controls == NULL) 299 return B_NO_MEMORY; 300 301 if (!IS_USER_ADDRESS(info.controls) 302 || user_memcpy(controls, info.controls, allocSize) < B_OK) { 303 free(controls); 304 return B_BAD_ADDRESS; 305 } 306 info.controls = controls; 307 308 status_t status = _MultiListMixControls(&info); 309 if (status != B_OK) { 310 free(controls); 311 return status; 312 } 313 314 info.controls = original_controls; 315 status = user_memcpy(info.controls, controls, allocSize); 316 if (status == B_OK) { 317 status = user_memcpy(buffer, &info, 318 sizeof(multi_mix_control_info)); 319 } 320 if (status != B_OK) 321 status = B_BAD_ADDRESS; 322 free(controls); 323 return status; 324 } 325 case B_MULTI_LIST_MIX_CONNECTIONS: 326 TRACE(ERR, "B_MULTI_LIST_MIX_CONNECTIONS n/i\n"); 327 return B_ERROR; 328 329 case B_MULTI_GET_BUFFERS: 330 // Fill out the struct for the first time; doesn't start anything. 331 { 332 multi_buffer_list list; 333 if (user_memcpy(&list, buffer, sizeof(multi_buffer_list)) != B_OK) 334 return B_BAD_ADDRESS; 335 buffer_desc **original_playback_descs = list.playback_buffers; 336 buffer_desc **original_record_descs = list.record_buffers; 337 338 buffer_desc *playback_descs[list.request_playback_buffers]; 339 buffer_desc *record_descs[list.request_record_buffers]; 340 341 if (!IS_USER_ADDRESS(list.playback_buffers) 342 || user_memcpy(playback_descs, list.playback_buffers, 343 sizeof(buffer_desc*) * list.request_playback_buffers) 344 < B_OK 345 || !IS_USER_ADDRESS(list.record_buffers) 346 || user_memcpy(record_descs, list.record_buffers, 347 sizeof(buffer_desc*) * list.request_record_buffers) 348 < B_OK) { 349 return B_BAD_ADDRESS; 350 } 351 352 list.playback_buffers = playback_descs; 353 list.record_buffers = record_descs; 354 status_t status = _MultiGetBuffers(&list); 355 if (status != B_OK) 356 return status; 357 358 list.playback_buffers = original_playback_descs; 359 list.record_buffers = original_record_descs; 360 361 if (user_memcpy(buffer, &list, sizeof(multi_buffer_list)) < B_OK 362 || user_memcpy(original_playback_descs, playback_descs, 363 sizeof(buffer_desc*) * list.request_playback_buffers) 364 < B_OK 365 || user_memcpy(original_record_descs, record_descs, 366 sizeof(buffer_desc*) * list.request_record_buffers) 367 < B_OK) { 368 status = B_BAD_ADDRESS; 369 } 370 371 return status; 372 } 373 374 case B_MULTI_SET_BUFFERS: 375 // Set what buffers to use, if the driver supports soft buffers. 376 TRACE(ERR, "B_MULTI_SET_BUFFERS n/i\n"); 377 return B_ERROR; /* we do not support soft buffers */ 378 379 case B_MULTI_SET_START_TIME: 380 // When to actually start 381 TRACE(ERR, "B_MULTI_SET_START_TIME n/i\n"); 382 return B_ERROR; 383 384 case B_MULTI_BUFFER_EXCHANGE: 385 // stop and go are derived from this being called 386 return _MultiBufferExchange((multi_buffer_info*)buffer); 387 388 case B_MULTI_BUFFER_FORCE_STOP: 389 // force stop of playback, nothing in data 390 return _MultiBufferForceStop(); 391 392 default: 393 TRACE(ERR, "Unhandled IOCTL catched: %#010x\n", op); 394 } 395 396 return B_DEV_INVALID_IOCTL; 397 } 398 399 400 void 401 Device::Removed() 402 { 403 fRemoved = true; 404 405 for (int i = 0; i < fStreams.Count(); i++) 406 fStreams[i]->OnRemove(); 407 } 408 409 410 status_t 411 Device::SetupDevice(bool deviceReplugged) 412 { 413 return B_OK; 414 } 415 416 417 status_t 418 Device::CompareAndReattach(usb_device device) 419 { 420 const usb_device_descriptor* deviceDescriptor 421 = gUSBModule->get_device_descriptor(device); 422 423 if (deviceDescriptor == NULL) { 424 TRACE(ERR, "Error of getting USB device descriptor.\n"); 425 return B_ERROR; 426 } 427 428 if (deviceDescriptor->vendor_id != fVendorID 429 && deviceDescriptor->product_id != fProductID) 430 // this certainly isn't the same device 431 return B_BAD_VALUE; 432 433 // this is the same device that was replugged - clear the removed state, 434 // re- setup the endpoints and transfers and open the device if it was 435 // previously opened 436 fDevice = device; 437 fRemoved = false; 438 status_t result = _SetupEndpoints(); 439 if (result != B_OK) { 440 fRemoved = true; 441 return result; 442 } 443 444 // we need to setup hardware on device replug 445 result = SetupDevice(true); 446 if (result != B_OK) 447 return result; 448 449 if (fOpen) { 450 fOpen = false; 451 result = Open(fNonBlocking ? O_NONBLOCK : 0); 452 } 453 454 return result; 455 } 456 457 458 status_t 459 Device::_MultiGetDescription(multi_description* multiDescription) 460 { 461 multi_description Description; 462 if (user_memcpy(&Description, multiDescription, 463 sizeof(multi_description)) != B_OK) 464 return B_BAD_ADDRESS; 465 466 Description.interface_version = B_CURRENT_INTERFACE_VERSION; 467 Description.interface_minimum = B_CURRENT_INTERFACE_VERSION; 468 469 strlcpy(Description.friendly_name, "USB Audio", 470 sizeof(Description.friendly_name)); 471 472 strlcpy(Description.vendor_info, "S.Zharski", 473 sizeof(Description.vendor_info)); 474 475 Description.output_channel_count = 0; 476 Description.input_channel_count = 0; 477 Description.output_bus_channel_count = 0; 478 Description.input_bus_channel_count = 0; 479 Description.aux_bus_channel_count = 0; 480 481 Description.output_rates = 0; 482 Description.input_rates = 0; 483 484 Description.min_cvsr_rate = 0; 485 Description.max_cvsr_rate = 0; 486 487 Description.output_formats = 0; 488 Description.input_formats = 0; 489 Description.lock_sources = B_MULTI_LOCK_INTERNAL; 490 Description.timecode_sources = 0; 491 Description.interface_flags = 0; 492 Description.start_latency = 3000; 493 494 Description.control_panel[0] = '\0'; 495 496 Vector<_AudioControl*> USBTerminals; 497 498 // channels (USB I/O terminals) are already in fStreams 499 // in outputs->inputs order, use them. 500 for (int i = 0; i < fStreams.Count(); i++) { 501 uint8 id = fStreams[i]->TerminalLink(); 502 _AudioControl* control = fAudioControl.Find(id); 503 // if (control->SubType() == USB_AUDIO_AC_OUTPUT_TERMINAL) { 504 // if (control->SubType() == USB_AUDIO_AC_INPUT_TERMINAL) { 505 // USBTerminals.PushFront(control); 506 // fStreams[i]->GetFormatsAndRates(Description); 507 // } else 508 // if (control->SubType() == IDSInputTerminal) { 509 USBTerminals.PushBack(control); 510 fStreams[i]->GetFormatsAndRates(&Description); 511 // } 512 } 513 514 Vector<multi_channel_info> Channels; 515 fAudioControl.GetChannelsDescription(Channels, &Description, USBTerminals); 516 fAudioControl.GetBusChannelsDescription(Channels, &Description ); 517 518 // Description.request_channel_count = channels + bus_channels; 519 520 TraceMultiDescription(&Description, Channels); 521 522 if (user_memcpy(multiDescription, &Description, 523 sizeof(multi_description)) != B_OK) 524 return B_BAD_ADDRESS; 525 526 if (user_memcpy(multiDescription->channels, 527 &Channels[0], sizeof(multi_channel_info) * min_c(Channels.Count(), 528 Description.request_channel_count)) != B_OK) 529 return B_BAD_ADDRESS; 530 531 return B_OK; 532 } 533 534 535 void 536 Device::TraceMultiDescription(multi_description* Description, 537 Vector<multi_channel_info>& Channels) 538 { 539 TRACE(API, "interface_version:%d\n", Description->interface_version); 540 TRACE(API, "interface_minimum:%d\n", Description->interface_minimum); 541 TRACE(API, "friendly_name:%s\n", Description->friendly_name); 542 TRACE(API, "vendor_info:%s\n", Description->vendor_info); 543 TRACE(API, "output_channel_count:%d\n", Description->output_channel_count); 544 TRACE(API, "input_channel_count:%d\n", Description->input_channel_count); 545 TRACE(API, "output_bus_channel_count:%d\n", 546 Description->output_bus_channel_count); 547 TRACE(API, "input_bus_channel_count:%d\n", 548 Description->input_bus_channel_count); 549 TRACE(API, "aux_bus_channel_count:%d\n", Description->aux_bus_channel_count); 550 TRACE(API, "output_rates:%#08x\n", Description->output_rates); 551 TRACE(API, "input_rates:%#08x\n", Description->input_rates); 552 TRACE(API, "min_cvsr_rate:%f\n", Description->min_cvsr_rate); 553 TRACE(API, "max_cvsr_rate:%f\n", Description->max_cvsr_rate); 554 TRACE(API, "output_formats:%#08x\n", Description->output_formats); 555 TRACE(API, "input_formats:%#08x\n", Description->input_formats); 556 TRACE(API, "lock_sources:%d\n", Description->lock_sources); 557 TRACE(API, "timecode_sources:%d\n", Description->timecode_sources); 558 TRACE(API, "interface_flags:%#08x\n", Description->interface_flags); 559 TRACE(API, "start_latency:%d\n", Description->start_latency); 560 TRACE(API, "control_panel:%s\n", Description->control_panel); 561 562 // multi_channel_info* Channels = Description->channels; 563 // for (int i = 0; i < Description->request_channel_count; i++) { 564 for (int i = 0; i < Channels.Count(); i++) { 565 TRACE(API, " channel_id:%d\n", Channels[i].channel_id); 566 TRACE(API, " kind:%#02x\n", Channels[i].kind); 567 TRACE(API, " designations:%#08x\n", Channels[i].designations); 568 TRACE(API, " connectors:%#08x\n", Channels[i].connectors); 569 } 570 571 TRACE(API, "request_channel_count:%d\n\n", 572 Description->request_channel_count); 573 } 574 575 576 status_t 577 Device::_MultiGetEnabledChannels(multi_channel_enable* Enable) 578 { 579 status_t status = B_OK; 580 581 Enable->lock_source = B_MULTI_LOCK_INTERNAL; 582 583 uint32 offset = 0; 584 for (int i = 0; i < fStreams.Count() && status == B_OK; i++) 585 status = fStreams[i]->GetEnabledChannels(offset, Enable); 586 587 return status; 588 } 589 590 591 status_t 592 Device::_MultiSetEnabledChannels(multi_channel_enable* Enable) 593 { 594 status_t status = B_OK; 595 uint32 offset = 0; 596 for (int i = 0; i < fStreams.Count() && status == B_OK; i++) 597 status = fStreams[i]->SetEnabledChannels(offset, Enable); 598 599 return status; 600 } 601 602 603 status_t 604 Device::_MultiGetGlobalFormat(multi_format_info* Format) 605 { 606 status_t status = B_OK; 607 608 Format->output_latency = 0; 609 Format->input_latency = 0; 610 Format->timecode_kind = 0; 611 612 // uint32 offset = 0; 613 for (int i = 0; i < fStreams.Count() && status == B_OK; i++) 614 status = fStreams[i]->GetGlobalFormat(Format); 615 616 return status; 617 } 618 619 620 status_t 621 Device::_MultiSetGlobalFormat(multi_format_info* Format) 622 { 623 status_t status = B_OK; 624 625 TRACE(API, "output_latency:%lld\n", Format->output_latency); 626 TRACE(API, "input_latency:%lld\n", Format->input_latency); 627 TRACE(API, "timecode_kind:%#08x\n", Format->timecode_kind); 628 629 // uint32 offset = 0; 630 for (int i = 0; i < fStreams.Count() && status == B_OK; i++) 631 status = fStreams[i]->SetGlobalFormat(Format); 632 633 return status; 634 } 635 636 637 status_t 638 Device::_MultiGetBuffers(multi_buffer_list* List) 639 { 640 status_t status = B_OK; 641 642 TRACE(API, "info_size:%d\n" 643 "request_playback_buffers:%d\n" 644 "request_playback_channels:%d\n" 645 "request_playback_buffer_size:%d\n" 646 "request_record_buffers:%d\n" 647 "request_record_channels:%d\n" 648 "request_record_buffer_size:%d\n", 649 List->info_size, 650 List->request_playback_buffers, 651 List->request_playback_channels, 652 List->request_playback_buffer_size, 653 List->request_record_buffers, 654 List->request_record_channels, 655 List->request_record_buffer_size); 656 657 List->flags = 0; 658 List->return_playback_channels = 0; 659 List->return_record_channels = 0; 660 661 for (int i = 0; i < fStreams.Count() && status == B_OK; i++) 662 status = fStreams[i]->GetBuffers(List); 663 664 TRACE(API, "flags:%#x\n" 665 "return_playback_buffers:%d\n" 666 "return_playback_channels:%d\n" 667 "return_playback_buffer_size:%d\n" 668 "return_record_buffers:%d\n" 669 "return_record_channels:%d\n" 670 "return_record_buffer_size:%d\n", 671 List->flags, 672 List->return_playback_buffers, 673 List->return_playback_channels, 674 List->return_playback_buffer_size, 675 List->return_record_buffers, 676 List->return_record_channels, 677 List->return_record_buffer_size); 678 679 #if 0 680 TRACE(API, "playback buffers\n"); 681 for (int32_t b = 0; b < List->return_playback_buffers; b++) 682 for (int32 c = 0; c < List->return_playback_channels; c++) 683 TRACE(API, "%d:%d %08x:%d\n", b, c, List->playback_buffers[b][c].base, 684 List->playback_buffers[b][c].stride); 685 686 TRACE(API, "record buffers:\n"); 687 for (int32_t b = 0; b < List->return_record_buffers; b++) 688 for (int32 c = 0; c < List->return_record_channels; c++) 689 TRACE(API, "%d:%d %08x:%d\n", b, c, List->record_buffers[b][c].base, 690 List->record_buffers[b][c].stride); 691 #endif 692 return B_OK; 693 } 694 695 696 status_t 697 Device::_MultiBufferExchange(multi_buffer_info* multiInfo) 698 { 699 multi_buffer_info Info; 700 if (!IS_USER_ADDRESS(multiInfo) 701 || user_memcpy(&Info, multiInfo, sizeof(multi_buffer_info)) != B_OK) { 702 return B_BAD_ADDRESS; 703 } 704 705 for (int i = 0; i < fStreams.Count(); i++) 706 if (!fStreams[i]->IsRunning()) 707 fStreams[i]->Start(); 708 709 status_t status = acquire_sem_etc(fBuffersReadySem, 1, 710 B_RELATIVE_TIMEOUT | B_CAN_INTERRUPT, 50000); 711 if (status == B_TIMED_OUT) { 712 TRACE(ERR, "Timeout during buffers exchange.\n"); 713 return status; 714 } 715 716 status = B_ERROR; 717 for (int i = 0; i < fStreams.Count(); i++) 718 if (fStreams[i]->ExchangeBuffer(&Info)) { 719 status = B_OK; 720 break; 721 } 722 723 if (status != B_OK) { 724 TRACE(ERR, "Error processing buffers:%08x.\n", status); 725 return status; 726 } 727 728 if (user_memcpy(multiInfo, &Info, sizeof(multi_buffer_info)) != B_OK) 729 return B_BAD_ADDRESS; 730 731 return status; 732 } 733 734 735 status_t 736 Device::_MultiBufferForceStop() 737 { 738 for (int i = 0; i < fStreams.Count(); i++) 739 fStreams[i]->Stop(); 740 return B_OK; 741 } 742 743 744 status_t 745 Device::_MultiGetMix(multi_mix_value_info* Info) 746 { 747 return fAudioControl.GetMix(Info); 748 } 749 750 751 status_t 752 Device::_MultiSetMix(multi_mix_value_info* Info) 753 { 754 return fAudioControl.SetMix(Info); 755 } 756 757 758 status_t 759 Device::_MultiListMixControls(multi_mix_control_info* Info) 760 { 761 status_t status = fAudioControl.ListMixControls(Info); 762 TraceListMixControls(Info); 763 return status; 764 } 765 766 767 void 768 Device::TraceListMixControls(multi_mix_control_info* Info) 769 { 770 TRACE(MIX, "control_count:%d\n.", Info->control_count); 771 772 int32 i = 0; 773 while (Info->controls[i].id > 0) { 774 multi_mix_control &c = Info->controls[i]; 775 TRACE(MIX, "id:%#08x\n", c.id); 776 TRACE(MIX, "flags:%#08x\n", c.flags); 777 TRACE(MIX, "master:%#08x\n", c.master); 778 TRACE(MIX, "parent:%#08x\n", c.parent); 779 TRACE(MIX, "string:%d\n", c.string); 780 TRACE(MIX, "name:%s\n", c.name); 781 i++; 782 } 783 } 784 785 786 status_t 787 Device::_SetupEndpoints() 788 { 789 const usb_configuration_info* config 790 = gUSBModule->get_nth_configuration(fDevice, 0); 791 792 if (config == NULL) { 793 TRACE(ERR, "Error of getting USB device configuration.\n"); 794 return B_ERROR; 795 } 796 797 if (config->interface_count <= 0) { 798 TRACE(ERR, "Error:no interfaces found in USB device configuration\n"); 799 return B_ERROR; 800 } 801 802 for (size_t i = 0; i < config->interface_count; i++) { 803 usb_interface_info* Interface = config->interface[i].active; 804 if (Interface->descr->interface_class != USB_AUDIO_INTERFACE_AUDIO_CLASS) 805 continue; 806 807 switch (Interface->descr->interface_subclass) { 808 case USB_AUDIO_INTERFACE_AUDIOCONTROL_SUBCLASS: 809 fAudioControl.Init(i, Interface); 810 break; 811 case USB_AUDIO_INTERFACE_AUDIOSTREAMING_SUBCLASS: 812 { 813 Stream* stream = new(std::nothrow) Stream(this, i, 814 &config->interface[i]); 815 if (B_OK == stream->Init()) { 816 // put the stream in the correct order: 817 // first output that input ones. 818 if (stream->IsInput()) 819 fStreams.PushBack(stream); 820 else 821 fStreams.PushFront(stream); 822 } else 823 delete stream; 824 } 825 break; 826 default: 827 TRACE(ERR, "Ignore interface of unsupported subclass %#x.\n", 828 Interface->descr->interface_subclass); 829 break; 830 } 831 } 832 833 if (fAudioControl.InitCheck() == B_OK && fStreams.Count() > 0) { 834 TRACE(INF, "Found device %#06x:%#06x\n", fVendorID, fProductID); 835 gUSBModule->set_configuration(fDevice, config); 836 837 for (int i = 0; i < fStreams.Count(); i++) 838 fStreams[i]->OnSetConfiguration(fDevice, config); 839 840 return B_OK; 841 } 842 843 return B_NO_INIT; 844 } 845 846 847 status_t 848 Device::StopDevice() 849 { 850 status_t result = B_OK; 851 852 if (result != B_OK) 853 TRACE(ERR, "Error of writing %#04x RX Control:%#010x\n", 0, result); 854 855 //TRACE_RET(result); 856 return result; 857 } 858 859