1// Copyright 2017 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <audio-proto-utils/format-utils.h> 6#include <ddk/device.h> 7#include <digest/digest.h> 8#include <fbl/algorithm.h> 9#include <fbl/auto_call.h> 10#include <fbl/limits.h> 11#include <lib/zx/vmar.h> 12#include <string.h> 13#include <zircon/hw/usb-audio.h> 14#include <zircon/process.h> 15#include <zircon/time.h> 16#include <zircon/types.h> 17 18#include <dispatcher-pool/dispatcher-thread-pool.h> 19 20#include "usb-audio.h" 21#include "usb-audio-device.h" 22#include "usb-audio-stream.h" 23#include "usb-audio-stream-interface.h" 24 25namespace audio { 26namespace usb { 27 28static constexpr uint32_t MAX_OUTSTANDING_REQ = 8; 29 30static constexpr uint32_t ExtractSampleRate(const usb_audio_as_samp_freq& sr) { 31 return static_cast<uint32_t>(sr.freq[0]) 32 | (static_cast<uint32_t>(sr.freq[1]) << 8) 33 | (static_cast<uint32_t>(sr.freq[2]) << 16); 34} 35 36UsbAudioStream::UsbAudioStream(UsbAudioDevice* parent, 37 fbl::unique_ptr<UsbAudioStreamInterface> ifc, 38 fbl::RefPtr<dispatcher::ExecutionDomain> default_domain) 39 : UsbAudioStreamBase(parent->zxdev()), 40 AudioStreamProtocol(ifc->direction() == Direction::Input), 41 parent_(*parent), 42 ifc_(fbl::move(ifc)), 43 default_domain_(fbl::move(default_domain)), 44 create_time_(zx_clock_get_monotonic()) { 45 snprintf(log_prefix_, sizeof(log_prefix_), 46 "UsbAud %04hx:%04hx %s-%03d", 47 parent_.vid(), 48 parent_.pid(), 49 is_input() ? "input" : "output", 50 ifc_->term_link()); 51} 52 53UsbAudioStream::~UsbAudioStream() { 54 // We destructing. All of our requests should be sitting in the free list. 55 ZX_DEBUG_ASSERT(allocated_req_cnt_ == free_req_cnt_); 56 57 while (!list_is_empty(&free_req_)) { 58 usb_req_release(&parent_.usb_proto(), list_remove_head_type(&free_req_, 59 usb_request_t, node)); 60 } 61} 62 63fbl::RefPtr<UsbAudioStream> UsbAudioStream::Create(UsbAudioDevice* parent, 64 fbl::unique_ptr<UsbAudioStreamInterface> ifc) { 65 ZX_DEBUG_ASSERT(parent != nullptr); 66 ZX_DEBUG_ASSERT(ifc != nullptr); 67 68 auto domain = dispatcher::ExecutionDomain::Create(); 69 if (domain == nullptr) { 70 LOG_EX(ERROR, *parent, 71 "Failed to create execution domain while trying to create UsbAudioStream\n"); 72 return nullptr; 73 } 74 75 fbl::AllocChecker ac; 76 auto stream = fbl::AdoptRef( 77 new (&ac) UsbAudioStream(parent, fbl::move(ifc), fbl::move(domain))); 78 if (!ac.check()) { 79 LOG_EX(ERROR, *parent, 80 "Out of memory while attempting to allocate UsbAudioStream\n"); 81 return nullptr; 82 } 83 84 stream->ComputePersistentUniqueId(); 85 86 return stream; 87} 88 89zx_status_t UsbAudioStream::Bind() { 90 // TODO(johngro): Do this differently when we have the ability to queue io 91 // transactions to a USB isochronous endpoint and can have the bus driver 92 // DMA directly from the ring buffer we have set up with our user. 93 { 94 fbl::AutoLock req_lock(&req_lock_); 95 96 list_initialize(&free_req_); 97 free_req_cnt_ = 0; 98 allocated_req_cnt_ = 0; 99 100 for (uint32_t i = 0; i < MAX_OUTSTANDING_REQ; ++i) { 101 usb_request_t* req; 102 zx_status_t status = usb_req_alloc(&parent_.usb_proto(), 103 &req, 104 ifc_->max_req_size(), 105 ifc_->ep_addr()); 106 if (status != ZX_OK) { 107 LOG(ERROR, "Failed to allocate usb request %u/%u (size %u): %d\n", 108 i + 1, MAX_OUTSTANDING_REQ, ifc_->max_req_size(), status); 109 return status; 110 } 111 112 req->cookie = this; 113 req->complete_cb = [](usb_request_t* req, void* cookie) -> void { 114 ZX_DEBUG_ASSERT(cookie != nullptr); 115 reinterpret_cast<UsbAudioStream*>(cookie)->RequestComplete(req); 116 }; 117 118 list_add_head(&free_req_, &req->node); 119 ++free_req_cnt_; 120 ++allocated_req_cnt_; 121 } 122 } 123 124 char name[64]; 125 snprintf(name, sizeof(name), "usb-audio-%s-%03d", 126 is_input() ? "input" : "output", ifc_->term_link()); 127 128 zx_status_t status = UsbAudioStreamBase::DdkAdd(name); 129 if (status == ZX_OK) { 130 // If bind/setup has succeeded, then the devmgr now holds a reference to us. 131 // Manually increase our reference count to account for this. 132 this->AddRef(); 133 } else { 134 LOG(ERROR, "Failed to publish UsbAudioStream device node (name \"%s\", status %d)\n", 135 name, status); 136 } 137 138 return status; 139} 140 141void UsbAudioStream::ComputePersistentUniqueId() { 142 // Do the best that we can to generate a persistent ID unique to this audio 143 // stream by blending information from a number of sources. In particular, 144 // consume... 145 // 146 // 1) This USB device's top level device descriptor (this contains the 147 // VID/PID of the device, among other things) 148 // 2) The contents of the descriptor list used to describe the control and 149 // streaming interfaces present in the device. 150 // 3) The manufacturer, product, and serial number string descriptors (if 151 // present) 152 // 4) The stream interface ID. 153 // 154 // The goal here is to produce something like a UUID which is as unique to a 155 // specific instance of a specific device as we can make it, but which 156 // should persist across boots even in the presence of driver updates an 157 // such. Even so, upper levels of code will still need to deal with the sad 158 // reality that some types of devices may end up looking the same between 159 // two different instances. If/when this becomes an issue, we may need to 160 // pursue other options. One choice might be to change the way devices are 161 // enumerated in the USB section of the device tree so that their path has 162 // only to do with physical topology, and has no runtime enumeration order 163 // dependencies. At that point in time, adding the topology into the hash 164 // should do the job, but would imply that the same device plugged into two 165 // different ports will have a different unique ID for the purposes of 166 // saving and restoring driver settings (as it does in some operating 167 // systems today). 168 // 169 uint16_t vid = parent_.desc().idVendor; 170 uint16_t pid = parent_.desc().idProduct; 171 audio_stream_unique_id_t fallback_id { .data = { 172 'U', 'S', 'B', ' ', 173 static_cast<uint8_t>(vid >> 8), 174 static_cast<uint8_t>(vid), 175 static_cast<uint8_t>(pid >> 8), 176 static_cast<uint8_t>(pid), 177 ifc_->iid() 178 }}; 179 persistent_unique_id_ = fallback_id; 180 181 digest::Digest sha; 182 zx_status_t res = sha.Init(); 183 if (res != ZX_OK) { 184 LOG(WARN, "Failed to initialize digest while computing unique ID. " 185 "Falling back on defaults (res %d)\n", res); 186 return; 187 } 188 189 // #1: Top level descriptor. 190 sha.Update(&parent_.desc(), sizeof(parent_.desc())); 191 192 // #2: The descriptor list 193 const auto& desc_list = parent_.desc_list(); 194 ZX_DEBUG_ASSERT((desc_list != nullptr) && (desc_list->size() > 0)); 195 sha.Update(desc_list->data(), desc_list->size()); 196 197 // #3: The various descriptor strings which may exist. 198 const fbl::Array<uint8_t>* desc_strings[] = { 199 &parent_.mfr_name(), 200 &parent_.prod_name(), 201 &parent_.serial_num() 202 }; 203 for (const auto str : desc_strings) { 204 if (str->size()) { 205 sha.Update(str->get(), str->size()); 206 } 207 } 208 209 // #4: The stream interface's ID. 210 auto iid = ifc_->iid(); 211 sha.Update(&iid, sizeof(iid)); 212 213 // Finish the SHA and attempt to copy as much of the results to our internal 214 // cached representation as we can. 215 uint8_t digest_out[digest::Digest::kLength]; 216 sha.Final(); 217 res = sha.CopyTo(digest_out, sizeof(digest_out)); 218 if (res != ZX_OK) { 219 LOG(WARN, "Failed to copy digest while computing unique ID. " 220 "Falling back on defaults (res %d)\n", res); 221 return; 222 } 223 224 constexpr size_t todo = fbl::min(sizeof(digest_out), sizeof(persistent_unique_id_.data)); 225 if (todo < sizeof(persistent_unique_id_.data)) { 226 ::memset(&persistent_unique_id_.data, 0, sizeof(persistent_unique_id_.data)); 227 } 228 ::memcpy(persistent_unique_id_.data, digest_out, todo); 229} 230 231void UsbAudioStream::ReleaseRingBufferLocked() { 232 if (ring_buffer_virt_ != nullptr) { 233 ZX_DEBUG_ASSERT(ring_buffer_size_ != 0); 234 zx::vmar::root_self()->unmap(reinterpret_cast<uintptr_t>(ring_buffer_virt_), 235 ring_buffer_size_); 236 ring_buffer_virt_ = nullptr; 237 ring_buffer_size_ = 0; 238 } 239 ring_buffer_vmo_.reset(); 240} 241 242void UsbAudioStream::DdkUnbind() { 243 // Close all of our client event sources if we have not already. 244 default_domain_->Deactivate(); 245 246 // Unpublish our device node. 247 DdkRemove(); 248} 249 250void UsbAudioStream::DdkRelease() { 251 // Reclaim our reference from the driver framework and let it go out of 252 // scope. If this is our last reference (it should be), we will destruct 253 // immediately afterwards. 254 auto stream = fbl::internal::MakeRefPtrNoAdopt(this); 255 256 // Make sure that our parent is no longer holding a reference to us. 257 parent_.RemoveAudioStream(stream); 258} 259 260zx_status_t UsbAudioStream::DdkIoctl(uint32_t op, 261 const void* in_buf, size_t in_len, 262 void* out_buf, size_t out_len, size_t* out_actual) { 263 // The only IOCTL we support is get channel. 264 if (op != AUDIO_IOCTL_GET_CHANNEL) { 265 return ZX_ERR_NOT_SUPPORTED; 266 } 267 268 if ((out_buf == nullptr) || 269 (out_actual == nullptr) || 270 (out_len != sizeof(zx_handle_t))) { 271 return ZX_ERR_INVALID_ARGS; 272 } 273 274 fbl::AutoLock lock(&lock_); 275 276 // Attempt to allocate a new driver channel and bind it to us. If we don't 277 // already have an stream_channel_, flag this channel is the privileged 278 // connection (The connection which is allowed to do things like change 279 // formats). 280 bool privileged = (stream_channel_ == nullptr); 281 auto channel = dispatcher::Channel::Create(); 282 if (channel == nullptr) 283 return ZX_ERR_NO_MEMORY; 284 285 dispatcher::Channel::ProcessHandler phandler( 286 [stream = fbl::WrapRefPtr(this), privileged](dispatcher::Channel* channel) -> zx_status_t { 287 OBTAIN_EXECUTION_DOMAIN_TOKEN(t, stream->default_domain_); 288 return stream->ProcessStreamChannel(channel, privileged); 289 }); 290 291 dispatcher::Channel::ChannelClosedHandler chandler; 292 if (privileged) { 293 chandler = dispatcher::Channel::ChannelClosedHandler( 294 [stream = fbl::WrapRefPtr(this)](const dispatcher::Channel* channel) -> void { 295 OBTAIN_EXECUTION_DOMAIN_TOKEN(t, stream->default_domain_); 296 stream->DeactivateStreamChannel(channel); 297 }); 298 } 299 300 zx::channel client_endpoint; 301 zx_status_t res = channel->Activate(&client_endpoint, 302 default_domain_, 303 fbl::move(phandler), 304 fbl::move(chandler)); 305 if (res == ZX_OK) { 306 if (privileged) { 307 ZX_DEBUG_ASSERT(stream_channel_ == nullptr); 308 stream_channel_ = channel; 309 } 310 311 *(reinterpret_cast<zx_handle_t*>(out_buf)) = client_endpoint.release(); 312 *out_actual = sizeof(zx_handle_t); 313 } 314 315 return res; 316} 317 318#define HREQ(_cmd, _payload, _handler, _allow_noack, ...) \ 319case _cmd: \ 320 if (req_size != sizeof(req._payload)) { \ 321 LOG(TRACE, "Bad " #_cmd " response length (%u != %zu)\n", \ 322 req_size, sizeof(req._payload)); \ 323 return ZX_ERR_INVALID_ARGS; \ 324 } \ 325 if (!_allow_noack && (req.hdr.cmd & AUDIO_FLAG_NO_ACK)) { \ 326 LOG(TRACE, "NO_ACK flag not allowed for " #_cmd "\n"); \ 327 return ZX_ERR_INVALID_ARGS; \ 328 } \ 329 return _handler(channel, req._payload, ##__VA_ARGS__); 330zx_status_t UsbAudioStream::ProcessStreamChannel(dispatcher::Channel* channel, bool priv) { 331 ZX_DEBUG_ASSERT(channel != nullptr); 332 fbl::AutoLock lock(&lock_); 333 334 // TODO(johngro) : Factor all of this behavior around accepting channels and 335 // dispatching audio driver requests into some form of utility class so it 336 // can be shared with the IntelHDA codec implementations as well. 337 union { 338 audio_proto::CmdHdr hdr; 339 audio_proto::StreamGetFmtsReq get_formats; 340 audio_proto::StreamSetFmtReq set_format; 341 audio_proto::GetGainReq get_gain; 342 audio_proto::SetGainReq set_gain; 343 audio_proto::PlugDetectReq plug_detect; 344 audio_proto::GetUniqueIdReq get_unique_id; 345 audio_proto::GetStringReq get_string; 346 // TODO(johngro) : add more commands here 347 } req; 348 349 static_assert(sizeof(req) <= 256, 350 "Request buffer is getting to be too large to hold on the stack!"); 351 352 uint32_t req_size; 353 zx_status_t res = channel->Read(&req, sizeof(req), &req_size); 354 if (res != ZX_OK) 355 return res; 356 357 if ((req_size < sizeof(req.hdr) || 358 (req.hdr.transaction_id == AUDIO_INVALID_TRANSACTION_ID))) 359 return ZX_ERR_INVALID_ARGS; 360 361 // Strip the NO_ACK flag from the request before selecting the dispatch target. 362 auto cmd = static_cast<audio_proto::Cmd>(req.hdr.cmd & ~AUDIO_FLAG_NO_ACK); 363 switch (cmd) { 364 HREQ(AUDIO_STREAM_CMD_GET_FORMATS, get_formats, OnGetStreamFormatsLocked, false); 365 HREQ(AUDIO_STREAM_CMD_SET_FORMAT, set_format, OnSetStreamFormatLocked, false, priv); 366 HREQ(AUDIO_STREAM_CMD_GET_GAIN, get_gain, OnGetGainLocked, false); 367 HREQ(AUDIO_STREAM_CMD_SET_GAIN, set_gain, OnSetGainLocked, true); 368 HREQ(AUDIO_STREAM_CMD_PLUG_DETECT, plug_detect, OnPlugDetectLocked, true); 369 HREQ(AUDIO_STREAM_CMD_GET_UNIQUE_ID, get_unique_id, OnGetUniqueIdLocked, false); 370 HREQ(AUDIO_STREAM_CMD_GET_STRING, get_string, OnGetStringLocked, false); 371 default: 372 LOG(TRACE, "Unrecognized stream command 0x%04x\n", req.hdr.cmd); 373 return ZX_ERR_NOT_SUPPORTED; 374 } 375} 376 377zx_status_t UsbAudioStream::ProcessRingBufferChannel(dispatcher::Channel* channel) { 378 ZX_DEBUG_ASSERT(channel != nullptr); 379 fbl::AutoLock lock(&lock_); 380 381 union { 382 audio_proto::CmdHdr hdr; 383 audio_proto::RingBufGetFifoDepthReq get_fifo_depth; 384 audio_proto::RingBufGetBufferReq get_buffer; 385 audio_proto::RingBufStartReq rb_start; 386 audio_proto::RingBufStopReq rb_stop; 387 // TODO(johngro) : add more commands here 388 } req; 389 390 static_assert(sizeof(req) <= 256, 391 "Request buffer is getting to be too large to hold on the stack!"); 392 393 uint32_t req_size; 394 zx_status_t res = channel->Read(&req, sizeof(req), &req_size); 395 if (res != ZX_OK) 396 return res; 397 398 if ((req_size < sizeof(req.hdr) || 399 (req.hdr.transaction_id == AUDIO_INVALID_TRANSACTION_ID))) 400 return ZX_ERR_INVALID_ARGS; 401 402 // Strip the NO_ACK flag from the request before selecting the dispatch target. 403 auto cmd = static_cast<audio_proto::Cmd>(req.hdr.cmd & ~AUDIO_FLAG_NO_ACK); 404 switch (cmd) { 405 HREQ(AUDIO_RB_CMD_GET_FIFO_DEPTH, get_fifo_depth, OnGetFifoDepthLocked, false); 406 HREQ(AUDIO_RB_CMD_GET_BUFFER, get_buffer, OnGetBufferLocked, false); 407 HREQ(AUDIO_RB_CMD_START, rb_start, OnStartLocked, false); 408 HREQ(AUDIO_RB_CMD_STOP, rb_stop, OnStopLocked, false); 409 default: 410 LOG(TRACE, "Unrecognized ring buffer command 0x%04x\n", req.hdr.cmd); 411 return ZX_ERR_NOT_SUPPORTED; 412 } 413 414 return ZX_ERR_NOT_SUPPORTED; 415} 416#undef HREQ 417 418zx_status_t UsbAudioStream::OnGetStreamFormatsLocked(dispatcher::Channel* channel, 419 const audio_proto::StreamGetFmtsReq& req) { 420 ZX_DEBUG_ASSERT(channel != nullptr); 421 audio_proto::StreamGetFmtsResp resp = { }; 422 423 const auto& formats = ifc_->formats(); 424 if (formats.size() > fbl::numeric_limits<uint16_t>::max()) { 425 LOG(ERROR, "Too many formats (%zu) to send during AUDIO_STREAM_CMD_GET_FORMATS request!\n", 426 formats.size()); 427 return ZX_ERR_INTERNAL; 428 } 429 430 size_t formats_sent = 0; 431 resp.hdr = req.hdr; 432 resp.format_range_count = static_cast<uint16_t>(formats.size()); 433 434 do { 435 size_t todo, payload_sz, __UNUSED to_send; 436 zx_status_t res; 437 438 todo = fbl::min<size_t>(formats.size() - formats_sent, 439 AUDIO_STREAM_CMD_GET_FORMATS_MAX_RANGES_PER_RESPONSE); 440 payload_sz = sizeof(resp.format_ranges[0]) * todo; 441 to_send = offsetof(audio_proto::StreamGetFmtsResp, format_ranges) + payload_sz; 442 443 resp.first_format_range_ndx = static_cast<uint16_t>(formats_sent); 444 for (uint32_t i = 0; i < todo; ++i) { 445 resp.format_ranges[i] = formats[formats_sent + i].range_; 446 } 447 448 res = channel->Write(&resp, sizeof(resp)); 449 if (res != ZX_OK) { 450 LOG(TRACE, "Failed to send get stream formats response (res %d)\n", res); 451 return res; 452 } 453 454 formats_sent += todo; 455 } while (formats_sent < formats.size()); 456 457 return ZX_OK; 458} 459 460zx_status_t UsbAudioStream::OnSetStreamFormatLocked(dispatcher::Channel* channel, 461 const audio_proto::StreamSetFmtReq& req, 462 bool privileged) { 463 ZX_DEBUG_ASSERT(channel != nullptr); 464 465 zx::channel client_rb_channel; 466 audio_proto::StreamSetFmtResp resp = { }; 467 resp.hdr = req.hdr; 468 469 // Only the privileged stream channel is allowed to change the format. 470 if (!privileged) { 471 ZX_DEBUG_ASSERT(channel != stream_channel_.get()); 472 resp.result = ZX_ERR_ACCESS_DENIED; 473 goto finished; 474 } 475 476 // Look up the details about the interface and the endpoint which will be 477 // used for the requested format. 478 size_t format_ndx; 479 resp.result = ifc_->LookupFormat(req.frames_per_second, 480 req.channels, 481 req.sample_format, 482 &format_ndx); 483 if (resp.result != ZX_OK) { 484 goto finished; 485 } 486 487 // Determine the frame size needed for this requested format, then compute 488 // the size of our short packets, and the constants used to generate the 489 // short/long packet cadence. For now, assume that we will be operating at 490 // a 1mSec isochronous rate. 491 // 492 // Make sure that we can fit our longest payload length into one of our 493 // usb requests. 494 // 495 // Store the results of all of these calculations in local variables. Do 496 // not commit them to member variables until we are certain that we are 497 // going to go ahead with this format change. 498 // 499 // TODO(johngro) : Unless/until we can find some way to set the USB bus 500 // driver to perform direct DMA to/from the Ring Buffer VMO without the need 501 // for software intervention, we may want to expose ways to either increase 502 // the isochronous interval (to minimize load) or to use USB 2.0 125uSec 503 // sub-frame timing (to decrease latency) if possible. 504 uint32_t frame_size; 505 frame_size = audio::utils::ComputeFrameSize(req.channels, req.sample_format); 506 if (!frame_size) { 507 LOG(ERROR, "Failed to compute frame size (ch %hu fmt 0x%08x)\n", 508 req.channels, req.sample_format); 509 resp.result = ZX_ERR_INTERNAL; 510 goto finished; 511 } 512 513 static constexpr uint32_t iso_packet_rate = 1000; 514 uint32_t bytes_per_packet, fractional_bpp_inc, long_payload_len; 515 bytes_per_packet = (req.frames_per_second / iso_packet_rate) * frame_size; 516 fractional_bpp_inc = (req.frames_per_second % iso_packet_rate); 517 long_payload_len = bytes_per_packet + (fractional_bpp_inc ? frame_size : 0); 518 519 ZX_DEBUG_ASSERT(format_ndx < ifc_->formats().size()); 520 if (long_payload_len > ifc_->formats()[format_ndx].max_req_size_) { 521 resp.result = ZX_ERR_INVALID_ARGS; 522 goto finished; 523 } 524 525 // Deny the format change request if the ring buffer is not currently stopped. 526 { 527 // TODO(johngro) : If the ring buffer is running, should we automatically 528 // stop it instead of returning bad state? 529 fbl::AutoLock req_lock(&req_lock_); 530 if (ring_buffer_state_ != RingBufferState::STOPPED) { 531 resp.result = ZX_ERR_BAD_STATE; 532 goto finished; 533 } 534 } 535 536 // Looks like we are going ahead with this format change. Tear down any 537 // exiting ring buffer interface before proceeding. 538 if (rb_channel_ != nullptr) { 539 rb_channel_->Deactivate(); 540 rb_channel_.reset(); 541 } 542 543 // Record the details of our cadence and format selection 544 selected_format_ndx_ = format_ndx; 545 selected_frame_rate_ = req.frames_per_second; 546 frame_size_ = frame_size; 547 iso_packet_rate_ = iso_packet_rate; 548 bytes_per_packet_ = bytes_per_packet; 549 fractional_bpp_inc_ = fractional_bpp_inc; 550 551 // Compute the effective fifo depth for this stream. Right now, we assume 552 // that the controller will never get farther ahead than two isochronous usb 553 // requests, so we report this as the worst case fifo_depth. 554 // 555 // Based on our cadence generation parameters, adjust this number based on 556 // whether or not it is possible to have 0, 1 or 2 long packets back to back 557 // at any point in time during the sequence. 558 // 559 // TODO(johngro): This is not the proper way to report the FIFO depth. How 560 // far ahead the USB controller will read ahead into its FIFO is going to be 561 // a property of the controller and the properties of the endpoint. It is 562 // possible that this is negotiable to some extent as well. I need to work 563 // with voydanof@ to determine what we can expose from the USB bus driver in 564 // order to report this accurately. 565 fifo_bytes_ = bytes_per_packet_ << 1; 566 567 // If we have no fractional portion to accumulate, we always send 568 // short packets. If our fractional portion is <= 1/2 of our 569 // isochronous rate, then we will never send two long packets back 570 // to back. 571 if (fractional_bpp_inc_) { 572 fifo_bytes_ += frame_size_; 573 if (fractional_bpp_inc_ > (iso_packet_rate_ >> 1)) { 574 fifo_bytes_ += frame_size_; 575 } 576 } 577 578 // Create a new ring buffer channel which can be used to move bulk data and 579 // bind it to us. 580 rb_channel_ = dispatcher::Channel::Create(); 581 if (rb_channel_ == nullptr) { 582 resp.result = ZX_ERR_NO_MEMORY; 583 } else { 584 dispatcher::Channel::ProcessHandler phandler( 585 [stream = fbl::WrapRefPtr(this)](dispatcher::Channel* channel) -> zx_status_t { 586 OBTAIN_EXECUTION_DOMAIN_TOKEN(t, stream->default_domain_); 587 return stream->ProcessRingBufferChannel(channel); 588 }); 589 590 dispatcher::Channel::ChannelClosedHandler chandler( 591 [stream = fbl::WrapRefPtr(this)](const dispatcher::Channel* channel) -> void { 592 OBTAIN_EXECUTION_DOMAIN_TOKEN(t, stream->default_domain_); 593 stream->DeactivateRingBufferChannel(channel); 594 }); 595 596 resp.result = rb_channel_->Activate(&client_rb_channel, 597 default_domain_, 598 fbl::move(phandler), 599 fbl::move(chandler)); 600 if (resp.result != ZX_OK) { 601 rb_channel_.reset(); 602 } 603 } 604 605finished: 606 if (resp.result == ZX_OK) { 607 // TODO(johngro): Report the actual external delay. 608 resp.external_delay_nsec = 0; 609 return channel->Write(&resp, sizeof(resp), fbl::move(client_rb_channel)); 610 } else { 611 return channel->Write(&resp, sizeof(resp)); 612 } 613} 614 615zx_status_t UsbAudioStream::OnGetGainLocked(dispatcher::Channel* channel, 616 const audio_proto::GetGainReq& req) { 617 ZX_DEBUG_ASSERT(channel != nullptr); 618 audio_proto::GetGainResp resp = { }; 619 resp.hdr = req.hdr; 620 621 ZX_DEBUG_ASSERT(ifc_->path() != nullptr); 622 const auto& path = *(ifc_->path()); 623 624 resp.can_mute = path.has_mute(); 625 resp.cur_mute = path.cur_mute(); 626 resp.can_agc = path.has_agc(); 627 resp.cur_agc = path.cur_agc(); 628 resp.cur_gain = path.cur_gain(); 629 resp.min_gain = path.min_gain(); 630 resp.max_gain = path.max_gain(); 631 resp.gain_step = path.gain_res(); 632 633 return channel->Write(&resp, sizeof(resp)); 634} 635 636zx_status_t UsbAudioStream::OnSetGainLocked(dispatcher::Channel* channel, 637 const audio_proto::SetGainReq& req) { 638 // TODO(johngro): Actually perform the set operation on our audio path. 639 ZX_DEBUG_ASSERT(channel != nullptr); 640 641 audio_proto::SetGainResp resp = { }; 642 resp.hdr = req.hdr; 643 644 ZX_DEBUG_ASSERT(ifc_->path() != nullptr); 645 auto& path = *(ifc_->path()); 646 bool req_mute = req.flags & AUDIO_SGF_MUTE; 647 bool req_agc = req.flags & AUDIO_SGF_AGC; 648 bool illegal_mute = (req.flags & AUDIO_SGF_MUTE_VALID) && req_mute && !path.has_mute(); 649 bool illegal_agc = (req.flags & AUDIO_SGF_AGC_VALID) && req_agc && !path.has_agc(); 650 bool illegal_gain = (req.flags & AUDIO_SGF_GAIN_VALID) && (req.gain != 0) && !path.has_gain(); 651 652 if (illegal_mute || illegal_agc || illegal_gain) { 653 // If this request is illegal, make no changes but attempt to report the 654 // current state of the world. 655 resp.cur_mute = path.cur_mute(); 656 resp.cur_agc = path.cur_agc(); 657 resp.cur_gain = path.cur_gain(); 658 resp.result = ZX_ERR_INVALID_ARGS; 659 } else { 660 if (req.flags & AUDIO_SGF_MUTE_VALID) { 661 resp.cur_mute = path.SetMute(parent_.usb_proto(), req_mute); 662 } 663 664 if (req.flags & AUDIO_SGF_AGC_VALID) { 665 resp.cur_agc = path.SetAgc(parent_.usb_proto(), req_agc); 666 } 667 668 if (req.flags & AUDIO_SGF_GAIN_VALID) { 669 resp.cur_gain = path.SetGain(parent_.usb_proto(), req.gain); 670 } 671 672 resp.result = ZX_OK; 673 } 674 675 return (req.hdr.cmd & AUDIO_FLAG_NO_ACK) ? ZX_OK : channel->Write(&resp, sizeof(resp)); 676} 677 678zx_status_t UsbAudioStream::OnPlugDetectLocked(dispatcher::Channel* channel, 679 const audio_proto::PlugDetectReq& req) { 680 if (req.hdr.cmd & AUDIO_FLAG_NO_ACK) 681 return ZX_OK; 682 683 audio_proto::PlugDetectResp resp = { }; 684 resp.hdr = req.hdr; 685 resp.flags = static_cast<audio_pd_notify_flags_t>(AUDIO_PDNF_HARDWIRED | AUDIO_PDNF_PLUGGED); 686 resp.plug_state_time = create_time_; 687 688 return channel->Write(&resp, sizeof(resp)); 689} 690 691zx_status_t UsbAudioStream::OnGetUniqueIdLocked(dispatcher::Channel* channel, 692 const audio_proto::GetUniqueIdReq& req) { 693 audio_proto::GetUniqueIdResp resp; 694 695 static_assert(sizeof(resp.unique_id) == sizeof(persistent_unique_id_), 696 "Unique ID sizes much match!"); 697 resp.hdr = req.hdr; 698 resp.unique_id = persistent_unique_id_; 699 700 return channel->Write(&resp, sizeof(resp)); 701} 702 703zx_status_t UsbAudioStream::OnGetStringLocked(dispatcher::Channel* channel, 704 const audio_proto::GetStringReq& req) { 705 audio_proto::GetStringResp resp; 706 const fbl::Array<uint8_t>* str; 707 708 resp.hdr = req.hdr; 709 resp.id = req.id; 710 711 switch (req.id) { 712 case AUDIO_STREAM_STR_ID_MANUFACTURER: str = &parent_.mfr_name(); break; 713 case AUDIO_STREAM_STR_ID_PRODUCT: str = &parent_.prod_name(); break; 714 default: str = nullptr; break; 715 } 716 717 if (str == nullptr) { 718 resp.result = ZX_ERR_NOT_FOUND; 719 resp.strlen = 0; 720 } else { 721 size_t todo = fbl::min<size_t>(sizeof(resp.str), str->size()); 722 ZX_DEBUG_ASSERT(todo <= fbl::numeric_limits<uint32_t>::max()); 723 724 ::memset(resp.str, 0, sizeof(resp.str)); 725 if (todo) { 726 ::memcpy(resp.str, str->get(), todo); 727 } 728 729 resp.result = ZX_OK; 730 resp.strlen = static_cast<uint32_t>(todo); 731 } 732 733 return channel->Write(&resp, sizeof(resp)); 734} 735 736zx_status_t UsbAudioStream::OnGetFifoDepthLocked(dispatcher::Channel* channel, 737 const audio_proto::RingBufGetFifoDepthReq& req) { 738 audio_proto::RingBufGetFifoDepthResp resp = { }; 739 740 resp.hdr = req.hdr; 741 resp.result = ZX_OK; 742 resp.fifo_depth = fifo_bytes_; 743 744 return channel->Write(&resp, sizeof(resp)); 745} 746 747zx_status_t UsbAudioStream::OnGetBufferLocked(dispatcher::Channel* channel, 748 const audio_proto::RingBufGetBufferReq& req) { 749 audio_proto::RingBufGetBufferResp resp = { }; 750 zx::vmo client_rb_handle; 751 uint32_t map_flags, client_rights; 752 753 resp.hdr = req.hdr; 754 resp.result = ZX_ERR_INTERNAL; 755 756 { 757 // We cannot create a new ring buffer if we are not currently stopped. 758 fbl::AutoLock req_lock(&req_lock_); 759 if (ring_buffer_state_ != RingBufferState::STOPPED) { 760 resp.result = ZX_ERR_BAD_STATE; 761 goto finished; 762 } 763 } 764 765 // Unmap and release any previous ring buffer. 766 ReleaseRingBufferLocked(); 767 768 // Compute the ring buffer size. It needs to be at least as big 769 // as the virtual fifo depth. 770 ZX_DEBUG_ASSERT(frame_size_ && ((fifo_bytes_ % frame_size_) == 0)); 771 ZX_DEBUG_ASSERT(fifo_bytes_ && ((fifo_bytes_ % fifo_bytes_) == 0)); 772 ring_buffer_size_ = req.min_ring_buffer_frames; 773 ring_buffer_size_ *= frame_size_; 774 if (ring_buffer_size_ < fifo_bytes_) 775 ring_buffer_size_ = fbl::round_up(fifo_bytes_, frame_size_); 776 777 // Set up our state for generating notifications. 778 if (req.notifications_per_ring) { 779 bytes_per_notification_ = ring_buffer_size_ / req.notifications_per_ring; 780 } else { 781 bytes_per_notification_ = 0; 782 } 783 784 // Create the ring buffer vmo we will use to share memory with the client. 785 resp.result = zx::vmo::create(ring_buffer_size_, 0, &ring_buffer_vmo_); 786 if (resp.result != ZX_OK) { 787 LOG(ERROR, "Failed to create ring buffer (size %u, res %d)\n", 788 ring_buffer_size_, resp.result); 789 goto finished; 790 } 791 792 // Map the VMO into our address space. 793 // 794 // TODO(johngro): skip this step when APIs in the USB bus driver exist to 795 // DMA directly from the VMO. 796 map_flags = ZX_VM_PERM_READ; 797 if (is_input()) 798 map_flags |= ZX_VM_PERM_WRITE; 799 800 resp.result = zx::vmar::root_self()->map(0, ring_buffer_vmo_, 801 0, ring_buffer_size_, 802 map_flags, 803 reinterpret_cast<uintptr_t*>(&ring_buffer_virt_)); 804 if (resp.result != ZX_OK) { 805 LOG(ERROR, "Failed to map ring buffer (size %u, res %d)\n", 806 ring_buffer_size_, resp.result); 807 goto finished; 808 } 809 810 // Create the client's handle to the ring buffer vmo and set it back to them. 811 client_rights = ZX_RIGHT_TRANSFER | ZX_RIGHT_MAP | ZX_RIGHT_READ; 812 if (!is_input()) 813 client_rights |= ZX_RIGHT_WRITE; 814 815 resp.result = ring_buffer_vmo_.duplicate(client_rights, &client_rb_handle); 816 if (resp.result != ZX_OK) { 817 LOG(ERROR, "Failed to duplicate ring buffer handle (res %d)\n", resp.result); 818 goto finished; 819 } 820 resp.num_ring_buffer_frames = ring_buffer_size_ / frame_size_; 821 822finished: 823 zx_status_t res; 824 if (resp.result == ZX_OK) { 825 ZX_DEBUG_ASSERT(client_rb_handle.is_valid()); 826 res = channel->Write(&resp, sizeof(resp), fbl::move(client_rb_handle)); 827 } else { 828 res = channel->Write(&resp, sizeof(resp)); 829 } 830 831 if (res != ZX_OK) 832 ReleaseRingBufferLocked(); 833 834 return res; 835} 836 837zx_status_t UsbAudioStream::OnStartLocked(dispatcher::Channel* channel, 838 const audio_proto::RingBufStartReq& req) { 839 audio_proto::RingBufStartResp resp = { }; 840 resp.hdr = req.hdr; 841 842 fbl::AutoLock req_lock(&req_lock_); 843 844 if (ring_buffer_state_ != RingBufferState::STOPPED) { 845 // The ring buffer is running, do not linger in the lock while we send 846 // the error code back to the user. 847 req_lock.release(); 848 resp.result = ZX_ERR_BAD_STATE; 849 return channel->Write(&resp, sizeof(resp)); 850 } 851 852 // We are idle, all of our usb requests should be sitting in the free list. 853 ZX_DEBUG_ASSERT(allocated_req_cnt_ == free_req_cnt_); 854 855 // Activate the format. 856 resp.result = ifc_->ActivateFormat(selected_format_ndx_, selected_frame_rate_); 857 if (resp.result != ZX_OK) { 858 return channel->Write(&resp, sizeof(resp)); 859 } 860 861 // Initialize the counters used to... 862 // 1) generate the short/long packet cadence. 863 // 2) generate notifications. 864 // 3) track the position in the ring buffer. 865 fractional_bpp_acc_ = 0; 866 notification_acc_ = 0; 867 ring_buffer_offset_ = 0; 868 ring_buffer_pos_ = 0; 869 870 // Schedule the frame number which the first transaction will go out on. 871 // 872 // TODO(johngro): This cannot be the current frame number, that train 873 // has already left the station. It probably should not be the next frame 874 // number either as that train might be just about to leave the station. 875 // 876 // For now, set this to be the current frame number +2 and use the first 877 // transaction complete callback to estimate the DMA start time. Moving 878 // forward, when the USB bus driver can tell us which frame a transaction 879 // went out on, schedule the transaction using the special "on the next USB 880 // isochronous frame" sentinel value and figure out which frame that was 881 // during the callback. 882 usb_frame_num_ = usb_get_current_frame(&parent_.usb_proto()) + 2; 883 884 // Flag ourselves as being in the starting state, then queue up all of our 885 // transactions. 886 ring_buffer_state_ = RingBufferState::STARTING; 887 while (!list_is_empty(&free_req_)) 888 QueueRequestLocked(); 889 890 // Record the transaction ID we will send back to our client when we have 891 // successfully started, then get out. 892 pending_job_resp_.start = resp; 893 return ZX_OK; 894} 895 896zx_status_t UsbAudioStream::OnStopLocked(dispatcher::Channel* channel, 897 const audio_proto::RingBufStopReq& req) { 898 fbl::AutoLock req_lock(&req_lock_); 899 900 // TODO(johngro): Fix this to use the cancel transaction capabilities added 901 // to the USB bus driver. 902 // 903 // Also, investigate whether or not the cancel interface is syncronous or 904 // whether we will need to maintain an intermediate stopping state. 905 if (ring_buffer_state_ != RingBufferState::STARTED) { 906 audio_proto::RingBufStopResp resp = { }; 907 908 req_lock.release(); 909 resp.hdr = req.hdr; 910 resp.result = ZX_ERR_BAD_STATE; 911 912 return channel->Write(&resp, sizeof(resp)); 913 } 914 915 ring_buffer_state_ = RingBufferState::STOPPING; 916 pending_job_resp_.stop.hdr = req.hdr; 917 918 return ZX_OK; 919} 920 921void UsbAudioStream::RequestComplete(usb_request_t* req) { 922 enum class Action { 923 NONE, 924 SIGNAL_STARTED, 925 SIGNAL_STOPPED, 926 NOTIFY_POSITION, 927 HANDLE_UNPLUG, 928 }; 929 930 union { 931 audio_proto::RingBufStopResp stop; 932 audio_proto::RingBufStartResp start; 933 audio_proto::RingBufPositionNotify notify_pos; 934 } resp; 935 936 uint64_t complete_time = zx_clock_get_monotonic(); 937 Action when_finished = Action::NONE; 938 939 // TODO(johngro) : See MG-940. Eliminate this as soon as we have a more 940 // official way of meeting real-time latency requirements. Also, the fact 941 // that this boosting gets done after the first transaction completes 942 // degrades the quality of the startup time estimate (if the system is under 943 // high load when the system starts up). As a general issue, there are 944 // better ways of refining this estimate than bumping the thread prio before 945 // the first transaction gets queued. Therefor, we just have a poor 946 // estimate for now and will need to live with the consequences. 947 if (!req_complete_prio_bumped_) { 948 zx_thread_set_priority(24 /* HIGH_PRIORITY in LK */); 949 req_complete_prio_bumped_ = true; 950 } 951 952 { 953 fbl::AutoLock req_lock(&req_lock_); 954 955 // Cache the status and length of this usb request. 956 zx_status_t req_status = req->response.status; 957 uint32_t req_length = static_cast<uint32_t>(req->header.length); 958 959 // Complete the usb request. This will return the transaction to the free 960 // list and (in the case of an input stream) copy the payload to the 961 // ring buffer, and update the ring buffer position. 962 // 963 // TODO(johngro): copying the payload out of the ring buffer is an 964 // operation which goes away when we get to the zero copy world. 965 CompleteRequestLocked(req); 966 967 // Did the transaction fail because the device was unplugged? If so, 968 // enter the stopping state and close the connections to our clients. 969 if (req_status == ZX_ERR_IO_NOT_PRESENT) { 970 ring_buffer_state_ = RingBufferState::STOPPING_AFTER_UNPLUG; 971 } else { 972 // If we are supposed to be delivering notifications, check to see 973 // if it is time to do so. 974 if (bytes_per_notification_) { 975 notification_acc_ += req_length; 976 977 if ((ring_buffer_state_ == RingBufferState::STARTED) && 978 (notification_acc_ >= bytes_per_notification_)) { 979 when_finished = Action::NOTIFY_POSITION; 980 notification_acc_ = (notification_acc_ % bytes_per_notification_); 981 resp.notify_pos.ring_buffer_pos = ring_buffer_pos_; 982 } 983 } 984 } 985 986 switch (ring_buffer_state_) { 987 case RingBufferState::STOPPING: 988 if (free_req_cnt_ == allocated_req_cnt_) { 989 resp.stop = pending_job_resp_.stop; 990 when_finished = Action::SIGNAL_STOPPED; 991 } 992 break; 993 994 case RingBufferState::STOPPING_AFTER_UNPLUG: 995 if (free_req_cnt_ == allocated_req_cnt_) { 996 resp.stop = pending_job_resp_.stop; 997 when_finished = Action::HANDLE_UNPLUG; 998 } 999 break; 1000 1001 case RingBufferState::STARTING: 1002 resp.start = pending_job_resp_.start; 1003 when_finished = Action::SIGNAL_STARTED; 1004 break; 1005 1006 case RingBufferState::STARTED: 1007 QueueRequestLocked(); 1008 break; 1009 1010 case RingBufferState::STOPPED: 1011 default: 1012 LOG(ERROR, "Invalid state (%u) in %s\n", 1013 static_cast<uint32_t>(ring_buffer_state_), __PRETTY_FUNCTION__); 1014 ZX_DEBUG_ASSERT(false); 1015 break; 1016 } 1017 } 1018 1019 if (when_finished != Action::NONE) { 1020 fbl::AutoLock lock(&lock_); 1021 switch (when_finished) { 1022 case Action::SIGNAL_STARTED: 1023 if (rb_channel_ != nullptr) { 1024 // TODO(johngro) : this start time estimate is not as good as it 1025 // could be. We really need to have the USB bus driver report 1026 // the relationship between the USB frame counter and the system 1027 // tick counter (and track the relationship in the case that the 1028 // USB oscillator is not derived from the system oscillator). 1029 // Then we can accurately report the start time as the time of 1030 // the tick on which we scheduled the first transaction. 1031 resp.start.result = ZX_OK; 1032 resp.start.start_time = zx_time_sub_duration(complete_time, ZX_MSEC(1)); 1033 rb_channel_->Write(&resp.start, sizeof(resp.start)); 1034 } 1035 { 1036 fbl::AutoLock req_lock(&req_lock_); 1037 ring_buffer_state_ = RingBufferState::STARTED; 1038 } 1039 break; 1040 1041 case Action::HANDLE_UNPLUG: 1042 if (rb_channel_ != nullptr) { 1043 rb_channel_->Deactivate(); 1044 rb_channel_.reset(); 1045 } 1046 1047 if (stream_channel_ != nullptr) { 1048 stream_channel_->Deactivate(); 1049 stream_channel_.reset(); 1050 } 1051 1052 { 1053 fbl::AutoLock req_lock(&req_lock_); 1054 ring_buffer_state_ = RingBufferState::STOPPED; 1055 } 1056 break; 1057 1058 case Action::SIGNAL_STOPPED: 1059 if (rb_channel_ != nullptr) { 1060 resp.stop.result = ZX_OK; 1061 rb_channel_->Write(&resp.stop, sizeof(resp.stop)); 1062 } 1063 { 1064 fbl::AutoLock req_lock(&req_lock_); 1065 ring_buffer_state_ = RingBufferState::STOPPED; 1066 ifc_->ActivateIdleFormat(); 1067 } 1068 break; 1069 1070 case Action::NOTIFY_POSITION: 1071 resp.notify_pos.hdr.cmd = AUDIO_RB_POSITION_NOTIFY; 1072 resp.notify_pos.hdr.transaction_id = AUDIO_INVALID_TRANSACTION_ID; 1073 rb_channel_->Write(&resp.notify_pos, sizeof(resp.notify_pos)); 1074 break; 1075 1076 default: 1077 ZX_DEBUG_ASSERT(false); 1078 break; 1079 } 1080 } 1081} 1082 1083void UsbAudioStream::QueueRequestLocked() { 1084 ZX_DEBUG_ASSERT((ring_buffer_state_ == RingBufferState::STARTING) || 1085 (ring_buffer_state_ == RingBufferState::STARTED)); 1086 ZX_DEBUG_ASSERT(!list_is_empty(&free_req_)); 1087 1088 // Figure out how much we want to send or receive this time (short or long 1089 // packet) 1090 uint32_t todo = bytes_per_packet_; 1091 fractional_bpp_acc_ += fractional_bpp_inc_; 1092 if (fractional_bpp_acc_ >= iso_packet_rate_) { 1093 fractional_bpp_acc_ -= iso_packet_rate_; 1094 todo += frame_size_; 1095 ZX_DEBUG_ASSERT(fractional_bpp_acc_ < iso_packet_rate_); 1096 } 1097 1098 // Grab a free usb request. 1099 auto req = list_remove_head_type(&free_req_, usb_request_t, node); 1100 ZX_DEBUG_ASSERT(req != nullptr); 1101 ZX_DEBUG_ASSERT(free_req_cnt_ > 0); 1102 --free_req_cnt_; 1103 1104 // If this is an output stream, copy our data into the usb request. 1105 // TODO(johngro): eliminate this when we can get to a zero-copy world. 1106 if (!is_input()) { 1107 uint32_t avail = ring_buffer_size_ - ring_buffer_offset_; 1108 ZX_DEBUG_ASSERT(ring_buffer_offset_ < ring_buffer_size_); 1109 ZX_DEBUG_ASSERT((avail % frame_size_) == 0); 1110 uint32_t amt = fbl::min(avail, todo); 1111 1112 const uint8_t* src = reinterpret_cast<uint8_t*>(ring_buffer_virt_) + ring_buffer_offset_; 1113 usb_req_copy_to(&parent_.usb_proto(), req, src, amt, 0); 1114 if (amt == avail) { 1115 ring_buffer_offset_ = todo - amt; 1116 if (ring_buffer_offset_ > 0) { 1117 usb_req_copy_to(&parent_.usb_proto(), req, ring_buffer_virt_, ring_buffer_offset_, 1118 amt); 1119 } 1120 } else { 1121 ring_buffer_offset_ += amt; 1122 } 1123 } 1124 1125 req->header.frame = usb_frame_num_++; 1126 req->header.length = todo; 1127 usb_request_queue(&parent_.usb_proto(), req); 1128} 1129 1130void UsbAudioStream::CompleteRequestLocked(usb_request_t* req) { 1131 ZX_DEBUG_ASSERT(req); 1132 1133 // If we are an input stream, copy the payload into the ring buffer. 1134 if (is_input()) { 1135 uint32_t todo = static_cast<uint32_t>(req->header.length); 1136 1137 uint32_t avail = ring_buffer_size_ - ring_buffer_offset_; 1138 ZX_DEBUG_ASSERT(ring_buffer_offset_ < ring_buffer_size_); 1139 ZX_DEBUG_ASSERT((avail % frame_size_) == 0); 1140 1141 uint32_t amt = fbl::min(avail, todo); 1142 uint8_t* dst = reinterpret_cast<uint8_t*>(ring_buffer_virt_) + ring_buffer_offset_; 1143 1144 if (req->response.status == ZX_OK) { 1145 usb_req_copy_from(&parent_.usb_proto(), req, dst, amt, 0); 1146 if (amt < todo) { 1147 usb_req_copy_from(&parent_.usb_proto(), req, ring_buffer_virt_, todo - amt, 1148 amt); 1149 } 1150 } else { 1151 // TODO(johngro): filling with zeros is only the proper thing to do 1152 // for signed formats. USB does support unsigned 8-bit audio; if 1153 // that is our format, we should fill with 0x80 instead in order to 1154 // fill with silence. 1155 memset(dst, 0, amt); 1156 if (amt < todo) { 1157 memset(ring_buffer_virt_, 0, todo - amt); 1158 } 1159 } 1160 } 1161 1162 // Update the ring buffer position. 1163 ring_buffer_pos_ += static_cast<uint32_t>(req->header.length); 1164 if (ring_buffer_pos_ >= ring_buffer_size_) { 1165 ring_buffer_pos_ -= ring_buffer_size_; 1166 ZX_DEBUG_ASSERT(ring_buffer_pos_ < ring_buffer_size_); 1167 } 1168 1169 // If this is an input stream, the ring buffer offset should always be equal 1170 // to the stream position. 1171 if (is_input()) { 1172 ring_buffer_offset_ = ring_buffer_pos_; 1173 } 1174 1175 // Return the transaction to the free list. 1176 list_add_head(&free_req_, &req->node); 1177 ++free_req_cnt_; 1178 ZX_DEBUG_ASSERT(free_req_cnt_ <= allocated_req_cnt_); 1179} 1180 1181void UsbAudioStream::DeactivateStreamChannel(const dispatcher::Channel* channel) { 1182 fbl::AutoLock lock(&lock_); 1183 1184 ZX_DEBUG_ASSERT(stream_channel_.get() == channel); 1185 ZX_DEBUG_ASSERT(rb_channel_.get() != channel); 1186 stream_channel_.reset(); 1187} 1188 1189void UsbAudioStream::DeactivateRingBufferChannel(const dispatcher::Channel* channel) { 1190 fbl::AutoLock lock(&lock_); 1191 1192 ZX_DEBUG_ASSERT(stream_channel_.get() != channel); 1193 ZX_DEBUG_ASSERT(rb_channel_.get() == channel); 1194 1195 { 1196 fbl::AutoLock req_lock(&req_lock_); 1197 if (ring_buffer_state_ != RingBufferState::STOPPED) { 1198 ring_buffer_state_ = RingBufferState::STOPPING; 1199 } 1200 } 1201 1202 rb_channel_.reset(); 1203} 1204 1205} // namespace usb 1206} // namespace audio 1207