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 "Stream.h" 10 11 #include <kernel.h> 12 #include <usb/USB_audio.h> 13 14 #include "Device.h" 15 #include "Driver.h" 16 #include "Settings.h" 17 18 19 Stream::Stream(Device* device, size_t interface, usb_interface_list* List) 20 : 21 AudioStreamingInterface(&device->AudioControl(), interface, List), 22 fDevice(device), 23 fStatus(B_NO_INIT), 24 fStreamEndpoint(0), 25 fIsRunning(false), 26 fArea(-1), 27 fAreaSize(0), 28 fDescriptors(NULL), 29 fDescriptorsCount(0), 30 fCurrentBuffer(0), 31 fStartingFrame(0), 32 fSamplesCount(0), 33 fPacketSize(0), 34 fProcessedBuffers(0), 35 fInsideNotify(0) 36 { 37 } 38 39 40 Stream::~Stream() 41 { 42 delete_area(fArea); 43 } 44 45 46 status_t 47 Stream::_ChooseAlternate() 48 { 49 // lookup alternate with maximal (ch * 100 + resolution) 50 uint16 maxChxRes = 0; 51 for (int i = 0; i < fAlternates.Count(); i++) { 52 if (fAlternates[i]->Interface() == 0) { 53 TRACE(INF, "Ignore alternate %d - zero interface description.\n", i); 54 continue; 55 } 56 57 if (fAlternates[i]->Format() == 0) { 58 TRACE(INF, "Ignore alternate %d - zero format description.\n", i); 59 continue; 60 } 61 62 if (fAlternates[i]->Format()->fFormatType 63 != USB_AUDIO_FORMAT_TYPE_I) { 64 TRACE(ERR, "Ignore alternate %d - format type %#02x " 65 "is not supported.\n", i, fAlternates[i]->Format()->fFormatType); 66 continue; 67 } 68 69 switch (fAlternates[i]->Interface()->fFormatTag) { 70 case USB_AUDIO_FORMAT_PCM: 71 case USB_AUDIO_FORMAT_PCM8: 72 case USB_AUDIO_FORMAT_IEEE_FLOAT: 73 // case USB_AUDIO_FORMAT_ALAW: 74 // case USB_AUDIO_FORMAT_MULAW: 75 break; 76 default: 77 TRACE(ERR, "Ignore alternate %d - format %#04x is not " 78 "supported.\n", i, fAlternates[i]->Interface()->fFormatTag); 79 continue; 80 } 81 82 TypeIFormatDescriptor* format 83 = static_cast<TypeIFormatDescriptor*>(fAlternates[i]->Format()); 84 85 if (format->fNumChannels > 2) { 86 TRACE(ERR, "Ignore alternate %d - channel count %d " 87 "is not supported.\n", i, format->fNumChannels); 88 continue; 89 } 90 91 if (fAlternates[i]->Interface()->fFormatTag == USB_AUDIO_FORMAT_PCM) { 92 switch(format->fBitResolution) { 93 default: 94 TRACE(ERR, "Ignore alternate %d - bit resolution %d " 95 "is not supported.\n", i, format->fBitResolution); 96 continue; 97 case 8: case 16: case 18: case 20: case 24: case 32: 98 break; 99 } 100 } 101 102 uint16 chxRes = format->fNumChannels * 100 + format->fBitResolution; 103 if (chxRes > maxChxRes) { 104 maxChxRes = chxRes; 105 fActiveAlternate = i; 106 } 107 } 108 109 if (maxChxRes <= 0) { 110 TRACE(ERR, "No compatible alternate found. " 111 "Stream initialization failed.\n"); 112 return B_NO_INIT; 113 } 114 115 const ASEndpointDescriptor* endpoint 116 = fAlternates[fActiveAlternate]->Endpoint(); 117 fIsInput = (endpoint->fEndpointAddress & USB_ENDPOINT_ADDR_DIR_IN) 118 == USB_ENDPOINT_ADDR_DIR_IN; 119 120 if (fIsInput) 121 fCurrentBuffer = (size_t)-1; 122 123 TRACE(INF, "Alternate %d EP:%x selected for %s!\n", 124 fActiveAlternate, endpoint->fEndpointAddress, 125 fIsInput ? "recording" : "playback"); 126 127 return B_OK; 128 } 129 130 131 status_t 132 Stream::Init() 133 { 134 fStatus = _ChooseAlternate(); 135 return fStatus; 136 } 137 138 139 void 140 Stream::OnRemove() 141 { 142 // the transfer callback schedule traffic - so we must ensure that we are 143 // not inside the callback anymore before returning, as we would otherwise 144 // violate the promise not to use any of the pipes after returning from the 145 // removed callback 146 while (atomic_add(&fInsideNotify, 0) != 0) 147 snooze(100); 148 149 gUSBModule->cancel_queued_transfers(fStreamEndpoint); 150 } 151 152 153 status_t 154 Stream::_SetupBuffers() 155 { 156 // allocate buffer for worst (maximal size) case 157 TypeIFormatDescriptor* format = static_cast<TypeIFormatDescriptor*>( 158 fAlternates[fActiveAlternate]->Format()); 159 160 uint32 samplingRate = fAlternates[fActiveAlternate]->GetSamplingRate(); 161 uint32 sampleSize = format->fNumChannels * format->fSubframeSize; 162 163 // data size pro 1 ms USB 1 frame or 1/8 ms USB 2 microframe 164 fPacketSize = samplingRate * sampleSize 165 / (fDevice->fUSBVersion < 0x0200 ? 1000 : 8000); 166 TRACE(INF, "packetSize:%ld\n", fPacketSize); 167 168 if (fPacketSize == 0) { 169 TRACE(ERR, "computed packet size is 0!"); 170 return B_BAD_VALUE; 171 } 172 173 if (fArea != -1) { 174 Stop(); 175 delete_area(fArea); 176 } 177 178 fAreaSize = (sizeof(usb_iso_packet_descriptor) + fPacketSize) 179 * sampleSize * 1024 / fPacketSize; 180 TRACE(INF, "estimate fAreaSize:%d\n", fAreaSize); 181 182 // round up to B_PAGE_SIZE and create area 183 fAreaSize = (fAreaSize + (B_PAGE_SIZE - 1)) &~ (B_PAGE_SIZE - 1); 184 TRACE(INF, "rounded up fAreaSize:%d\n", fAreaSize); 185 186 fArea = create_area( (fIsInput) ? DRIVER_NAME "_record_area" 187 : DRIVER_NAME "_playback_area", (void**)&fDescriptors, 188 B_ANY_KERNEL_ADDRESS, fAreaSize, B_CONTIGUOUS, 189 B_READ_AREA | B_WRITE_AREA); 190 191 if (fArea < 0) { 192 TRACE(ERR, "Error of creating %#x - " 193 "bytes size buffer area:%#010x\n", fAreaSize, fArea); 194 fStatus = fArea; 195 return fStatus; 196 } 197 198 TRACE(INF, "Created area id:%d at addr:%#010x size:%#010lx\n", 199 fArea, fDescriptors, fAreaSize); 200 201 // descriptors count 202 fDescriptorsCount = fAreaSize 203 / (sizeof(usb_iso_packet_descriptor) + fPacketSize); 204 205 // we need same size sub-buffers. round it 206 fDescriptorsCount /= kSamplesBufferCount; 207 fDescriptorsCount *= kSamplesBufferCount; 208 TRACE(INF, "descriptorsCount:%d\n", fDescriptorsCount); 209 210 // samples count 211 fSamplesCount = fDescriptorsCount * fPacketSize / sampleSize; 212 TRACE(INF, "samplesCount:%d\n", fSamplesCount); 213 214 // initialize descriptors array 215 for (size_t i = 0; i < fDescriptorsCount; i++) { 216 fDescriptors[i].request_length = fPacketSize; 217 fDescriptors[i].actual_length = 0; 218 fDescriptors[i].status = B_OK; 219 } 220 221 return fStatus; 222 } 223 224 225 status_t 226 Stream::OnSetConfiguration(usb_device device, 227 const usb_configuration_info* config) 228 { 229 if (config == NULL) { 230 TRACE(ERR, "NULL configuration. Not set.\n"); 231 return B_ERROR; 232 } 233 234 usb_interface_info* interface 235 = &config->interface[fInterface].alt[fActiveAlternate]; 236 if (interface == NULL) { 237 TRACE(ERR, "NULL interface. Not set.\n"); 238 return B_ERROR; 239 } 240 241 status_t status = gUSBModule->set_alt_interface(device, interface); 242 uint8 address = fAlternates[fActiveAlternate]->Endpoint()->fEndpointAddress; 243 244 TRACE(INF, "set_alt_interface %x\n", status); 245 246 for (size_t i = 0; i < interface->endpoint_count; i++) { 247 if (address == interface->endpoint[i].descr->endpoint_address) { 248 fStreamEndpoint = interface->endpoint[i].handle; 249 TRACE(INF, "%s Stream Endpoint [address %#04x] handle is: %#010x.\n", 250 fIsInput ? "Input" : "Output", address, fStreamEndpoint); 251 return B_OK; 252 } 253 } 254 255 TRACE(INF, "%s Stream Endpoint [address %#04x] was not found.\n", 256 fIsInput ? "Input" : "Output", address); 257 return B_ERROR; 258 } 259 260 261 status_t 262 Stream::Start() 263 { 264 status_t result = B_BUSY; 265 if (!fIsRunning) { 266 for (size_t i = 0; i < kSamplesBufferCount; i++) 267 result = _QueueNextTransfer(i, i == 0); 268 fIsRunning = result == B_OK; 269 } 270 return result; 271 } 272 273 274 status_t 275 Stream::Stop() 276 { 277 if (fIsRunning) { 278 // wait until possible notification handling finished... 279 while (atomic_add(&fInsideNotify, 0) != 0) 280 snooze(100); 281 fIsRunning = false; 282 } 283 gUSBModule->cancel_queued_transfers(fStreamEndpoint); 284 285 return B_OK; 286 } 287 288 289 status_t 290 Stream::_QueueNextTransfer(size_t queuedBuffer, bool start) 291 { 292 TypeIFormatDescriptor* format = static_cast<TypeIFormatDescriptor*>( 293 fAlternates[fActiveAlternate]->Format()); 294 295 size_t bufferSize = format->fNumChannels * format->fSubframeSize; 296 bufferSize *= fSamplesCount / kSamplesBufferCount; 297 298 uint8* buffers = (uint8*)(fDescriptors + fDescriptorsCount); 299 300 size_t packetsCount = fDescriptorsCount / kSamplesBufferCount; 301 302 TRACE(DTA, "buffers:%#010x[%#x]\ndescrs:%#010x[%#x]\n", 303 buffers + bufferSize * queuedBuffer, bufferSize, 304 fDescriptors + queuedBuffer * packetsCount, packetsCount); 305 306 status_t status = gUSBModule->queue_isochronous(fStreamEndpoint, 307 buffers + bufferSize * queuedBuffer, bufferSize, 308 fDescriptors + queuedBuffer * packetsCount, packetsCount, 309 &fStartingFrame, start ? USB_ISO_ASAP : 0, 310 Stream::_TransferCallback, this); 311 312 TRACE(DTA, "frame:%#010x\n", fStartingFrame); 313 return status; // B_OK; 314 } 315 316 317 void 318 Stream::_TransferCallback(void* cookie, status_t status, void* data, 319 size_t actualLength) 320 { 321 Stream* stream = (Stream*)cookie; 322 atomic_add(&stream->fInsideNotify, 1); 323 if (status == B_CANCELED || stream->fDevice->fRemoved || !stream->fIsRunning) { 324 atomic_add(&stream->fInsideNotify, -1); 325 TRACE(ERR, "Cancelled: c:%p st:%#010x, data:%#010x, len:%d\n", 326 cookie, status, data, actualLength); 327 return; 328 } 329 330 stream->fCurrentBuffer = (stream->fCurrentBuffer + 1) % kSamplesBufferCount; 331 332 stream->_DumpDescriptors(); 333 334 /*status_t result =*/ stream->_QueueNextTransfer(stream->fCurrentBuffer, false); 335 336 if (atomic_add(&stream->fProcessedBuffers, 1) > (int32)kSamplesBufferCount) 337 TRACE(ERR, "Processed buffers overflow:%d\n", stream->fProcessedBuffers); 338 339 release_sem_etc(stream->fDevice->fBuffersReadySem, 1, B_DO_NOT_RESCHEDULE); 340 341 TRACE(DTA, "st:%#010x, data:%#010x, len:%d\n", status, data, actualLength); 342 343 atomic_add(&stream->fInsideNotify, -1); 344 } 345 346 347 void 348 Stream::_DumpDescriptors() 349 { 350 //size_t packetsCount = fDescriptorsCount / kSamplesBufferCount; 351 size_t from = /*fCurrentBuffer > 0 ? packetsCount :*/ 0 ; 352 size_t to = /*fCurrentBuffer > 0 ?*/ fDescriptorsCount /*: packetsCount*/ ; 353 for (size_t i = from; i < to; i++) 354 TRACE(ISO, "%d:req_len:%d; act_len:%d; stat:%#010x\n", i, 355 fDescriptors[i].request_length, fDescriptors[i].actual_length, 356 fDescriptors[i].status); 357 } 358 359 360 status_t 361 Stream::GetEnabledChannels(uint32& offset, multi_channel_enable* Enable) 362 { 363 AudioChannelCluster* cluster = ChannelCluster(); 364 if (cluster == 0) 365 return B_ERROR; 366 367 for (size_t i = 0; i < cluster->ChannelsCount(); i++) { 368 B_SET_CHANNEL(Enable->enable_bits, offset++, true); 369 TRACE(INF, "Report channel %d as enabled.\n", offset); 370 } 371 372 return B_OK; 373 } 374 375 376 status_t 377 Stream::SetEnabledChannels(uint32& offset, multi_channel_enable* Enable) 378 { 379 AudioChannelCluster* cluster = ChannelCluster(); 380 if (cluster == 0) 381 return B_ERROR; 382 383 for (size_t i = 0; i < cluster->ChannelsCount(); i++, offset++) { 384 TRACE(INF, "%s channel %d.\n", 385 (B_TEST_CHANNEL(Enable->enable_bits, offset) 386 ? "Enable" : "Disable"), offset + 1); 387 } 388 389 return B_OK; 390 } 391 392 393 status_t 394 Stream::GetGlobalFormat(multi_format_info* Format) 395 { 396 _multi_format* format = fIsInput ? &Format->input : &Format->output; 397 format->cvsr = fAlternates[fActiveAlternate]->GetSamplingRate(); 398 format->rate = fAlternates[fActiveAlternate]->GetSamplingRateId(0); 399 format->format = fAlternates[fActiveAlternate]->GetFormatId(); 400 TRACE(INF, "%s.rate:%d cvsr:%f format:%#08x\n", 401 fIsInput ? "input" : "ouput", 402 format->rate, format->cvsr, format->format); 403 return B_OK; 404 } 405 406 407 status_t 408 Stream::SetGlobalFormat(multi_format_info* Format) 409 { 410 _multi_format* format = fIsInput ? &Format->input : &Format->output; 411 AudioStreamAlternate* alternate = fAlternates[fActiveAlternate]; 412 if (format->rate == alternate->GetSamplingRateId(0) 413 && format->format == alternate->GetFormatId()) { 414 TRACE(INF, "No changes required\n"); 415 return B_OK; 416 } 417 418 alternate->SetSamplingRateById(format->rate); 419 alternate->SetFormatId(format->format); 420 TRACE(INF, "%s.rate:%d cvsr:%f format:%#08x\n", 421 fIsInput ? "input" : "ouput", 422 format->rate, format->cvsr, format->format); 423 424 // cancel data flow - it will be rewaked at next buffer exchange call 425 Stop(); 426 427 // TODO: wait for cancelling? 428 429 // layout of buffers should be adjusted after changing sampling rate/format 430 status_t status = _SetupBuffers(); 431 432 if (status != B_OK) 433 return status; 434 435 // set endpoint speed 436 uint32 samplingRate = fAlternates[fActiveAlternate]->GetSamplingRate(); 437 size_t actualLength = 0; 438 usb_audio_sampling_freq freq = _ASFormatDescriptor::GetSamFreq(samplingRate); 439 uint8 address = fAlternates[fActiveAlternate]->Endpoint()->fEndpointAddress; 440 441 status = gUSBModule->send_request(fDevice->fDevice, 442 USB_REQTYPE_CLASS | USB_REQTYPE_ENDPOINT_OUT, 443 USB_AUDIO_SET_CUR, USB_AUDIO_SAMPLING_FREQ_CONTROL << 8, 444 address, sizeof(freq), &freq, &actualLength); 445 446 TRACE(ERR, "set_speed %02x%02x%02x for ep %#x %d: %s\n", 447 freq.bytes[0], freq.bytes[1], freq.bytes[2], 448 address, actualLength, strerror(status)); 449 return status; 450 } 451 452 453 status_t 454 Stream::GetBuffers(multi_buffer_list* List) 455 { 456 // TODO: check the available buffers count! 457 if (fAreaSize == 0) 458 return B_NO_INIT; 459 460 int32 startChannel = List->return_playback_channels; 461 buffer_desc** Buffers = List->playback_buffers; 462 463 if (fIsInput) { 464 List->flags |= B_MULTI_BUFFER_RECORD; 465 List->return_record_buffer_size = fSamplesCount / kSamplesBufferCount; 466 List->return_record_buffers = kSamplesBufferCount; 467 startChannel = List->return_record_channels; 468 Buffers = List->record_buffers; 469 470 TRACE(DTA, "flags:%#10x\nreturn_record_buffer_size:%#010x\n" 471 "return_record_buffers:%#010x\n", List->flags, 472 List->return_record_buffer_size, List->return_record_buffers); 473 } else { 474 List->flags |= B_MULTI_BUFFER_PLAYBACK; 475 List->return_playback_buffer_size = fSamplesCount / kSamplesBufferCount; 476 List->return_playback_buffers = kSamplesBufferCount; 477 478 TRACE(DTA, "flags:%#10x\nreturn_playback_buffer_size:%#010x\n" 479 "return_playback_buffers:%#010x\n", List->flags, 480 List->return_playback_buffer_size, List->return_playback_buffers); 481 } 482 483 TypeIFormatDescriptor* format = static_cast<TypeIFormatDescriptor*>( 484 fAlternates[fActiveAlternate]->Format()); 485 // const ASEndpointDescriptor* endpoint 486 // = fAlternates[fActiveAlternate]->Endpoint(); 487 488 // [buffer][channel] init buffers 489 for (size_t buffer = 0; buffer < kSamplesBufferCount; buffer++) { 490 TRACE(DTA, "%s buffer #%d:\n", fIsInput ? "input" : "output", buffer + 1); 491 492 struct buffer_desc descs[format->fNumChannels]; 493 for (size_t channel = startChannel; 494 channel < format->fNumChannels; channel++) { 495 // init stride to the same for all buffers 496 uint32 stride = format->fSubframeSize * format->fNumChannels; 497 descs[channel].stride = stride; 498 499 // init to buffers area begin 500 descs[channel].base 501 = (char*)(fDescriptors + fDescriptorsCount); 502 // shift for whole buffer if required 503 size_t bufferSize = fPacketSize/*endpoint->fMaxPacketSize*/ 504 * (fDescriptorsCount / kSamplesBufferCount); 505 descs[channel].base += buffer * bufferSize; 506 // shift for channel if required 507 descs[channel].base += channel * format->fSubframeSize; 508 509 TRACE(DTA, "%d:%d: base:%#010x; stride:%#010x\n", buffer, channel, 510 descs[channel].base, descs[channel].stride); 511 } 512 if (!IS_USER_ADDRESS(Buffers[buffer]) 513 || user_memcpy(Buffers[buffer], descs, sizeof(descs)) < B_OK) { 514 return B_BAD_ADDRESS; 515 } 516 } 517 518 if (fIsInput) { 519 List->return_record_channels += format->fNumChannels; 520 TRACE(MIX, "return_record_channels:%#010x\n", 521 List->return_record_channels); 522 } else { 523 List->return_playback_channels += format->fNumChannels; 524 TRACE(MIX, "return_playback_channels:%#010x\n", 525 List->return_playback_channels); 526 } 527 528 return B_OK; 529 } 530 531 532 bool 533 Stream::ExchangeBuffer(multi_buffer_info* Info) 534 { 535 if (fProcessedBuffers <= 0) 536 return false; 537 538 if (fIsInput) { 539 Info->recorded_real_time = system_time();// TODO fRealTime; 540 Info->recorded_frames_count += fSamplesCount / kSamplesBufferCount; 541 Info->record_buffer_cycle = fCurrentBuffer; 542 } else { 543 Info->played_real_time = system_time();// TODO fRealTime; 544 Info->played_frames_count += fSamplesCount / kSamplesBufferCount; 545 Info->playback_buffer_cycle = fCurrentBuffer; 546 } 547 548 atomic_add(&fProcessedBuffers, -1); 549 550 return true; 551 } 552 553