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 let channel_config = match self.stream_config.channels {
202 1 => 0x0001u16, 2 => 0x0003u16, 4 => 0x0033u16, 6 => 0x003Fu16, 8 => 0x00FFu16, _ => 0x0003u16, };
209
210 writer.write(
211 CS_INTERFACE,
212 &[
213 INPUT_TERMINAL, ID_INPUT_TERMINAL + id_offset, tt[0], tt[1],
217 0x00, self.stream_config.channels, (channel_config & 0xFF) as u8,
220 (channel_config >> 8) as u8, 0x00, 0x00, ],
224 )?;
225
226 let tt = if is_input {
228 TerminalType::UsbStreaming.into()
229 } else {
230 terminal_type
231 }
232 .to_le_bytes();
233 writer.write(
234 CS_INTERFACE,
235 &[
236 OUTPUT_TERMINAL, ID_OUTPUT_TERMINAL + id_offset, tt[0], tt[1],
240 0x00, ID_INPUT_TERMINAL + id_offset, 0x00, ],
244 )
245 }
246
247 fn write_as_and_ep_descriptors(&self, writer: &mut DescriptorWriter) -> usb_device::Result<()> {
248 let is_input = self.endpoint.address().direction() == UsbDirection::In;
249 let id_offset = if is_input { 0 } else { 4 };
250 writer.interface(self.interface, AUDIO, AUDIOSTREAMING, 0x00)?;
252
253 writer.interface_alt(self.interface, 0x01, AUDIO, AUDIOSTREAMING, 0x00, None)?;
255
256 let terminal_link = id_offset
258 + if is_input {
259 ID_OUTPUT_TERMINAL
260 } else {
261 ID_INPUT_TERMINAL
262 };
263 writer.write(
264 CS_INTERFACE,
265 &[
266 AS_GENERAL, terminal_link, 0x01, PCM as u8,
270 (PCM >> 8) as u8, ],
272 )?;
273
274 let mut format_desc = [0x00u8; 128];
276 let mut iter = format_desc.iter_mut().enumerate();
277 append!(iter, FORMAT_TYPE); append!(iter, FORMAT_TYPE_I); append!(iter, self.stream_config.channels); append!(
281 iter,
282 match self.stream_config.format {
283 Format::S16le => 2,
285 Format::S24le => 3,
286 }
287 );
288 append!(
289 iter,
290 match self.stream_config.format {
291 Format::S16le => 16,
293 Format::S24le => 24,
294 }
295 );
296 match self.stream_config.rates {
297 Rates::Continuous(min, max) => {
298 append!(iter, 0x00); append_u24le!(iter, min);
300 append_u24le!(iter, max);
301 }
302 Rates::Discrete(rates) => {
303 append!(iter, rates.len() as u8); for rate in rates {
305 append_u24le!(iter, *rate);
306 }
307 }
308 }
309 let length = iter.next().unwrap().0;
310 writer.write(CS_INTERFACE, &format_desc[..length])?;
311
312 writer.endpoint(&self.endpoint)?;
314
315 writer.write(
317 0x25,
318 &[
319 0x01, 0x00, 0x00, 0x00, 0x00, ],
325 )
326 }
327}
328
329pub struct AudioClassBuilder<'a> {
331 input: Option<StreamConfig<'a>>,
332 output: Option<StreamConfig<'a>>,
333}
334
335impl<'a> AudioClassBuilder<'a> {
336 pub fn new() -> AudioClassBuilder<'static> {
338 AudioClassBuilder {
339 input: None,
340 output: None,
341 }
342 }
343
344 pub fn input(self, input: StreamConfig<'a>) -> AudioClassBuilder<'a> {
348 AudioClassBuilder {
349 input: Some(input),
350 output: self.output,
351 }
352 }
353
354 pub fn output(self, output: StreamConfig<'a>) -> AudioClassBuilder<'a> {
358 AudioClassBuilder {
359 input: self.input,
360 output: Some(output),
361 }
362 }
363
364 pub fn build<B: UsbBus>(self, alloc: &'a UsbBusAllocator<B>) -> Result<AudioClass<'a, B>> {
366 let control_iface = alloc.interface();
367 let mut ac = AudioClass {
368 control_iface,
369 input: None,
370 output: None,
371 };
372 if let Some(stream_config) = self.input {
373 let interface = alloc.interface();
374 let endpoint = alloc.alloc(
375 None,
376 EndpointType::Isochronous {
377 synchronization: IsochronousSynchronizationType::Asynchronous,
378 usage: IsochronousUsageType::Data,
379 },
380 stream_config.ep_size,
381 1,
382 )?;
383 let alt_setting = DEFAULT_ALTERNATE_SETTING;
384 ac.input = Some(AudioStream {
385 stream_config,
386 interface,
387 endpoint,
388 alt_setting,
389 })
390 }
391
392 if let Some(stream_config) = self.output {
393 let interface = alloc.interface();
394 let endpoint = alloc.alloc(
395 None,
396 EndpointType::Isochronous {
397 synchronization: IsochronousSynchronizationType::Adaptive,
398 usage: IsochronousUsageType::Data,
399 },
400 stream_config.ep_size,
401 1,
402 )?;
403 let alt_setting = DEFAULT_ALTERNATE_SETTING;
404 ac.output = Some(AudioStream {
405 stream_config,
406 interface,
407 endpoint,
408 alt_setting,
409 })
410 }
411
412 Ok(ac)
413 }
414}
415
416pub struct AudioClass<'a, B: UsbBus> {
422 control_iface: InterfaceNumber,
423 input: Option<AudioStream<'a, B, In>>,
424 output: Option<AudioStream<'a, B, Out>>,
425}
426
427impl<B: UsbBus> AudioClass<'_, B> {
428 pub fn read(&self, data: &mut [u8]) -> Result<usize> {
431 if let Some(ref info) = self.output {
432 info.endpoint.read(data).map_err(Error::UsbError)
433 } else {
434 Err(Error::StreamNotInitialized)
435 }
436 }
437
438 pub fn write(&self, data: &[u8]) -> Result<usize> {
441 if let Some(ref info) = self.input {
442 info.endpoint.write(data).map_err(Error::UsbError)
443 } else {
444 Err(Error::StreamNotInitialized)
445 }
446 }
447
448 pub fn input_alt_setting(&self) -> Result<u8> {
451 self.input
452 .as_ref()
453 .ok_or(Error::StreamNotInitialized)
454 .map(|si| si.alt_setting)
455 }
456
457 pub fn output_alt_setting(&self) -> Result<u8> {
460 self.output
461 .as_ref()
462 .ok_or(Error::StreamNotInitialized)
463 .map(|si| si.alt_setting)
464 }
465}
466
467impl<B: UsbBus> UsbClass<B> for AudioClass<'_, B> {
468 fn get_configuration_descriptors(
469 &self,
470 writer: &mut DescriptorWriter,
471 ) -> usb_device::Result<()> {
472 let mut in_collection = 0u8;
473 if self.input.is_some() {
474 in_collection += 1;
475 }
476 if self.output.is_some() {
477 in_collection += 1;
478 }
479
480 writer.iad(
481 self.control_iface,
482 in_collection + 1, AUDIO, AUDIOCONTROL,
485 0x00, None, )?;
488
489 writer.interface(self.control_iface, AUDIO, AUDIOCONTROL, 0x00)?;
491
492 let total_length = 8u16 + (1 + 21) * in_collection as u16;
493
494 let mut ac_header = [
495 HEADER, 0x00,
497 0x01, total_length as u8,
499 (total_length >> 8) as u8, in_collection, 0x00,
502 0x00, ];
504 let mut ndx = 6;
505 if let Some(ref input) = self.input {
506 ac_header[ndx] = input.interface.into();
507 ndx += 1;
508 }
509 if let Some(ref output) = self.output {
510 ac_header[ndx] = output.interface.into();
511 ndx += 1;
512 }
513 writer.write(CS_INTERFACE, &ac_header[..ndx])?;
514 if let Some(ref a) = self.input {
515 a.write_ac_descriptors(writer)?;
516 }
517 if let Some(ref a) = self.output {
518 a.write_ac_descriptors(writer)?;
519 }
520
521 if let Some(ref a) = self.input {
523 a.write_as_and_ep_descriptors(writer)?;
524 }
525 if let Some(ref a) = self.output {
526 a.write_as_and_ep_descriptors(writer)?;
527 }
528 Ok(())
529 }
530
531 fn control_in(&mut self, xfer: ControlIn<B>) {
532 let req = xfer.request();
533 if req.request_type == RequestType::Standard
534 && req.recipient == Recipient::Interface
535 && req.request == Request::GET_INTERFACE
536 && req.length == 1
537 {
538 let iface = req.index as u8;
539 if let Some(info) = self.input.as_ref() {
540 if iface == info.interface.into() {
541 xfer.accept_with(&[info.alt_setting]).ok();
542 return;
543 }
544 }
545 if let Some(info) = self.output.as_ref() {
546 if iface == info.interface.into() {
547 xfer.accept_with(&[info.alt_setting]).ok();
548 }
549 }
550 }
551 }
552
553 fn control_out(&mut self, xfer: ControlOut<B>) {
554 let req = xfer.request();
555 if req.request_type == RequestType::Standard
556 && req.recipient == Recipient::Interface
557 && req.request == Request::SET_INTERFACE
558 {
559 let iface = req.index as u8;
560 let alt_setting = req.value;
561
562 if let Some(info) = self.input.as_mut() {
563 if iface == info.interface.into() {
564 info.alt_setting = alt_setting as u8;
565 xfer.accept().ok();
566 return;
567 }
568 }
569 if let Some(info) = self.output.as_mut() {
570 if iface == info.interface.into() {
571 info.alt_setting = alt_setting as u8;
572 xfer.accept().ok();
573 }
574 }
575 }
576 }
577}