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