1#![no_std]
36
37use class_codes::*;
38use core::convert::From;
39use usb_device::control::{Recipient, Request, RequestType};
40use usb_device::device::DEFAULT_ALTERNATE_SETTING;
41use usb_device::endpoint::{Endpoint, EndpointDirection, In, Out};
42use usb_device::{class_prelude::*, UsbDirection};
43
44mod terminal_type;
45pub use terminal_type::TerminalType;
46mod class_codes;
47
48const ID_INPUT_TERMINAL: u8 = 0x01;
49const ID_OUTPUT_TERMINAL: u8 = 0x02;
50
51const MAX_ISO_EP_SIZE: u32 = 1023;
52
53#[derive(Clone, Copy, Debug)]
54pub enum Format {
55 S16le,
57 S24le,
59}
60
61#[derive(Debug)]
63pub enum Rates<'a> {
64 Continuous(u32, u32),
68 Discrete(&'a [u32]),
70}
71
72#[derive(Debug)]
73pub struct StreamConfig<'a> {
74 format: Format,
75 channels: u8,
76 rates: Rates<'a>,
77 terminal_type: TerminalType,
78 ep_size: u16,
81}
82
83impl StreamConfig<'_> {
84 pub fn new_discrete(
89 format: Format,
90 channels: u8,
91 rates: &'_ [u32],
92 terminal_type: TerminalType,
93 ) -> Result<StreamConfig<'_>> {
94 let max_rate = rates.iter().max().unwrap();
95 let ep_size = Self::ep_size(format, channels, *max_rate)?;
96 let rates = Rates::Discrete(rates);
97 Ok(StreamConfig {
98 format,
99 channels,
100 rates,
101 terminal_type,
102 ep_size,
103 })
104 }
105
106 pub fn new_continuous(
111 format: Format,
112 channels: u8,
113 min_rate: u32,
114 max_rate: u32,
115 terminal_type: TerminalType,
116 ) -> Result<StreamConfig<'static>> {
117 if min_rate >= max_rate {
118 return Err(Error::InvalidValue);
119 }
120 let ep_size = Self::ep_size(format, channels, max_rate)?;
121 let rates = Rates::Continuous(min_rate, max_rate);
122 Ok(StreamConfig {
123 format,
124 channels,
125 rates,
126 terminal_type,
127 ep_size,
128 })
129 }
130
131 fn ep_size(format: Format, channels: u8, max_rate: u32) -> Result<u16> {
133 let octets_per_frame = channels as u32
134 * match format {
135 Format::S16le => 2,
136 Format::S24le => 3,
137 };
138 let ep_size = octets_per_frame * max_rate / 1000;
139 if ep_size > MAX_ISO_EP_SIZE {
140 return Err(Error::BandwidthExceeded);
141 }
142 Ok(ep_size as u16)
143 }
144}
145
146#[derive(Debug)]
148pub enum Error {
149 InvalidValue,
150 BandwidthExceeded,
151 StreamNotInitialized,
152 UsbError(usb_device::UsbError),
153}
154
155impl From<UsbError> for Error {
156 fn from(err: UsbError) -> Self {
157 Error::UsbError(err)
158 }
159}
160
161type Result<T> = core::result::Result<T, Error>;
163
164struct AudioStream<'a, B: UsbBus, D: EndpointDirection> {
166 stream_config: StreamConfig<'a>,
167 interface: InterfaceNumber,
168 endpoint: Endpoint<'a, B, D>,
169 alt_setting: u8,
170}
171
172macro_rules! append {
173 ($iter:ident, $value:expr) => {
174 *($iter.next().ok_or(UsbError::BufferOverflow)?.1) = $value;
175 };
176}
177
178macro_rules! append_u24le {
179 ($iter:ident, $value:expr) => {
180 append!($iter, $value as u8);
181 append!($iter, ($value >> 8) as u8);
182 append!($iter, ($value >> 16) as u8);
183 };
184}
185
186impl<B: UsbBus, D: EndpointDirection> AudioStream<'_, B, D> {
187 fn write_ac_descriptors(&self, writer: &mut DescriptorWriter) -> usb_device::Result<()> {
188 let is_input = self.endpoint.address().direction() == UsbDirection::In;
189 let terminal_type: u16 = self.stream_config.terminal_type.into();
190 let id_offset = if is_input { 0 } else { 4 };
191
192 let tt = if is_input {
194 terminal_type
195 } else {
196 TerminalType::UsbStreaming.into()
197 }
198 .to_le_bytes();
199
200 writer.write(
201 CS_INTERFACE,
202 &[
203 INPUT_TERMINAL, ID_INPUT_TERMINAL + id_offset, tt[0], tt[1],
207 0x00, self.stream_config.channels, 0x03,
210 0x00, 0x00, 0x00, ],
214 )?;
215
216 let tt = if is_input {
218 TerminalType::UsbStreaming.into()
219 } else {
220 terminal_type
221 }
222 .to_le_bytes();
223 writer.write(
224 CS_INTERFACE,
225 &[
226 OUTPUT_TERMINAL, ID_OUTPUT_TERMINAL + id_offset, tt[0], tt[1],
230 0x00, ID_INPUT_TERMINAL + id_offset, 0x00, ],
234 )
235 }
236
237 fn write_as_and_ep_descriptors(&self, writer: &mut DescriptorWriter) -> usb_device::Result<()> {
238 let is_input = self.endpoint.address().direction() == UsbDirection::In;
239 let id_offset = if is_input { 0 } else { 4 };
240 writer.interface(self.interface, AUDIO, AUDIOSTREAMING, 0x00)?;
242
243 writer.interface_alt(self.interface, 0x01, AUDIO, AUDIOSTREAMING, 0x00, None)?;
245
246 let terminal_link = id_offset
248 + if is_input {
249 ID_OUTPUT_TERMINAL
250 } else {
251 ID_INPUT_TERMINAL
252 };
253 writer.write(
254 CS_INTERFACE,
255 &[
256 AS_GENERAL, terminal_link, 0x01, PCM as u8,
260 (PCM >> 8) as u8, ],
262 )?;
263
264 let mut format_desc = [0x00u8; 128];
266 let mut iter = format_desc.iter_mut().enumerate();
267 append!(iter, FORMAT_TYPE); append!(iter, FORMAT_TYPE_I); append!(iter, self.stream_config.channels); append!(
271 iter,
272 match self.stream_config.format {
273 Format::S16le => 2,
275 Format::S24le => 3,
276 }
277 );
278 append!(
279 iter,
280 match self.stream_config.format {
281 Format::S16le => 16,
283 Format::S24le => 24,
284 }
285 );
286 match self.stream_config.rates {
287 Rates::Continuous(min, max) => {
288 append!(iter, 0x00); append_u24le!(iter, min);
290 append_u24le!(iter, max);
291 }
292 Rates::Discrete(rates) => {
293 append!(iter, rates.len() as u8); for rate in rates {
295 append_u24le!(iter, *rate);
296 }
297 }
298 }
299 let length = iter.next().unwrap().0;
300 writer.write(CS_INTERFACE, &format_desc[..length])?;
301
302 writer.endpoint(&self.endpoint)?;
304
305 writer.write(
307 0x25,
308 &[
309 0x01, 0x00, 0x00, 0x00, 0x00, ],
315 )
316 }
317}
318
319pub struct AudioClassBuilder<'a> {
321 input: Option<StreamConfig<'a>>,
322 output: Option<StreamConfig<'a>>,
323}
324
325impl<'a> AudioClassBuilder<'a> {
326 pub fn new() -> AudioClassBuilder<'static> {
328 AudioClassBuilder {
329 input: None,
330 output: None,
331 }
332 }
333
334 pub fn input(self, input: StreamConfig<'a>) -> AudioClassBuilder<'a> {
338 AudioClassBuilder {
339 input: Some(input),
340 output: self.output,
341 }
342 }
343
344 pub fn output(self, output: StreamConfig<'a>) -> AudioClassBuilder<'a> {
348 AudioClassBuilder {
349 input: self.input,
350 output: Some(output),
351 }
352 }
353
354 pub fn build<B: UsbBus>(self, alloc: &'a UsbBusAllocator<B>) -> Result<AudioClass<'a, B>> {
356 let control_iface = alloc.interface();
357 let mut ac = AudioClass {
358 control_iface,
359 input: None,
360 output: None,
361 };
362 if let Some(stream_config) = self.input {
363 let interface = alloc.interface();
364 let endpoint = alloc.alloc(
365 None,
366 EndpointType::Isochronous {
367 synchronization: IsochronousSynchronizationType::Asynchronous,
368 usage: IsochronousUsageType::Data,
369 },
370 stream_config.ep_size,
371 1,
372 )?;
373 let alt_setting = DEFAULT_ALTERNATE_SETTING;
374 ac.input = Some(AudioStream {
375 stream_config,
376 interface,
377 endpoint,
378 alt_setting,
379 })
380 }
381
382 if let Some(stream_config) = self.output {
383 let interface = alloc.interface();
384 let endpoint = alloc.alloc(
385 None,
386 EndpointType::Isochronous {
387 synchronization: IsochronousSynchronizationType::Adaptive,
388 usage: IsochronousUsageType::Data,
389 },
390 stream_config.ep_size,
391 1,
392 )?;
393 let alt_setting = DEFAULT_ALTERNATE_SETTING;
394 ac.output = Some(AudioStream {
395 stream_config,
396 interface,
397 endpoint,
398 alt_setting,
399 })
400 }
401
402 Ok(ac)
403 }
404}
405
406pub struct AudioClass<'a, B: UsbBus> {
412 control_iface: InterfaceNumber,
413 input: Option<AudioStream<'a, B, In>>,
414 output: Option<AudioStream<'a, B, Out>>,
415}
416
417impl<B: UsbBus> AudioClass<'_, B> {
418 pub fn read(&self, data: &mut [u8]) -> Result<usize> {
421 if let Some(ref info) = self.output {
422 info.endpoint.read(data).map_err(Error::UsbError)
423 } else {
424 Err(Error::StreamNotInitialized)
425 }
426 }
427
428 pub fn write(&self, data: &[u8]) -> Result<usize> {
431 if let Some(ref info) = self.input {
432 info.endpoint.write(data).map_err(Error::UsbError)
433 } else {
434 Err(Error::StreamNotInitialized)
435 }
436 }
437
438 pub fn input_alt_setting(&self) -> Result<u8> {
441 self.input
442 .as_ref()
443 .ok_or(Error::StreamNotInitialized)
444 .map(|si| si.alt_setting)
445 }
446
447 pub fn output_alt_setting(&self) -> Result<u8> {
450 self.output
451 .as_ref()
452 .ok_or(Error::StreamNotInitialized)
453 .map(|si| si.alt_setting)
454 }
455}
456
457impl<B: UsbBus> UsbClass<B> for AudioClass<'_, B> {
458 fn get_configuration_descriptors(
459 &self,
460 writer: &mut DescriptorWriter,
461 ) -> usb_device::Result<()> {
462 let mut in_collection = 0u8;
463 if self.input.is_some() {
464 in_collection += 1;
465 }
466 if self.output.is_some() {
467 in_collection += 1;
468 }
469
470 writer.iad(
471 self.control_iface,
472 in_collection + 1, AUDIO, AUDIOCONTROL,
475 0x00, None, )?;
478
479 writer.interface(self.control_iface, AUDIO, AUDIOCONTROL, 0x00)?;
481
482 let total_length = 8u16 + (1 + 21) * in_collection as u16;
483
484 let mut ac_header = [
485 HEADER, 0x00,
487 0x01, total_length as u8,
489 (total_length >> 8) as u8, in_collection, 0x00,
492 0x00, ];
494 let mut ndx = 6;
495 if let Some(ref input) = self.input {
496 ac_header[ndx] = input.interface.into();
497 ndx += 1;
498 }
499 if let Some(ref output) = self.output {
500 ac_header[ndx] = output.interface.into();
501 ndx += 1;
502 }
503 writer.write(CS_INTERFACE, &ac_header[..ndx])?;
504 if let Some(ref a) = self.input {
505 a.write_ac_descriptors(writer)?;
506 }
507 if let Some(ref a) = self.output {
508 a.write_ac_descriptors(writer)?;
509 }
510
511 if let Some(ref a) = self.input {
513 a.write_as_and_ep_descriptors(writer)?;
514 }
515 if let Some(ref a) = self.output {
516 a.write_as_and_ep_descriptors(writer)?;
517 }
518 Ok(())
519 }
520
521 fn control_in(&mut self, xfer: ControlIn<B>) {
522 let req = xfer.request();
523 if req.request_type == RequestType::Standard
524 && req.recipient == Recipient::Interface
525 && req.request == Request::GET_INTERFACE
526 && req.length == 1
527 {
528 let iface = req.index as u8;
529 if let Some(info) = self.input.as_ref() {
530 if iface == info.interface.into() {
531 xfer.accept_with(&[info.alt_setting]).ok();
532 return;
533 }
534 }
535 if let Some(info) = self.output.as_ref() {
536 if iface == info.interface.into() {
537 xfer.accept_with(&[info.alt_setting]).ok();
538 }
539 }
540 }
541 }
542
543 fn control_out(&mut self, xfer: ControlOut<B>) {
544 let req = xfer.request();
545 if req.request_type == RequestType::Standard
546 && req.recipient == Recipient::Interface
547 && req.request == Request::SET_INTERFACE
548 {
549 let iface = req.index as u8;
550 let alt_setting = req.value;
551
552 if let Some(info) = self.input.as_mut() {
553 if iface == info.interface.into() {
554 info.alt_setting = alt_setting as u8;
555 xfer.accept().ok();
556 return;
557 }
558 }
559 if let Some(info) = self.output.as_mut() {
560 if iface == info.interface.into() {
561 info.alt_setting = alt_setting as u8;
562 xfer.accept().ok();
563 }
564 }
565 }
566 }
567}