| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #pragma once |
| |
| #include <ddk/protocol/usb-old.h> |
| #include <fbl/ref_counted.h> |
| #include <fbl/ref_ptr.h> |
| #include <zircon/hw/usb.h> |
| #include <zircon/types.h> |
| #include <zircon/syscalls.h> |
| |
| #include <threads.h> |
| #include <sys/types.h> |
| |
| namespace audio { |
| namespace usb { |
| |
| // A small helper class for managing a device's descriptor list memory. |
| class DescriptorListMemory : public fbl::RefCounted<DescriptorListMemory> { |
| public: |
| class Iterator { |
| public: |
| explicit Iterator(fbl::RefPtr<DescriptorListMemory> mem); |
| |
| // Advance the iterator to the next valid header and return true. If |
| // there are no more valid headers, simply return false. |
| bool Next(); |
| |
| bool valid() const { return (offset_ < mem_->size()); } |
| size_t offset() const { return offset_; } |
| const fbl::RefPtr<DescriptorListMemory>& desc_list() const { return mem_; } |
| |
| const usb_descriptor_header_t* hdr() const { |
| if (!valid()) { |
| return nullptr; |
| } |
| |
| auto tmp = reinterpret_cast<uintptr_t>(mem_->data()); |
| return reinterpret_cast<const usb_descriptor_header_t*>(tmp + offset_); |
| } |
| |
| template <typename T> |
| const T* hdr_as() const { |
| auto h = hdr(); |
| ZX_DEBUG_ASSERT(offset_ <= mem_->size()); |
| return ((h != nullptr) && (h->bLength <= (mem_->size() - offset_))) |
| ? reinterpret_cast<const T*>(h) |
| : nullptr; |
| } |
| |
| private: |
| DISALLOW_COPY_ASSIGN_AND_MOVE(Iterator); |
| |
| // Validate that the current offset points at something which could be a |
| // valid descriptor which fits within the descriptor memory and return |
| // true. Otherwise, invalidate the offset and return false. |
| bool ValidateOffset(); |
| |
| fbl::RefPtr<DescriptorListMemory> mem_; |
| size_t offset_ = 0; |
| }; |
| |
| static fbl::RefPtr<DescriptorListMemory> Create(usb_protocol_t* proto); |
| const void* data() const { return data_; } |
| size_t size() const { return size_; } |
| |
| private: |
| friend class fbl::RefPtr<DescriptorListMemory>; |
| |
| DescriptorListMemory() = default; |
| ~DescriptorListMemory(); |
| |
| void* data_ = nullptr; |
| size_t size_ = 0; |
| }; |
| |
| } // namespace usb |
| } // namespace audio |