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