blob: 38e4816ba75ca928de71eeeb77c397fcfbf1d86f [file] [log] [blame]
// 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