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