Descriptors.h
Go to the documentation of this file.
1 /****
2  * Descriptors.h
3  *
4  * Copyright 2023 mikee47 <mike@sillyhouse.net>
5  *
6  * This file is part of the Sming USB Library
7  *
8  * This library is free software: you can redistribute it and/or modify it under the terms of the
9  * GNU General Public License as published by the Free Software Foundation, version 3 or later.
10  *
11  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  * See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along with this library.
16  * If not, see <https://www.gnu.org/licenses/>.
17  *
18  ****/
19 
20 #pragma once
21 
22 #include <tusb.h>
23 #include <Delegate.h>
24 #include <WString.h>
25 #include <Print.h>
26 #if CFG_TUD_ENABLED
27 #include <usb_descriptors.h>
28 #endif
29 
30 namespace USB
31 {
40 using GetDeviceDescriptor = Delegate<const tusb_desc_device_t*(const tusb_desc_device_t& desc)>;
41 
45 struct Descriptor {
46  union Type {
47  uint8_t value;
48  struct {
49  uint8_t id : 5;
50  uint8_t type : 2; // tusb_request_type_t
51  uint8_t reserved : 1;
52  };
53  };
54 
55  static_assert(sizeof(Type) == 1, "Bad alignment");
56 
58  uint8_t type;
59  // uint8_t content[];
60 
65  template <typename T> const T* as() const
66  {
67  return reinterpret_cast<const T*>(this);
68  }
69 
70  size_t printTo(Print& p) const;
71 };
72 
78 struct DescriptorList {
79  const Descriptor* desc;
80  size_t length;
81 
86  class Iterator
87  {
88  public:
89  Iterator() = default;
90  Iterator(const Iterator&) = default;
91 
92  Iterator(const DescriptorList* list, uint16_t offset) : mList(list), mOffset(offset)
93  {
94  }
95 
96  operator bool() const
97  {
98  return mList != nullptr && mOffset < mList->length;
99  }
100 
101  bool operator==(const Iterator& rhs) const
102  {
103  return mList == rhs.mList && mOffset == rhs.mOffset;
104  }
105 
106  bool operator!=(const Iterator& rhs) const
107  {
108  return !operator==(rhs);
109  }
110 
111  const Descriptor* operator*() const
112  {
113  if(!*this) {
114  return nullptr;
115  }
116 
117  auto ptr = reinterpret_cast<const uint8_t*>(mList->desc);
118  return reinterpret_cast<const Descriptor*>(ptr + mOffset);
119  }
120 
122  {
123  next();
124  return *this;
125  }
126 
127  Iterator operator++(int)
128  {
129  Iterator tmp(*this);
130  next();
131  return tmp;
132  }
133 
134  void next()
135  {
136  if(!*this) {
137  return;
138  }
139  mOffset += operator*()->length;
140  }
141 
142  using const_iterator = Iterator;
143 
144  private:
145  const DescriptorList* mList{nullptr};
146  uint16_t mOffset{0};
147  };
148 
149  Iterator begin() const
150  {
151  return Iterator(this, 0);
152  }
153 
154  Iterator end() const
155  {
156  return Iterator(this, length);
157  }
158 
161  size_t printTo(Print& p) const;
162 };
163 
167 template <size_t max_chars> struct StringDescriptor : public Descriptor {
168  uint16_t text[max_chars];
169 
173  StringDescriptor() : Descriptor{2, TUSB_DESC_STRING}
174  {
175  }
176 
182  StringDescriptor(const char* str, size_t charCount) : StringDescriptor()
183  {
184  charCount = std::min(charCount, max_chars);
185  for(unsigned i = 0; i < charCount; ++i) {
186  text[i] = str[i];
187  }
188  length = 2 + (charCount * 2);
189  }
190 
191  StringDescriptor(const String& s) : StringDescriptor(s.c_str(), s.length())
192  {
193  }
194 };
195 
196 static_assert(sizeof(StringDescriptor<8>) == 18, "Bad descriptor alignment");
197 
205 using GetDescriptorString = Delegate<const Descriptor*(uint8_t index)>;
206 
209 
210 } // namespace USB
uint16_t text[max_chars]
UTF16-LE encoded text (no NUL terminator)
Definition: Descriptors.h:185
Definition: Libraries/USB/src/USB/CDC/Device.h:25
bool operator==(const Iterator &rhs) const
Definition: Descriptors.h:118
const T * as() const
Less clumsy way to cast descriptor to a specific type.
Definition: Descriptors.h:82
uint8_t type
Definition: Descriptors.h:67
Template for making a USB string descriptor.
Definition: Descriptors.h:184
Structure of a USB descriptor.
Definition: Descriptors.h:62
const Descriptor * operator*() const
Definition: Descriptors.h:128
The String class.
Definition: WString.h:136
const Descriptor * desc
Definition: Descriptors.h:96
#define str(s)
Definition: testrunner.h:124
uint8_t reserved
Definition: Descriptors.h:68
Definition: Descriptors.h:103
uint8_t id
Definition: Descriptors.h:66
Iterator end() const
Definition: Descriptors.h:171
Iterator & operator++()
Definition: Descriptors.h:138
Delegate< const Descriptor *(uint8_t index)> GetDescriptorString
Application-provided callback to customise string responses.
Definition: Descriptors.h:222
uint8_t length
Total size (in bytes) including this header.
Definition: Descriptors.h:72
bool operator!=(const Iterator &rhs) const
Definition: Descriptors.h:123
void next()
Definition: Descriptors.h:151
Delegate< const tusb_desc_device_t *(const tusb_desc_device_t &desc)> GetDeviceDescriptor
Callback to support provision of dynamic device descriptors.
Definition: Descriptors.h:57
Type
Definition: Resource.h:41
Iterator const_iterator
Definition: Descriptors.h:159
Iterator begin() const
Definition: Descriptors.h:166
Provides formatted output to stream.
Definition: Print.h:36
StringDescriptor()
Construct an empty string descriptor.
Definition: Descriptors.h:190
void onGetDeviceDescriptor(GetDeviceDescriptor callback)
uint8_t value
Definition: Descriptors.h:64
size_t printTo(Print &p) const
void onGetDescriptorSting(GetDescriptorString callback)
Buffer containing list of descriptors.
Definition: Descriptors.h:95
uint8_t type
e.g. TUSB_DESC_STRING
Definition: Descriptors.h:75
Definition: Delegate.h:20
size_t length
Definition: Descriptors.h:97
size_t printTo(Print &p) const