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