1// Copyright 2018 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#pragma once 6 7#include <ddk/protocol/usb.h> 8#include <fbl/ref_counted.h> 9#include <fbl/ref_ptr.h> 10#include <zircon/hw/usb.h> 11#include <zircon/types.h> 12#include <zircon/syscalls.h> 13 14#include <threads.h> 15#include <sys/types.h> 16 17namespace audio { 18namespace usb { 19 20// A small helper class for managing a device's descriptor list memory. 21class DescriptorListMemory : public fbl::RefCounted<DescriptorListMemory> { 22 public: 23 class Iterator { 24 public: 25 explicit Iterator(fbl::RefPtr<DescriptorListMemory> mem); 26 27 // Advance the iterator to the next valid header and return true. If 28 // there are no more valid headers, simply return false. 29 bool Next(); 30 31 bool valid() const { return (offset_ < mem_->size()); } 32 size_t offset() const { return offset_; } 33 const fbl::RefPtr<DescriptorListMemory>& desc_list() const { return mem_; } 34 35 const usb_descriptor_header_t* hdr() const { 36 if (!valid()) { 37 return nullptr; 38 } 39 40 auto tmp = reinterpret_cast<uintptr_t>(mem_->data()); 41 return reinterpret_cast<const usb_descriptor_header_t*>(tmp + offset_); 42 } 43 44 template <typename T> 45 const T* hdr_as() const { 46 auto h = hdr(); 47 ZX_DEBUG_ASSERT(offset_ <= mem_->size()); 48 return ((h != nullptr) && (h->bLength <= (mem_->size() - offset_))) 49 ? reinterpret_cast<const T*>(h) 50 : nullptr; 51 } 52 53 private: 54 DISALLOW_COPY_ASSIGN_AND_MOVE(Iterator); 55 56 // Validate that the current offset points at something which could be a 57 // valid descriptor which fits within the descriptor memory and return 58 // true. Otherwise, invalidate the offset and return false. 59 bool ValidateOffset(); 60 61 fbl::RefPtr<DescriptorListMemory> mem_; 62 size_t offset_ = 0; 63 }; 64 65 static fbl::RefPtr<DescriptorListMemory> Create(usb_protocol_t* proto); 66 const void* data() const { return data_; } 67 size_t size() const { return size_; } 68 69 private: 70 friend class fbl::RefPtr<DescriptorListMemory>; 71 72 DescriptorListMemory() = default; 73 ~DescriptorListMemory(); 74 75 void* data_ = nullptr; 76 size_t size_ = 0; 77}; 78 79} // namespace usb 80} // namespace audio 81