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 #include <fbl/alloc_checker.h>
6 #include <fbl/auto_call.h>
7 #include <pretty/hexdump.h>
8 
9 #include <utility>
10 
11 #include "debug-logging.h"
12 #include "usb-audio-descriptors.h"
13 
14 namespace audio {
15 namespace usb {
16 
~DescriptorListMemory()17 DescriptorListMemory::~DescriptorListMemory() {
18     // According to docs in the header, data allocated using
19     // usb_get_descriptor_list should be free'ed using a standard C "free"
20     if (data_ != nullptr) {
21         free(data_);
22     }
23 }
24 
Create(usb_protocol_t * proto)25 fbl::RefPtr<DescriptorListMemory> DescriptorListMemory::Create(usb_protocol_t* proto) {
26     ZX_DEBUG_ASSERT(proto != nullptr);
27 
28     fbl::AllocChecker ac;
29     auto ret = fbl::AdoptRef(new (&ac) DescriptorListMemory());
30     if (!ac.check()) {
31         GLOBAL_LOG(ERROR, "Failed to allocate descriptor list memory!");
32         return nullptr;
33     }
34 
35     size_t desc_length = usb_get_descriptors_length(proto);
36     ret->data_ = malloc(desc_length);
37     if (!ret->data_) {
38         return nullptr;
39     }
40     usb_get_descriptors(proto, ret->data_, desc_length, &ret->size_);
41 
42     if (zxlog_level_enabled(SPEW)) {
43         GLOBAL_LOG(SPEW, "Descriptor List is %zu bytes long\n", ret->size_);
44         hexdump8_ex(ret->data_, ret->size_, 0u);
45     }
46 
47     return ret;
48 }
49 
Iterator(fbl::RefPtr<DescriptorListMemory> mem)50 DescriptorListMemory::Iterator::Iterator(fbl::RefPtr<DescriptorListMemory> mem)
51     : mem_(std::move(mem)) {
52     ZX_DEBUG_ASSERT(mem_ != nullptr);
53     // Make sure our offset is valid, or go ahead and invalidate it right from
54     // the start.
55     ValidateOffset();
56 }
57 
Next()58 bool DescriptorListMemory::Iterator::Next() {
59     auto h = hdr();
60 
61     // Have we already run out of headers?
62     if (h == nullptr) {
63         return false;
64     }
65 
66     // Advance to the next header, then validate our offset.  Note that there is
67     // no overflow check here.  If we overflow a 64 bit size_t, the implication
68     // is that we are holding a USB descriptor list in RAM whose size is within
69     // 256 bytes of our entire 64 bit address space.  This really should be
70     // impossible, so we don't bother to check.
71     offset_ += h->bLength;
72     return ValidateOffset();
73 }
74 
ValidateOffset()75 bool DescriptorListMemory::Iterator::ValidateOffset() {
76     ZX_DEBUG_ASSERT(offset_ <= mem_->size());
77     size_t space = mem_->size() - offset_;
78 
79     if (!space) {
80         return false;
81     }
82 
83     // If anything goes wrong from here on out, make sure to invalidate our offset.
84     auto cleanup = fbl::MakeAutoCall([this] { offset_ = mem_->size(); });
85 
86     if (space < sizeof(usb_descriptor_header_t)) {
87         GLOBAL_LOG(WARN,
88                    "Insufficient space at offset %zu to contain even the most basic USB descriptor "
89                    "(space needed %zu, space left %zu)\n",
90                    offset_, sizeof(usb_descriptor_header_t), space);
91         return false;
92     }
93 
94     auto tmp = reinterpret_cast<uintptr_t>(mem_->data());
95     auto h = reinterpret_cast<const usb_descriptor_header_t*>(tmp + offset_);
96     if (h->bLength > space) {
97         GLOBAL_LOG(WARN,
98                    "Malformed USB descriptor header (type %u) at offset %zu.  "
99                    "Header indicates that it is %u bytes long, but there %zu bytes remaining\n",
100                    h->bDescriptorType,
101                    offset_,
102                    h->bLength,
103                    space);
104         return false;
105     }
106 
107     GLOBAL_LOG(SPEW, "Found Descriptor [type 0x%02x, len 0x%02x] at offset 0x%zx/0x%zx\n",
108             h->bDescriptorType, h->bLength, offset_, mem_->size());
109 
110     cleanup.cancel();
111     return true;
112 }
113 
114 }  // namespace usb
115 }  // namespace audio
116