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