1/* 2 * Driver for USB Audio Device Class devices. 3 * Copyright (c) 2009,10,12 S.Zharski <imker@gmx.li> 4 * Distributed under the terms of the MIT license. 5 * 6 */ 7 8 9#include "Stream.h" 10#include "Device.h" 11#include "Driver.h" 12#include "Settings.h" 13 14 15Stream::Stream(Device *device, size_t interface, usb_interface_list *List 16 /*, bool isInput, uint32 HWChannel*/) 17 : 18 AudioStreamingInterface(&device->AudioControl(), interface, List), 19 fDevice(device), 20 fStatus(B_NO_INIT), 21 fStreamEndpoint(0), 22 fIsRunning(false), 23 fArea(-1), 24 fDescriptors(0), 25 fDescriptorsCount(0), 26 fCurrentBuffer(0), 27 fStartingFrame(0), 28 fSamplesCount(0), 29 fProcessedBuffers(0)/*, 30 fBuffersPhysAddress(0)/ *, 31 fRealTime(0), 32 fFramesCount(0), 33 fBufferCycle(0)*/ 34{ 35 36} 37 38 39Stream::~Stream() 40{ 41 delete_area(fArea); 42} 43 44 45status_t 46Stream::Init() 47{ 48 // lookup alternate with maximal (ch * 100 + resolution) 49 uint16 maxChxRes = 0; 50 for (int i = 0; i < fAlternates.Count(); i++) { 51 if (fAlternates[i]->Interface() == 0) { 52 TRACE("Ignore alternate %d - zero interface description.\n", i); 53 continue; 54 } 55 56 if (fAlternates[i]->Format() == 0) { 57 TRACE("Ignore alternate %d - zero format description.\n", i); 58 continue; 59 } 60 61 if (fAlternates[i]->Format()->fFormatType != UAF_FORMAT_TYPE_I) { 62 TRACE("Ignore alternate %d - format type %#02x is not supported.\n", 63 i, fAlternates[i]->Format()->fFormatType); 64 continue; 65 } 66 67 switch (fAlternates[i]->Interface()->fFormatTag) { 68 case UAF_PCM: 69 case UAF_PCM8: 70 case UAF_IEEE_FLOAT: 71 // case UAF_ALAW: 72 // case UAF_MULAW: 73 break; 74 default: 75 TRACE("Ignore alternate %d - format %#04x is not supported.\n", 76 i, fAlternates[i]->Interface()->fFormatTag); 77 continue; 78 } 79 80 TypeIFormatDescriptor* format 81 = static_cast<TypeIFormatDescriptor*>(fAlternates[i]->Format()); 82 83 if (fAlternates[i]->Interface()->fFormatTag == UAF_PCM) { 84 switch(format->fBitResolution) { 85 default: 86 TRACE("Ignore alternate %d - bit resolution %d " 87 "is not supported.\n", i, format->fBitResolution); 88 continue; 89 case 8: case 16: case 18: case 20: case 24: case 32: 90 break; 91 } 92 } 93 94 uint16 chxRes = format->fNumChannels * 100 + format->fBitResolution; 95 if (chxRes > maxChxRes) { 96 maxChxRes = chxRes; 97 fActiveAlternate = i; 98 } 99 } 100 101 if (maxChxRes <= 0) { 102 TRACE("No compatible alternate found. Stream initialization failed.\n"); 103 return fStatus; 104 } 105 const ASEndpointDescriptor* endpoint = fAlternates[ 106 fActiveAlternate]->Endpoint(); 107 fIsInput = (endpoint->fEndpointAddress & USB_ENDPOINT_ADDR_DIR_IN) 108 == USB_ENDPOINT_ADDR_DIR_IN; 109 TRACE("Alternate %d selected!\n", fActiveAlternate); 110 111 TypeIFormatDescriptor* format 112 = static_cast<TypeIFormatDescriptor*>(fAlternates[ 113 fActiveAlternate]->Format()); 114 115 size_t bufferSize = format->fNumChannels * format->fSubframeSize; 116 TRACE("bufferSize:%d\n", bufferSize); 117 118 bufferSize *= kSamplesBufferSize; 119 TRACE("bufferSize:%d\n", bufferSize); 120 121 bufferSize *= (sizeof(usb_iso_packet_descriptor) + endpoint->fMaxPacketSize); 122 TRACE("bufferSize:%d\n", bufferSize); 123 124 bufferSize /= endpoint->fMaxPacketSize; 125 TRACE("bufferSize:%d\n", bufferSize); 126 127 bufferSize = (bufferSize + (B_PAGE_SIZE - 1)) &~ (B_PAGE_SIZE - 1); 128 TRACE("bufferSize:%d\n", bufferSize); 129 130 fArea = create_area( (fIsInput) ? DRIVER_NAME "_record_area" : 131 DRIVER_NAME "_playback_area", 132 (void**)&fDescriptors, B_ANY_KERNEL_ADDRESS, 133 bufferSize, B_CONTIGUOUS, 134 B_READ_AREA | B_WRITE_AREA); 135 if (fArea < 0) { 136 TRACE_ALWAYS("Error of creating %#x - bytes size buffer area:%#010x\n", 137 bufferSize, fArea); 138 fStatus = fArea; 139 return fStatus; 140 } 141 142 physical_entry PhysEntry; 143 get_memory_map(fDescriptors, bufferSize, &PhysEntry, 1); 144 145 TRACE_ALWAYS("Created area id: " 146 "%d\naddress:%#010x[phys:%#010x]\nsize:%#010x\n", 147 fArea, fDescriptors, PhysEntry.address, bufferSize); 148 149 fDescriptorsCount = bufferSize; 150 fDescriptorsCount /= (sizeof(usb_iso_packet_descriptor) 151 + endpoint->fMaxPacketSize); 152 fDescriptorsCount /= kSamplesBufferCount; 153 // we need same size buffers. round it! 154 fDescriptorsCount *= kSamplesBufferCount; 155 156 fSamplesCount = fDescriptorsCount * endpoint->fMaxPacketSize; 157 TRACE("samplesCount:%d\n", fSamplesCount); 158 159 fSamplesCount /= format->fNumChannels * format->fSubframeSize; 160 TRACE("samplesCount:%d\n", fSamplesCount); 161 162 for (size_t i = 0; i < fDescriptorsCount; i++) { 163 fDescriptors[i].request_length = endpoint->fMaxPacketSize; 164 fDescriptors[i].actual_length = 0; 165 fDescriptors[i].status = B_OK; 166 } 167 168/* uint32* b = (uint32*)(fDescriptors + fDescriptorsCount); 169 for (size_t i = 0; i < fSamplesCount; i++) { 170 b[i] = i * 10; 171 }*/ 172 173 TRACE_ALWAYS("Descriptors count:%d\nsample size:%d\nchannels:%d:%d\n", 174 fDescriptorsCount, format->fSubframeSize, format->fNumChannels, 175 sizeof(usb_iso_packet_descriptor)); 176 return fStatus = B_OK; 177} 178 179 180status_t 181Stream::OnSetConfiguration(usb_device device, 182 const usb_configuration_info *config) 183{ 184 if (config == NULL) { 185 TRACE_ALWAYS("NULL configuration. Not set.\n"); 186 return B_ERROR; 187 } 188 189 usb_interface_info* interface 190 = &config->interface[fInterface].alt[fActiveAlternate]; 191 if (interface == NULL) { 192 TRACE_ALWAYS("NULL interface. Not set.\n"); 193 return B_ERROR; 194 } 195 196 /*status_t status =*/ gUSBModule->set_alt_interface(device, interface); 197 uint8 address = fAlternates[fActiveAlternate]->Endpoint()->fEndpointAddress; 198 199 for (size_t i = 0; i < interface->endpoint_count; i++) { 200 if (address == interface->endpoint[i].descr->endpoint_address) { 201 fStreamEndpoint = interface->endpoint[i].handle; 202 TRACE("%s Stream Endpoint [address %#04x] handle is: %#010x.\n", 203 fIsInput ? "Input" : "Output", address, fStreamEndpoint); 204 return B_OK; 205 } 206 } 207 208 TRACE("%s Stream Endpoint [address %#04x] was not found.\n", 209 fIsInput ? "Input" : "Output", address); 210 return B_ERROR; 211} 212 213 214status_t 215Stream::Start() 216{ 217 status_t result = B_BUSY; 218 if (!fIsRunning) { 219 if (!fIsInput) { 220 // for (size_t i = 0; i < kSamplesBufferCount; i++) 221 // result = _QueueNextTransfer(i); 222 // TODO 223 // result = _QueueNextTransfer(0); 224 result = B_OK; 225 } else 226 result = B_OK; 227 fIsRunning = result == B_OK; 228 } 229 return result; 230} 231 232 233status_t 234Stream::Stop() 235{ 236 if (fIsRunning) { 237 gUSBModule->cancel_queued_transfers(fStreamEndpoint); 238 fIsRunning = false; 239 } 240 241 return B_OK; 242} 243 244 245status_t 246Stream::_QueueNextTransfer(size_t queuedBuffer) 247{ 248 TypeIFormatDescriptor* format 249 = static_cast<TypeIFormatDescriptor*>(fAlternates[ 250 fActiveAlternate]->Format()); 251 252 size_t bufferSize = format->fNumChannels * format->fSubframeSize; 253 bufferSize *= fSamplesCount / kSamplesBufferCount; 254 255 uint8* buffers = (uint8*)(fDescriptors + fDescriptorsCount); 256 257 size_t packetsCount = fDescriptorsCount / kSamplesBufferCount; 258 259 TRACE("buffers:%#010x[%#x]\ndescrs:%#010x[%#x]\n", 260 buffers + bufferSize * queuedBuffer, bufferSize, 261 fDescriptors + queuedBuffer * packetsCount, packetsCount); 262 263 return gUSBModule->queue_isochronous(fStreamEndpoint, 264 buffers + bufferSize * queuedBuffer, bufferSize, 265 fDescriptors + queuedBuffer * packetsCount, packetsCount, 266 NULL/*&fStartingFrame*/, USB_ISO_ASAP, 267 Stream::_TransferCallback, this); 268 269 return B_OK; 270} 271 272 273void 274Stream::_TransferCallback(void *cookie, int32 status, void *data, 275 uint32 actualLength) 276{ 277 Stream *stream = (Stream *)cookie; 278 279 stream->fCurrentBuffer++; 280 if (stream->fCurrentBuffer >= kSamplesBufferCount) { 281 stream->fCurrentBuffer = 0; 282 } 283 284 stream->_DumpDescriptors(); 285 286 stream->_DumpDescriptors(); 287 288 /* 289 status_t result = stream->_QueueNextTransfer(stream->fCurrentBuffer); 290 291 if (atomic_add(&stream->fProcessedBuffers, 1) > (int32)kSamplesBufferCount) { 292 TRACE_ALWAYS("Processed buffers overflow:%d\n", stream->fProcessedBuffers); 293 } 294*/ 295 release_sem_etc(stream->fDevice->fBuffersReadySem, 1, B_DO_NOT_RESCHEDULE); 296 297 // TRACE_ALWAYS("st:%#010x, len:%d -> %#010x\n", status, actualLength, result); 298 TRACE_ALWAYS("st:%#010x, data:%#010x, len:%d\n", status, data, actualLength); 299 300/* if (status != B_OK) { 301 TRACE_ALWAYS("Device status error:%#010x\n", status); 302 status_t result = gUSBModule->clear_feature(device->fControLeNDPOint, 303 USB_FEATURE_ENDPOINT_HALT); 304 if (result != B_OK) 305 TRACE_ALWAYS("Error during clearing of HALT state:%#010x.\n", result); 306 } 307*/ 308} 309 310 311void 312Stream::_DumpDescriptors() 313{ 314 size_t packetsCount = fDescriptorsCount / kSamplesBufferCount; 315 size_t from = /*fCurrentBuffer > 0 ? packetsCount :*/ 0 ; 316 size_t to = /*fCurrentBuffer > 0 ?*/ fDescriptorsCount /*: packetsCount*/ ; 317 for (size_t i = from; i < to; i++) { 318 TRACE_ALWAYS("%d:req_len:%d; act_len:%d; stat:%#010x\n", i, 319 fDescriptors[i].request_length, fDescriptors[i].actual_length, 320 fDescriptors[i].status); 321 } 322} 323 324 325status_t 326Stream::GetEnabledChannels(uint32& offset, multi_channel_enable *Enable) 327{ 328 AudioChannelCluster* cluster = ChannelCluster(); 329 if (cluster == 0) { 330 return B_ERROR; 331 } 332 333 for (size_t i = 0; i < cluster->ChannelsCount(); i++) { 334 B_SET_CHANNEL(Enable->enable_bits, offset++, true); 335 TRACE("Report channel %d as enabled.\n", offset); 336 } 337 338 return B_OK; 339} 340 341 342status_t 343Stream::SetEnabledChannels(uint32& offset, multi_channel_enable *Enable) 344{ 345 AudioChannelCluster* cluster = ChannelCluster(); 346 if (cluster == 0) { 347 return B_ERROR; 348 } 349 350 for (size_t i = 0; i < cluster->ChannelsCount(); i++) { 351 TRACE("%s channel %d.\n", (B_TEST_CHANNEL(Enable->enable_bits, offset++) 352 ? "Enable" : "Disable"), offset + 1); 353 } 354 355 return B_OK; 356} 357 358 359status_t 360Stream::GetGlobalFormat(multi_format_info *Format) 361{ 362 if (IsInput()) { 363 // TODO 364 Format->input.rate = B_SR_48000; 365 Format->input.cvsr = 48000; 366 Format->input.format = B_FMT_16BIT; 367 } else { 368 // TODO 369 Format->output.rate = B_SR_48000; 370 Format->output.cvsr = 48000; 371 Format->output.format = B_FMT_16BIT; 372 } 373 374 return B_OK; 375} 376 377 378status_t 379Stream::SetGlobalFormat(multi_format_info *Format) 380{ 381 if (IsInput()) { 382 // TODO 383 TRACE("input.rate:%d\n", Format->input.rate); 384 TRACE("input.cvsr:%f\n", Format->input.cvsr); 385 TRACE("input.format:%#08x\n", Format->input.format); 386 } else { 387 // TODO 388 TRACE("output.rate:%d\n", Format->output.rate); 389 TRACE("output.cvsr:%f\n", Format->output.cvsr); 390 TRACE("output.format:%#08x\n", Format->output.format); 391 } 392 393 return B_OK; 394} 395 396 397status_t 398Stream::GetBuffers(multi_buffer_list* List) 399{ 400// TODO: check the available buffers count! 401 402 int32 startChannel = List->return_playback_channels; 403 buffer_desc** Buffers = List->playback_buffers; 404 405 if (fIsInput) { 406 List->flags |= B_MULTI_BUFFER_RECORD; 407 List->return_record_buffer_size = fSamplesCount / kSamplesBufferCount; 408 List->return_record_buffers = kSamplesBufferCount; 409 startChannel = List->return_record_channels; 410 Buffers = List->record_buffers; 411 412 TRACE("flags:%#10x\nreturn_record_buffer_size:%#010x\n" 413 "return_record_buffers:%#010x\n", List->flags, 414 List->return_record_buffer_size, List->return_record_buffers); 415 } else { 416 List->flags |= B_MULTI_BUFFER_PLAYBACK; 417 List->return_playback_buffer_size = fSamplesCount / kSamplesBufferCount; 418 List->return_playback_buffers = kSamplesBufferCount; 419 420 TRACE("flags:%#10x\nreturn_playback_buffer_size:%#010x\n" 421 "return_playback_buffers:%#010x\n", List->flags, 422 List->return_playback_buffer_size, List->return_playback_buffers); 423 } 424 425 TypeIFormatDescriptor* format 426 = static_cast<TypeIFormatDescriptor*>( 427 fAlternates[fActiveAlternate]->Format()); 428 const ASEndpointDescriptor* endpoint 429 = fAlternates[fActiveAlternate]->Endpoint(); 430 431 // [buffer][channel] init buffers 432 for (size_t buffer = 0; buffer < kSamplesBufferCount; buffer++) { 433 TRACE("%s buffer #%d:\n", fIsInput ? "input" : "output", buffer + 1); 434 435 for (size_t channel = startChannel; 436 channel < format->fNumChannels; channel++) 437 { 438 // init stride to the same for all buffers 439 uint32 stride = format->fSubframeSize * format->fNumChannels; 440 Buffers[buffer][channel].stride = stride; 441 442 // init to buffers area begin 443 Buffers[buffer][channel].base 444 = (char*)(fDescriptors + fDescriptorsCount); 445 // shift for whole buffer if required 446 size_t bufferSize = endpoint->fMaxPacketSize 447 * (fDescriptorsCount / kSamplesBufferCount); 448 Buffers[buffer][channel].base += buffer * bufferSize; 449 // shift for channel if required 450 Buffers[buffer][channel].base += channel * format->fSubframeSize; 451 452 TRACE("%d:%d: base:%#010x; stride:%#010x\n", buffer, channel, 453 Buffers[buffer][channel].base, Buffers[buffer][channel].stride); 454 } 455 } 456 457 if (fIsInput) { 458 List->return_record_channels += format->fNumChannels; 459 TRACE("return_record_channels:%#010x\n", List->return_record_channels); 460 } else { 461 List->return_playback_channels += format->fNumChannels; 462 TRACE("return_playback_channels:%#010x\n", 463 List->return_playback_channels); 464 } 465 466 return B_OK; 467} 468 469 470/* 471int32 472Stream::InterruptHandler(uint32 SignaledChannelsMask) 473{ 474 uint32 ChannelMask = 1 << fHWChannel; 475 if ((SignaledChannelsMask & ChannelMask) == 0) { 476 return B_UNHANDLED_INTERRUPT; 477 } 478 479 uint32 CurrentSamplePositionFlag = fDevice->ReadPCI32(TrCurSPFBReg); 480 481 fRealTime = system_time(); 482 fFramesCount += fBufferSize; 483 fBufferCycle = ((CurrentSamplePositionFlag & ChannelMask) == ChannelMask) ? 1 : 0; 484 485fCSP = CurrentSamplePositionFlag; 486 487 release_sem_etc(fDevice->fBuffersReadySem, 1, B_DO_NOT_RESCHEDULE); 488 489 return B_HANDLED_INTERRUPT; 490}*/ 491 492 493bool 494Stream::ExchangeBuffer(multi_buffer_info* Info) 495{ 496 if (fProcessedBuffers <= 0) { 497 // looks like somebody else has processed buffers but this stream 498 release_sem_etc(fDevice->fBuffersReadySem, 1, B_DO_NOT_RESCHEDULE); 499 return false; 500 } 501 502 Info->played_real_time = system_time();// TODO fRealTime; 503 Info->played_frames_count += fSamplesCount / kSamplesBufferCount; 504 Info->playback_buffer_cycle = fCurrentBuffer; 505 506 fCurrentBuffer++; 507 fCurrentBuffer %= kSamplesBufferCount; 508 509 atomic_add(&fProcessedBuffers, -1); 510 511 return true; 512} 513 514 515/* 516ASInterfaceDescriptor* 517Stream::ASInterface() 518{ 519 return fAlternates[fActiveAlternate]->Interface(); 520} 521 522 523_ASFormatDescriptor* 524Stream::ASFormat() 525{ 526 return fAlternates[fActiveAlternate]->Format(); 527}*/ 528 529