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 (fArea == -1) { 169 fAreaSize = (sizeof(usb_iso_packet_descriptor) + fPacketSize) 170 * sampleSize * 1024 / fPacketSize; 171 TRACE(INF, "estimate fAreaSize:%d\n", fAreaSize); 172 173 // round up to B_PAGE_SIZE and create area 174 fAreaSize = (fAreaSize + (B_PAGE_SIZE - 1)) &~ (B_PAGE_SIZE - 1); 175 TRACE(INF, "rounded up fAreaSize:%d\n", fAreaSize); 176 177 fArea = create_area( (fIsInput) ? DRIVER_NAME "_record_area" 178 : DRIVER_NAME "_playback_area", (void**)&fDescriptors, 179 B_ANY_KERNEL_ADDRESS, fAreaSize, B_CONTIGUOUS, 180 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); 181 182 if (fArea < 0) { 183 TRACE(ERR, "Error of creating %#x - " 184 "bytes size buffer area:%#010x\n", fAreaSize, fArea); 185 fStatus = fArea; 186 return fStatus; 187 } 188 189 TRACE(INF, "Created area id:%d at addr:%#010x size:%#010lx\n", 190 fArea, fDescriptors, fAreaSize); 191 } 192 193 // descriptors count 194 fDescriptorsCount = fAreaSize 195 / (sizeof(usb_iso_packet_descriptor) + fPacketSize); 196 197 // we need same size sub-buffers. round it 198 fDescriptorsCount /= kSamplesBufferCount; 199 fDescriptorsCount *= kSamplesBufferCount; 200 TRACE(INF, "descriptorsCount:%d\n", fDescriptorsCount); 201 202 // samples count 203 fSamplesCount = fDescriptorsCount * fPacketSize / sampleSize; 204 TRACE(INF, "samplesCount:%d\n", fSamplesCount); 205 206 // initialize descriptors array 207 for (size_t i = 0; i < fDescriptorsCount; i++) { 208 fDescriptors[i].request_length = fPacketSize; 209 fDescriptors[i].actual_length = 0; 210 fDescriptors[i].status = B_OK; 211 } 212 213 return fStatus; 214 } 215 216 217 status_t 218 Stream::OnSetConfiguration(usb_device device, 219 const usb_configuration_info* config) 220 { 221 if (config == NULL) { 222 TRACE(ERR, "NULL configuration. Not set.\n"); 223 return B_ERROR; 224 } 225 226 usb_interface_info* interface 227 = &config->interface[fInterface].alt[fActiveAlternate]; 228 if (interface == NULL) { 229 TRACE(ERR, "NULL interface. Not set.\n"); 230 return B_ERROR; 231 } 232 233 status_t status = gUSBModule->set_alt_interface(device, interface); 234 uint8 address = fAlternates[fActiveAlternate]->Endpoint()->fEndpointAddress; 235 236 TRACE(INF, "set_alt_interface %x\n", status); 237 238 for (size_t i = 0; i < interface->endpoint_count; i++) { 239 if (address == interface->endpoint[i].descr->endpoint_address) { 240 fStreamEndpoint = interface->endpoint[i].handle; 241 TRACE(INF, "%s Stream Endpoint [address %#04x] handle is: %#010x.\n", 242 fIsInput ? "Input" : "Output", address, fStreamEndpoint); 243 return B_OK; 244 } 245 } 246 247 TRACE(INF, "%s Stream Endpoint [address %#04x] was not found.\n", 248 fIsInput ? "Input" : "Output", address); 249 return B_ERROR; 250 } 251 252 253 status_t 254 Stream::Start() 255 { 256 status_t result = B_BUSY; 257 if (!fIsRunning) { 258 for (size_t i = 0; i < kSamplesBufferCount; i++) 259 result = _QueueNextTransfer(i, true); 260 fIsRunning = result == B_OK; 261 } 262 return result; 263 } 264 265 266 status_t 267 Stream::Stop() 268 { 269 if (fIsRunning) { 270 // wait until possible notification handling finished... 271 while (atomic_add(&fInsideNotify, 0) != 0) 272 snooze(100); 273 gUSBModule->cancel_queued_transfers(fStreamEndpoint); 274 fIsRunning = false; 275 } 276 277 return B_OK; 278 } 279 280 281 status_t 282 Stream::_QueueNextTransfer(size_t queuedBuffer, bool start) 283 { 284 TypeIFormatDescriptor* format = static_cast<TypeIFormatDescriptor*>( 285 fAlternates[fActiveAlternate]->Format()); 286 287 size_t bufferSize = format->fNumChannels * format->fSubframeSize; 288 bufferSize *= fSamplesCount / kSamplesBufferCount; 289 290 uint8* buffers = (uint8*)(fDescriptors + fDescriptorsCount); 291 292 size_t packetsCount = fDescriptorsCount / kSamplesBufferCount; 293 294 TRACE(DTA, "buffers:%#010x[%#x]\ndescrs:%#010x[%#x]\n", 295 buffers + bufferSize * queuedBuffer, bufferSize, 296 fDescriptors + queuedBuffer * packetsCount, packetsCount); 297 298 status_t status = gUSBModule->queue_isochronous(fStreamEndpoint, 299 buffers + bufferSize * queuedBuffer, bufferSize, 300 fDescriptors + queuedBuffer * packetsCount, packetsCount, 301 &fStartingFrame, start ? USB_ISO_ASAP : 0, 302 Stream::_TransferCallback, this); 303 304 TRACE(DTA, "frame:%#010x\n", fStartingFrame); 305 return status; // B_OK; 306 } 307 308 309 void 310 Stream::_TransferCallback(void* cookie, status_t status, void* data, 311 size_t actualLength) 312 { 313 Stream* stream = (Stream*)cookie; 314 atomic_add(&stream->fInsideNotify, 1); 315 if (status == B_CANCELED || stream->fDevice->fRemoved) { 316 atomic_add(&stream->fInsideNotify, -1); 317 TRACE(ERR, "Cancelled: c:%p st:%#010x, data:%#010x, len:%d\n", 318 cookie, status, data, actualLength); 319 return; 320 } 321 322 stream->fCurrentBuffer = (stream->fCurrentBuffer + 1) % kSamplesBufferCount; 323 324 stream->_DumpDescriptors(); 325 326 /*status_t result =*/ stream->_QueueNextTransfer(stream->fCurrentBuffer, false); 327 328 if (atomic_add(&stream->fProcessedBuffers, 1) > (int32)kSamplesBufferCount) 329 TRACE(ERR, "Processed buffers overflow:%d\n", stream->fProcessedBuffers); 330 331 release_sem_etc(stream->fDevice->fBuffersReadySem, 1, B_DO_NOT_RESCHEDULE); 332 333 TRACE(DTA, "st:%#010x, data:%#010x, len:%d\n", status, data, actualLength); 334 335 atomic_add(&stream->fInsideNotify, -1); 336 } 337 338 339 void 340 Stream::_DumpDescriptors() 341 { 342 //size_t packetsCount = fDescriptorsCount / kSamplesBufferCount; 343 size_t from = /*fCurrentBuffer > 0 ? packetsCount :*/ 0 ; 344 size_t to = /*fCurrentBuffer > 0 ?*/ fDescriptorsCount /*: packetsCount*/ ; 345 for (size_t i = from; i < to; i++) 346 TRACE(ISO, "%d:req_len:%d; act_len:%d; stat:%#010x\n", i, 347 fDescriptors[i].request_length, fDescriptors[i].actual_length, 348 fDescriptors[i].status); 349 } 350 351 352 status_t 353 Stream::GetEnabledChannels(uint32& offset, multi_channel_enable* Enable) 354 { 355 AudioChannelCluster* cluster = ChannelCluster(); 356 if (cluster == 0) 357 return B_ERROR; 358 359 for (size_t i = 0; i < cluster->ChannelsCount(); i++) { 360 B_SET_CHANNEL(Enable->enable_bits, offset++, true); 361 TRACE(INF, "Report channel %d as enabled.\n", offset); 362 } 363 364 return B_OK; 365 } 366 367 368 status_t 369 Stream::SetEnabledChannels(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++, offset++) { 376 TRACE(INF, "%s channel %d.\n", 377 (B_TEST_CHANNEL(Enable->enable_bits, offset) 378 ? "Enable" : "Disable"), offset + 1); 379 } 380 381 return B_OK; 382 } 383 384 385 status_t 386 Stream::GetGlobalFormat(multi_format_info* Format) 387 { 388 _multi_format* format = fIsInput ? &Format->input : &Format->output; 389 format->cvsr = fAlternates[fActiveAlternate]->GetSamplingRate(); 390 format->rate = fAlternates[fActiveAlternate]->GetSamplingRateId(0); 391 format->format = fAlternates[fActiveAlternate]->GetFormatId(); 392 TRACE(INF, "%s.rate:%d cvsr:%f format:%#08x\n", 393 fIsInput ? "input" : "ouput", 394 format->rate, format->cvsr, format->format); 395 return B_OK; 396 } 397 398 399 status_t 400 Stream::SetGlobalFormat(multi_format_info* Format) 401 { 402 _multi_format* format = fIsInput ? &Format->input : &Format->output; 403 AudioStreamAlternate* alternate = fAlternates[fActiveAlternate]; 404 if (format->rate == alternate->GetSamplingRateId(0) 405 && format->format == alternate->GetFormatId()) { 406 TRACE(INF, "No changes required\n"); 407 return B_OK; 408 } 409 410 alternate->SetSamplingRateById(format->rate); 411 alternate->SetFormatId(format->format); 412 TRACE(INF, "%s.rate:%d cvsr:%f format:%#08x\n", 413 fIsInput ? "input" : "ouput", 414 format->rate, format->cvsr, format->format); 415 416 // cancel data flow - it will be rewaked at next buffer exchange call 417 Stop(); 418 419 // TODO: wait for cancelling? 420 421 // layout of buffers should be adjusted after changing sampling rate/format 422 status_t status = _SetupBuffers(); 423 424 if (status != B_OK) 425 return status; 426 427 // set endpoint speed 428 uint32 samplingRate = fAlternates[fActiveAlternate]->GetSamplingRate(); 429 size_t actualLength = 0; 430 usb_audio_sampling_freq freq = _ASFormatDescriptor::GetSamFreq(samplingRate); 431 uint8 address = fAlternates[fActiveAlternate]->Endpoint()->fEndpointAddress; 432 433 status = gUSBModule->send_request(fDevice->fDevice, 434 USB_REQTYPE_CLASS | USB_REQTYPE_ENDPOINT_OUT, 435 USB_AUDIO_SET_CUR, USB_AUDIO_SAMPLING_FREQ_CONTROL << 8, 436 address, sizeof(freq), &freq, &actualLength); 437 438 TRACE(ERR, "set_speed %02x%02x%02x for ep %#x %d: %x\n", 439 freq.bytes[0], freq.bytes[1], freq.bytes[2], 440 address, actualLength, status); 441 return status; 442 } 443 444 445 status_t 446 Stream::GetBuffers(multi_buffer_list* List) 447 { 448 // TODO: check the available buffers count! 449 if (fAreaSize == 0) 450 return B_NO_INIT; 451 452 int32 startChannel = List->return_playback_channels; 453 buffer_desc** Buffers = List->playback_buffers; 454 455 if (fIsInput) { 456 List->flags |= B_MULTI_BUFFER_RECORD; 457 List->return_record_buffer_size = fSamplesCount / kSamplesBufferCount; 458 List->return_record_buffers = kSamplesBufferCount; 459 startChannel = List->return_record_channels; 460 Buffers = List->record_buffers; 461 462 TRACE(DTA, "flags:%#10x\nreturn_record_buffer_size:%#010x\n" 463 "return_record_buffers:%#010x\n", List->flags, 464 List->return_record_buffer_size, List->return_record_buffers); 465 } else { 466 List->flags |= B_MULTI_BUFFER_PLAYBACK; 467 List->return_playback_buffer_size = fSamplesCount / kSamplesBufferCount; 468 List->return_playback_buffers = kSamplesBufferCount; 469 470 TRACE(DTA, "flags:%#10x\nreturn_playback_buffer_size:%#010x\n" 471 "return_playback_buffers:%#010x\n", List->flags, 472 List->return_playback_buffer_size, List->return_playback_buffers); 473 } 474 475 TypeIFormatDescriptor* format = static_cast<TypeIFormatDescriptor*>( 476 fAlternates[fActiveAlternate]->Format()); 477 // const ASEndpointDescriptor* endpoint 478 // = fAlternates[fActiveAlternate]->Endpoint(); 479 480 // [buffer][channel] init buffers 481 for (size_t buffer = 0; buffer < kSamplesBufferCount; buffer++) { 482 TRACE(DTA, "%s buffer #%d:\n", fIsInput ? "input" : "output", buffer + 1); 483 484 struct buffer_desc descs[format->fNumChannels]; 485 for (size_t channel = startChannel; 486 channel < format->fNumChannels; channel++) { 487 // init stride to the same for all buffers 488 uint32 stride = format->fSubframeSize * format->fNumChannels; 489 descs[channel].stride = stride; 490 491 // init to buffers area begin 492 descs[channel].base 493 = (char*)(fDescriptors + fDescriptorsCount); 494 // shift for whole buffer if required 495 size_t bufferSize = fPacketSize/*endpoint->fMaxPacketSize*/ 496 * (fDescriptorsCount / kSamplesBufferCount); 497 descs[channel].base += buffer * bufferSize; 498 // shift for channel if required 499 descs[channel].base += channel * format->fSubframeSize; 500 501 TRACE(DTA, "%d:%d: base:%#010x; stride:%#010x\n", buffer, channel, 502 descs[channel].base, descs[channel].stride); 503 } 504 if (!IS_USER_ADDRESS(Buffers[buffer]) 505 || user_memcpy(Buffers[buffer], descs, sizeof(descs)) < B_OK) { 506 return B_BAD_ADDRESS; 507 } 508 } 509 510 if (fIsInput) { 511 List->return_record_channels += format->fNumChannels; 512 TRACE(MIX, "return_record_channels:%#010x\n", 513 List->return_record_channels); 514 } else { 515 List->return_playback_channels += format->fNumChannels; 516 TRACE(MIX, "return_playback_channels:%#010x\n", 517 List->return_playback_channels); 518 } 519 520 return B_OK; 521 } 522 523 524 bool 525 Stream::ExchangeBuffer(multi_buffer_info* Info) 526 { 527 if (fProcessedBuffers <= 0) 528 return false; 529 530 if (fIsInput) { 531 Info->recorded_real_time = system_time();// TODO fRealTime; 532 Info->recorded_frames_count += fSamplesCount / kSamplesBufferCount; 533 Info->record_buffer_cycle = fCurrentBuffer; 534 } else { 535 Info->played_real_time = system_time();// TODO fRealTime; 536 Info->played_frames_count += fSamplesCount / kSamplesBufferCount; 537 Info->playback_buffer_cycle = fCurrentBuffer; 538 } 539 540 atomic_add(&fProcessedBuffers, -1); 541 542 return true; 543 } 544 545