arduino-audio-tools
Loading...
Searching...
No Matches
USBAudio2DescriptorBuilder.h
Go to the documentation of this file.
1#pragma once
2#include <cstdint>
3#include <cstring>
4
5#include "tusb.h"
6#include "USBAudioConfig.h"
7
8namespace audio_tools {
9
31 public:
32 // UAC2 entity IDs — assigned sequentially from 1.
33 // Chain 1 is used for the OUT path (or the only path in pure-IN mode).
34 // Chain 2 is used for the IN path in RXTX mode.
35 static constexpr uint8_t ENTITY_CLOCK = 1;
36 static constexpr uint8_t ENTITY_IT1 = 2;
37 static constexpr uint8_t ENTITY_FU1 = 3;
38 static constexpr uint8_t ENTITY_OT1 = 4;
39 static constexpr uint8_t ENTITY_IT2 = 5;
40 static constexpr uint8_t ENTITY_FU2 = 6;
41 static constexpr uint8_t ENTITY_OT2 = 7;
42
44
45
46 // Kept for backward compatibility with existing call sites.
47 const uint16_t buildDescriptor(uint8_t /*itf*/, uint8_t /*alt*/, uint8_t* desc) {
48 return buildFullDescriptor(desc);
49 }
50
51 // Build the complete audio-function descriptor using interface numbers from
52 // config. Returns a pointer to an internal static buffer; *outLen receives
53 // the total byte count.
54 const uint16_t buildFullDescriptor(uint8_t* desc) {
56 }
57
58 // Same but with an explicit first (AC) interface number.
59 const uint16_t buildFullDescriptor(uint8_t first_itf, uint8_t* desc) {
60 uint8_t* p = desc;
61
62 const uint8_t itf_ac = first_itf;
63 uint8_t itf_as = (uint8_t)(first_itf + 1);
64 const uint8_t num_as = (uint8_t)audioFunctionsCount();
65
66 // ── IAD ──────────────────────────────────────────────────────────────────
67 p = writeIAD(p, itf_ac, (uint8_t)(1 + num_as));
68
69 // ── Standard AC Interface ─────────────────────────────────────────────
70 const uint8_t ac_nEps = p_config->enable_interrupt_ep ? 1 : 0;
71 p = writeStdIface(p, itf_ac, 0, ac_nEps, 0x01 /*AUDIO*/, 0x01 /*CONTROL*/, 0x20 /*UAC2*/);
72
73 // ── CS AC entities — patch wTotalLength after ────────────────────────────
74 uint8_t* cs_ac_start = p;
75 p = writeCsAcHeader(p);
77
79 // OUT path: USB Streaming input → Feature Unit → Speaker output
81 0x0101 /*USB Streaming*/, ENTITY_CLOCK);
84 0x0301 /*Speaker*/, ENTITY_FU1,
86 }
87
89 // IN path: Microphone input → Feature Unit → USB Streaming output.
90 // Pure-IN mode reuses chain 1 IDs; RXTX mode uses chain 2 IDs.
91 const bool rxtx = p_config->enable_ep_out;
92 const uint8_t it = rxtx ? ENTITY_IT2 : ENTITY_IT1;
93 const uint8_t fu = rxtx ? ENTITY_FU2 : ENTITY_FU1;
94 const uint8_t ot = rxtx ? ENTITY_OT2 : ENTITY_OT1;
95 p = writeInputTerminal(p, it, 0x0201 /*Microphone*/, ENTITY_CLOCK);
96 p = writeFeatureUnit(p, fu, it);
97 p = writeOutputTerminal(p, ot, 0x0101 /*USB Streaming*/, fu,
99 }
100
101 // Patch wTotalLength (bytes 6-7 of CS AC Header) — covers only the
102 // class-specific descriptors above, not the interrupt endpoint below.
103 const uint16_t cs_ac_len = (uint16_t)(p - cs_ac_start);
104 cs_ac_start[6] = (uint8_t)(cs_ac_len & 0xFF);
105 cs_ac_start[7] = (uint8_t)(cs_ac_len >> 8);
106
107 // Interrupt EP must follow the CS AC block (USB spec §9.6.6:
108 // endpoint descriptors come after class-specific interface descriptors).
111 }
112
113 // ── OUT AS Interface ─────────────────────────────────────────────────────
114 if (p_config->enable_ep_out) {
115 const uint8_t nEps = enableFeedbackEp() ? 2 : 1;
116 p = writeStdIface(p, itf_as, 0, 0, 0x01, 0x02, 0x20); // alt=0 zero BW
117 p = writeStdIface(p, itf_as, 1, nEps, 0x01, 0x02, 0x20); // alt=1 active
118 p = writeCsAsInterface(p, ENTITY_IT1); // links to USB Streaming IT
119 p = writeFormatType(p);
121 p = writeCsIsoEndpoint(p);
122 if (enableFeedbackEp()) {
124 }
125 ++itf_as;
126 }
127
128 // ── IN AS Interface ──────────────────────────────────────────────────────
129 if (p_config->enable_ep_in) {
130 // Links to the Output Terminal that has USB Streaming type
131 const uint8_t ot = p_config->enable_ep_out ? ENTITY_OT2
132 : ENTITY_OT1;
133 p = writeStdIface(p, itf_as, 0, 0, 0x01, 0x02, 0x20); // alt=0 zero BW
134 p = writeStdIface(p, itf_as, 1, 1, 0x01, 0x02, 0x20); // alt=1 active
135 p = writeCsAsInterface(p, ot);
136 p = writeFormatType(p);
138 p = writeCsIsoEndpoint(p);
139 }
140
141 uint16_t outLen = (uint16_t)(p - desc);
142 return outLen;
143 }
144
146 return (p_config->enable_ep_in ? 1 : 0) + (p_config->enable_ep_out ? 1 : 0);
147 }
148
149
150 // True when the explicit-feedback endpoint should appear in the descriptor.
151 // Mirrors isFeedbackEpEnabled() in USBAudioDeviceBase: feedback is only valid
152 // for a pure OUT (speaker) path — with an IN endpoint present the host uses
153 // the IN stream as implicit feedback, and TX-only mode has no OUT EP at all.
154 bool enableFeedbackEp() const {
158 }
159
160 // Isochronous packet size for one 1 ms frame at a given rate.
161 // +1 extra sample provides headroom for clock-drift compensation: the host
162 // may send ceil(rate/1000)+1 samples in occasional frames to stay in sync.
163 uint16_t calcPacketSizeForRate(uint32_t rate) const {
164 const uint16_t bytes_per_sample = (p_config->bits_per_sample / 8) * p_config->channels;
165 return bytes_per_sample * (uint16_t)(((rate + 999) / 1000) + 1);
166 }
167
168 // Isochronous packet size for one 1 ms frame at the configured rate/format.
169 // +1 extra sample is required for Windows: at rates that are exact multiples
170 // of 1000 Hz (e.g. 48000 Hz = exactly 48 samples/frame), Windows' USB audio
171 // driver may deliver 49 samples in some frames for synchronisation, causing
172 // a descriptor rejection when wMaxPacketSize is set to the nominal 48-sample
173 // value. Rates like 44100 Hz already have implicit headroom from ceiling
174 // division (44.1 → 45), but the +1 makes this safe for all rates.
175 uint16_t calcMaxPacketSize() const {
176 const uint16_t bytes_per_sample = (p_config->bits_per_sample / 8) * p_config->channels;
177 return bytes_per_sample * (uint16_t)(((p_config->sample_rate + 999) / 1000) + 1);
178 }
179
180 protected:
182
183 // ── helpers ─────────────────────────────────────────────────────────────────
184
185 uint32_t channelConfig() const {
186 // Stereo: FL+FR = bits 0-1; mono: FL = bit 0; >2ch: lower N bits.
187 if (p_config->channels == 1) return 0x00000001u;
188 if (p_config->channels == 2) return 0x00000003u;
189 return (1u << p_config->channels) - 1u;
190 }
191
192 // ── descriptor writers ──────────────────────────────────────────────────────
193
194 // Interface Association Descriptor (8 bytes)
195 uint8_t* writeIAD(uint8_t* p, uint8_t first_itf, uint8_t count) {
196 *p++ = 8;
197 *p++ = 0x0B; // INTERFACE_ASSOCIATION
198 *p++ = first_itf;
199 *p++ = count;
200 *p++ = 0x01; // bFunctionClass AUDIO
201 *p++ = 0x00; // bFunctionSubClass
202 *p++ = 0x20; // bFunctionProtocol UAC2
203 *p++ = 0x00; // iFunction
204 return p;
205 }
206
207 // Standard Interface Descriptor (9 bytes)
208 uint8_t* writeStdIface(uint8_t* p, uint8_t itf, uint8_t alt,
209 uint8_t nEps, uint8_t cls, uint8_t sub, uint8_t proto) {
210 *p++ = 9;
211 *p++ = 0x04; // INTERFACE
212 *p++ = itf;
213 *p++ = alt;
214 *p++ = nEps;
215 *p++ = cls;
216 *p++ = sub;
217 *p++ = proto;
218 *p++ = 0; // iInterface
219 return p;
220 }
221
222 // UAC2 CS AC Interface Header (9 bytes).
223 // Caller patches wTotalLength at offsets [6] and [7].
224 uint8_t* writeCsAcHeader(uint8_t* p) {
225 *p++ = 9;
226 *p++ = 0x24; // CS_INTERFACE
227 *p++ = 0x01; // HEADER
228 *p++ = 0x00;
229 *p++ = 0x02; // bcdADC 2.00
230 *p++ = deviceCategory();
231 *p++ = 0x00; // wTotalLength LSB — patched by caller
232 *p++ = 0x00; // wTotalLength MSB — patched by caller
233 *p++ = 0x00; // bmControls
234 return p;
235 }
236
237 // UAC2 bCategory: Windows uses this to classify the audio endpoint.
238 // Using the wrong category (e.g. IO_BOX for a capture-only device) causes
239 // Windows to look for a playback path that does not exist and fail to
240 // enumerate the audio format (Details tab missing in microphone properties).
241 uint8_t deviceCategory() const {
242 bool has_in = p_config->enable_ep_in;
243 bool has_out = p_config->enable_ep_out;
244 if (has_in && !has_out) return 0x03; // Microphone
245 if (!has_in && has_out) return 0x01; // Desktop Speaker
246 return 0x08; // I/O Box (bidirectional)
247 }
248
249 // UAC2 Clock Source Descriptor (8 bytes)
250 //
251 // bmAttributes D1..D0 — clock type:
252 // 0x00 = external, 0x01 = internal fixed, 0x02 = internal variable,
253 // 0x03 = internal programmable
254 // bmControls — bit-pair encoding:
255 // D1..D0 = Clock Frequency (01=read-only, 11=host-programmable)
256 // D3..D2 = Clock Validity (01=read-only)
257 //
258 // Always declare "internal programmable" (0x03) with "host-programmable
259 // frequency" (0x07), even when only one rate is supported. Windows 11's
260 // usbaudio2.sys requires the ability to round-trip a SET_CUR / GET_CUR for
261 // the clock frequency before it will populate the audio format in the device
262 // properties (Details tab) and accept the device in WASAPI. With a "fixed"
263 // clock (0x01 / 0x05) Windows skips the SET_CUR step at integer rates
264 // (48000, 16000 Hz) and then fails to enumerate the format — the Details tab
265 // does not appear and Audacity returns error -9999. At fractional rates
266 // (44100 Hz) it works by accident because the ceiling arithmetic in
267 // calcMaxPacketSize already signals the irregular-frame nature of the stream.
268 // The single-rate vs multi-rate distinction is carried by GET_RANGE only.
269 uint8_t* writeClockSource(uint8_t* p, uint8_t clock_id) {
270 *p++ = 8;
271 *p++ = 0x24; // CS_INTERFACE
272 *p++ = 0x0A; // CLOCK_SOURCE
273 *p++ = clock_id;
274 *p++ = 0x03; // bmAttributes: internal programmable clock
275 *p++ = 0x07; // bmControls: freq host-programmable (11b), validity read-only (01b)
276 *p++ = 0x00; // bAssocTerminal
277 *p++ = 0x00; // iClockSource
278 return p;
279 }
280
281 // UAC2 Input Terminal Descriptor (17 bytes)
282 uint8_t* writeInputTerminal(uint8_t* p, uint8_t term_id,
283 uint16_t term_type, uint8_t clock_id) {
284 const uint32_t ch_cfg = channelConfig();
285 *p++ = 17;
286 *p++ = 0x24; // CS_INTERFACE
287 *p++ = 0x02; // INPUT_TERMINAL
288 *p++ = term_id;
289 *p++ = (uint8_t)(term_type & 0xFF);
290 *p++ = (uint8_t)(term_type >> 8);
291 *p++ = 0x00; // bAssocTerminal
292 *p++ = clock_id; // bCSourceID
293 *p++ = p_config->channels;
294 *p++ = (uint8_t)(ch_cfg & 0xFF);
295 *p++ = (uint8_t)((ch_cfg >> 8) & 0xFF);
296 *p++ = (uint8_t)((ch_cfg >> 16) & 0xFF);
297 *p++ = (uint8_t)((ch_cfg >> 24) & 0xFF);
298 *p++ = 0; // iChannelNames
299 *p++ = 0x00;
300 *p++ = 0x00; // bmControls
301 *p++ = 0; // iTerminal
302 return p;
303 }
304
305 // UAC2 Feature Unit Descriptor (6 + (channels+1)*4 bytes)
306 //
307 // bmaControls[] is a 32-bit bitmap per channel (+ master at index 0).
308 // Each control is a 2-bit pair:
309 // 00 = not present, 01 = read-only, 11 = host-programmable
310 //
311 // D1..D0 = Mute (FU_CTRL_MUTE = 0x01)
312 // D3..D2 = Volume (FU_CTRL_VOLUME = 0x02)
313 //
314 // 0x0F = Mute host-programmable (11b) | Volume host-programmable (11b)
315 //
316 // Volume uses int16 in 1/256 dB units (0x8000 = silence, 0 = 0 dB).
317 // AudioTools maps this to float 0.0 (silence) – 1.0 (0 dB).
318 // GET_RANGE reports -100 dB .. 0 dB in 1 dB steps.
319 uint8_t* writeFeatureUnit(uint8_t* p, uint8_t unit_id, uint8_t src_id) {
320 const uint8_t len = (uint8_t)(6 + (p_config->channels + 1) * 4);
321 *p++ = len;
322 *p++ = 0x24; // CS_INTERFACE
323 *p++ = 0x06; // FEATURE_UNIT
324 *p++ = unit_id;
325 *p++ = src_id;
326 // Master bmaControls[0]: Mute + Volume, host-programmable
327 *p++ = 0x0F; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;
328 // Per-channel bmaControls[1..N]: same controls
329 for (uint8_t i = 0; i < p_config->channels; i++) {
330 *p++ = 0x0F; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;
331 }
332 *p++ = 0x00; // iFeature
333 return p;
334 }
335
336 // UAC2 Output Terminal Descriptor (12 bytes)
337 uint8_t* writeOutputTerminal(uint8_t* p, uint8_t term_id, uint16_t term_type,
338 uint8_t src_id, uint8_t clock_id) {
339 *p++ = 12;
340 *p++ = 0x24; // CS_INTERFACE
341 *p++ = 0x03; // OUTPUT_TERMINAL
342 *p++ = term_id;
343 *p++ = (uint8_t)(term_type & 0xFF);
344 *p++ = (uint8_t)(term_type >> 8);
345 *p++ = 0x00; // bAssocTerminal
346 *p++ = src_id; // bSourceID
347 *p++ = clock_id; // bCSourceID
348 *p++ = 0x00;
349 *p++ = 0x00; // bmControls
350 *p++ = 0; // iTerminal
351 return p;
352 }
353
354 // UAC2 CS AS Interface Descriptor (16 bytes)
355 uint8_t* writeCsAsInterface(uint8_t* p, uint8_t terminal_link) {
356 const uint32_t ch_cfg = channelConfig();
357 *p++ = 16;
358 *p++ = 0x24; // CS_INTERFACE
359 *p++ = 0x01; // AS_GENERAL
360 *p++ = terminal_link;
361 *p++ = 0x00; // bmControls
362 *p++ = 0x01; // bFormatType TYPE_I
363 // bmFormats: PCM = 0x00000001
364 *p++ = 0x01; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;
365 *p++ = p_config->channels;
366 *p++ = (uint8_t)(ch_cfg & 0xFF);
367 *p++ = (uint8_t)((ch_cfg >> 8) & 0xFF);
368 *p++ = (uint8_t)((ch_cfg >> 16) & 0xFF);
369 *p++ = (uint8_t)((ch_cfg >> 24) & 0xFF);
370 *p++ = 0; // iChannelNames
371 return p;
372 }
373
374 // UAC2 Type I Format Type Descriptor (6 bytes)
375 uint8_t* writeFormatType(uint8_t* p) {
376 *p++ = 6;
377 *p++ = 0x24; // CS_INTERFACE
378 *p++ = 0x02; // FORMAT_TYPE
379 *p++ = 0x01; // FORMAT_TYPE_I
380 *p++ = (uint8_t)(p_config->bits_per_sample / 8); // bSubslotSize
381 *p++ = p_config->bits_per_sample; // bBitResolution
382 return p;
383 }
384
385 // Standard Isochronous Endpoint Descriptor (7 bytes)
386 //
387 // wMaxPacketSize must be large enough for the highest rate the device
388 // advertises in the Clock Source GET_RANGE response. The actual per-frame
389 // byte count varies with the current sample rate; the host will never
390 // send or expect more than wMaxPacketSize in a single (micro)frame.
391 uint8_t* writeIsoEndpoint(uint8_t* p, uint8_t ep_addr) {
392 // Fixed clock: wMaxPacketSize matches the configured rate.
393 // Multi-rate: covers the highest supported rate (192 kHz).
394 const uint16_t pkt = p_config->enable_multi_sample_rate
395 ? calcPacketSizeForRate(192000)
397 // bmAttributes: Isochronous (01) + sync type (bits[3:2]) + usage=data (00)
398 // bits 3:2: 00=None, 01=Async, 10=Adaptive, 11=Sync
399 // IN endpoints: Asynchronous (0x05) — device drives the clock.
400 // OUT endpoints: Asynchronous (0x05) when a feedback EP is present,
401 // Adaptive (0x09) otherwise (device adapts to host rate).
402 bool const is_in = (ep_addr & 0x80u);
403 bool const is_out = !is_in;
404 uint8_t bmAttr;
405 if (is_in) bmAttr = 0x05u; // ISO + Async
406 else if (is_out && enableFeedbackEp()) bmAttr = 0x05u; // ISO + Async
407 else bmAttr = 0x09u; // ISO + Adaptive
408 *p++ = 7;
409 *p++ = 0x05; // ENDPOINT
410 *p++ = ep_addr;
411 *p++ = bmAttr;
412 *p++ = (uint8_t)(pkt & 0xFF);
413 *p++ = (uint8_t)(pkt >> 8);
414 *p++ = 0x01; // bInterval (1 = every frame for FS; host uses 125 µs for HS)
415 return p;
416 }
417
418 // Explicit Feedback Endpoint Descriptor (7 bytes, IN, no CS descriptor)
419 uint8_t* writeFeedbackEndpoint(uint8_t* p, uint8_t ep_addr) {
420 *p++ = 7;
421 *p++ = 0x05; // ENDPOINT
422 *p++ = ep_addr; // must be an IN address (bit 7 set)
423 *p++ = 0x11; // Isochronous, No Sync, Explicit Feedback usage
424 *p++ = 0x04; // wMaxPacketSize LSB (4 bytes)
425 *p++ = 0x00; // wMaxPacketSize MSB
426 *p++ = 0x01; // bInterval
427 return p;
428 }
429
430 // Audio Control Interrupt IN Endpoint Descriptor (7 bytes)
431 //
432 // Carries 6-byte UAC2 status/change notifications (bInfo, bAttribute,
433 // wValue = CS<<8|CN, wIndex = EntityID<<8|Itf) so the device can push
434 // volume, mute, or sample-rate changes to the host.
435 uint8_t* writeInterruptEndpoint(uint8_t* p, uint8_t ep_addr) {
436 *p++ = 7;
437 *p++ = 0x05; // ENDPOINT
438 *p++ = ep_addr; // IN address (bit 7 set)
439 *p++ = 0x03; // bmAttributes: Interrupt
440 *p++ = 0x06; // wMaxPacketSize LSB (6 bytes for UAC2 notification)
441 *p++ = 0x00; // wMaxPacketSize MSB
442 *p++ = 0x10; // bInterval: 2^(16-1) = 32768 frames ≈ poll only when needed
443 return p;
444 }
445
446 // UAC2 CS ISO Endpoint Descriptor (8 bytes)
447 uint8_t* writeCsIsoEndpoint(uint8_t* p) {
448 *p++ = 8;
449 *p++ = 0x25; // CS_ENDPOINT
450 *p++ = 0x01; // EP_GENERAL
451 *p++ = 0x00; // bmAttributes
452 *p++ = 0x00; // bmControls
453 *p++ = 0x00; // bLockDelayUnits (no locking)
454 *p++ = 0x00;
455 *p++ = 0x00; // wLockDelay
456 return p;
457 }
458};
459
460} // namespace audio_tools
USB Audio Class 2.0 descriptor generator.
Definition USBAudio2DescriptorBuilder.h:30
uint8_t * writeInputTerminal(uint8_t *p, uint8_t term_id, uint16_t term_type, uint8_t clock_id)
Definition USBAudio2DescriptorBuilder.h:282
uint8_t * writeFeedbackEndpoint(uint8_t *p, uint8_t ep_addr)
Definition USBAudio2DescriptorBuilder.h:419
uint8_t * writeIsoEndpoint(uint8_t *p, uint8_t ep_addr)
Definition USBAudio2DescriptorBuilder.h:391
uint8_t * writeClockSource(uint8_t *p, uint8_t clock_id)
Definition USBAudio2DescriptorBuilder.h:269
static constexpr uint8_t ENTITY_OT1
first Output Terminal
Definition USBAudio2DescriptorBuilder.h:38
uint8_t * writeCsIsoEndpoint(uint8_t *p)
Definition USBAudio2DescriptorBuilder.h:447
const uint16_t buildFullDescriptor(uint8_t *desc)
Definition USBAudio2DescriptorBuilder.h:54
static constexpr uint8_t ENTITY_FU2
second Feature Unit (RXTX)
Definition USBAudio2DescriptorBuilder.h:40
static constexpr uint8_t ENTITY_FU1
first Feature Unit
Definition USBAudio2DescriptorBuilder.h:37
uint8_t * writeInterruptEndpoint(uint8_t *p, uint8_t ep_addr)
Definition USBAudio2DescriptorBuilder.h:435
uint8_t * writeStdIface(uint8_t *p, uint8_t itf, uint8_t alt, uint8_t nEps, uint8_t cls, uint8_t sub, uint8_t proto)
Definition USBAudio2DescriptorBuilder.h:208
int audioFunctionsCount() const
Definition USBAudio2DescriptorBuilder.h:145
static constexpr uint8_t ENTITY_CLOCK
Definition USBAudio2DescriptorBuilder.h:35
uint8_t * writeOutputTerminal(uint8_t *p, uint8_t term_id, uint16_t term_type, uint8_t src_id, uint8_t clock_id)
Definition USBAudio2DescriptorBuilder.h:337
const uint16_t buildFullDescriptor(uint8_t first_itf, uint8_t *desc)
Definition USBAudio2DescriptorBuilder.h:59
uint8_t deviceCategory() const
Definition USBAudio2DescriptorBuilder.h:241
static constexpr uint8_t ENTITY_IT2
second Input Terminal (RXTX)
Definition USBAudio2DescriptorBuilder.h:39
uint32_t channelConfig() const
Definition USBAudio2DescriptorBuilder.h:185
uint8_t * writeIAD(uint8_t *p, uint8_t first_itf, uint8_t count)
Definition USBAudio2DescriptorBuilder.h:195
uint8_t * writeCsAcHeader(uint8_t *p)
Definition USBAudio2DescriptorBuilder.h:224
static constexpr uint8_t ENTITY_OT2
second Output Terminal (RXTX)
Definition USBAudio2DescriptorBuilder.h:41
static constexpr uint8_t ENTITY_IT1
first Input Terminal
Definition USBAudio2DescriptorBuilder.h:36
uint16_t calcPacketSizeForRate(uint32_t rate) const
Definition USBAudio2DescriptorBuilder.h:163
const uint16_t buildDescriptor(uint8_t, uint8_t, uint8_t *desc)
Definition USBAudio2DescriptorBuilder.h:47
USBAudioConfig * p_config
Definition USBAudio2DescriptorBuilder.h:181
uint8_t * writeFormatType(uint8_t *p)
Definition USBAudio2DescriptorBuilder.h:375
uint16_t calcMaxPacketSize() const
Definition USBAudio2DescriptorBuilder.h:175
bool enableFeedbackEp() const
Definition USBAudio2DescriptorBuilder.h:154
uint8_t * writeFeatureUnit(uint8_t *p, uint8_t unit_id, uint8_t src_id)
Definition USBAudio2DescriptorBuilder.h:319
uint8_t * writeCsAsInterface(uint8_t *p, uint8_t terminal_link)
Definition USBAudio2DescriptorBuilder.h:355
USBAudio2DescriptorBuilder(USBAudioConfig &cfg)
Definition USBAudio2DescriptorBuilder.h:43
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:53
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:55
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:57
Configuration for USB Audio (inherits sample_rate / channels / bits_per_sample from AudioInfo).
Definition USBAudioConfig.h:89
bool enable_interrupt_ep
Definition USBAudioConfig.h:146
int16_t ep_fb
ISO IN (explicit feedback, RX-only mode)
Definition USBAudioConfig.h:106
int16_t ep_in
ISO IN (device → host, capture/microphone)
Definition USBAudioConfig.h:104
bool enable_multi_sample_rate
Definition USBAudioConfig.h:141
int16_t ep_int
INT IN (AC status/change notifications)
Definition USBAudioConfig.h:107
bool enable_feedback_ep
Enable isochronous feedback endpoint so the host can adjust its clock.
Definition USBAudioConfig.h:133
int16_t ep_out
ISO OUT (host → device, playback/speaker)
Definition USBAudioConfig.h:105
bool enable_ep_in
device → host (capture / microphone)
Definition USBAudioConfig.h:92
uint8_t itf_num_ac
Definition USBAudioConfig.h:112
bool enable_ep_out
host → device (playback / speaker)
Definition USBAudioConfig.h:93