1#[allow(missing_docs)]
34pub mod codes;
35pub mod descriptors;
36
37use core::future::{Future, poll_fn};
38use core::pin::pin;
39use core::task::Poll;
40
41use aligned::{A4, Aligned};
42use embassy_time::{Duration, Instant, Timer};
43use embassy_usb::control::Request;
44use embassy_usb_driver::host::{HostError, PipeError, UsbHostAllocator, UsbPipe, pipe};
45use embassy_usb_driver::{Direction, EndpointInfo, EndpointType, Speed};
46use heapless::{String, Vec};
47
48use crate::control::{ControlType, Recipient, RequestType, SetupPacket};
49use crate::descriptor::DEFAULT_MAX_DESCRIPTOR_SIZE;
50use crate::handler::{EnumerationInfo, RegisterError};
51
52const MAX_RANGES: usize = 16;
53const MAX_STRING_BUF_SIZE: usize = 255;
55const MAX_STRING_LENGTH: usize = 127;
57
58pub struct UacHandler<'d, A: UsbHostAllocator<'d>> {
63 pub interface_collection: descriptors::AudioInterfaceCollection,
65 pub control_channel: A::Pipe<pipe::Control, pipe::InOut>,
67 pub output_channel: Option<A::Pipe<pipe::Isochronous, pipe::Out>>,
69 pub feedback_channel: Option<A::Pipe<pipe::Isochronous, pipe::In>>,
71 input_terminal_id: u8,
72 output_interface_idx: usize,
73 speed: Speed,
74 _phantom: core::marker::PhantomData<&'d ()>,
75}
76
77#[derive(Debug)]
79#[cfg_attr(feature = "defmt", derive(defmt::Format))]
80pub enum RequestError {
81 RequestFailed(PipeError),
83 DeviceDisconnected,
85 InvalidResponse,
87 NoSupportedInterface,
89}
90
91impl<'d, A: UsbHostAllocator<'d>> UacHandler<'d, A> {
92 pub async fn try_register(alloc: &A, enum_info: EnumerationInfo) -> Result<Self, RegisterError> {
99 let mut control_channel = alloc.alloc_pipe::<pipe::Control, pipe::InOut>(
107 enum_info.device_address,
108 &EndpointInfo {
109 addr: 0.into(),
110 ep_type: EndpointType::Control,
111 max_packet_size: (enum_info.device_desc.max_packet_size0 as u16)
112 .min(enum_info.speed().max_packet_size()),
113 interval_ms: 0,
114 },
115 enum_info.split(),
116 )?;
117
118 let mut cfg_desc_buf = [0u8; DEFAULT_MAX_DESCRIPTOR_SIZE];
119 let configuration = enum_info
120 .active_config_or_set_default(&mut control_channel, &mut cfg_desc_buf)
121 .await?;
122
123 let interface_collection = match descriptors::AudioInterfaceCollection::try_from_configuration(&configuration) {
124 Ok(collection) => collection,
125 Err(e) => {
126 warn!("Failed to parse Audio Interface Collection: {:#?}", e);
127 return Err(RegisterError::NoSupportedInterface);
128 }
129 };
130 debug!("[UAC] Audio Interface Collection: {:#?}", interface_collection);
131
132 let output_interface_idx = interface_collection
134 .audio_streaming_interfaces
135 .iter()
136 .position(|i| {
137 i.endpoint_descriptor
138 .map(|e| e.ep_dir() == Direction::Out)
139 .unwrap_or(false)
140 })
141 .ok_or(RegisterError::NoSupportedInterface)?;
142 let output_interface = &interface_collection.audio_streaming_interfaces[output_interface_idx];
143
144 let input_terminal = interface_collection
146 .control_interface
147 .terminal_descriptors
148 .get(&output_interface.class_descriptor.terminal_link_id)
149 .ok_or(RegisterError::NoSupportedInterface)?;
150
151 debug!("[UAC] Input Terminal: {:#?}", input_terminal);
152
153 if output_interface.class_descriptor.format != codes::format_type::Format::Type1(codes::format_type::Type1::PCM)
155 {
156 error!(
157 "[UAC] Only PCM format is supported, got {:?}",
158 output_interface.class_descriptor.format
159 );
160 return Err(RegisterError::NoSupportedInterface);
161 }
162
163 let streaming_interface = output_interface
165 .interface_descriptors
166 .iter()
167 .max_by_key(|i| i.num_endpoints)
168 .ok_or(RegisterError::NoSupportedInterface)?;
169
170 let mut output_channel = None;
172 let mut feedback_channel = None;
173 let input_terminal_id = output_interface.class_descriptor.terminal_link_id;
174 let packet = SetupPacket {
176 request_type: RequestType {
177 direction: Direction::Out,
178 control_type: ControlType::Standard,
179 recipient: Recipient::Interface,
180 },
181 request: Request::SET_INTERFACE,
182 value: streaming_interface.alternate_setting as u16,
183 index: streaming_interface.interface_number as u16,
184 length: 0,
185 };
186 control_channel
187 .control_out(&packet.to_bytes(), &mut [])
188 .await
189 .map_err(|e| RegisterError::HostError(HostError::PipeError(e)))?;
190 debug!(
191 "[UAC] Set output interface to alternate setting: {}",
192 streaming_interface.alternate_setting
193 );
194
195 if streaming_interface.num_endpoints > 0 {
196 output_channel = Some(alloc.alloc_pipe::<pipe::Isochronous, pipe::Out>(
197 enum_info.device_address,
198 &output_interface.endpoint_descriptor.unwrap().into(),
199 enum_info.split(),
200 )?);
201 }
202 if streaming_interface.num_endpoints > 1 {
203 if let Some(feedback_endpoint) = output_interface.feedback_endpoint_descriptor {
204 feedback_channel = Some(alloc.alloc_pipe::<pipe::Isochronous, pipe::In>(
205 enum_info.device_address,
206 &feedback_endpoint.into(),
207 enum_info.split(),
208 )?);
209 }
210 }
211
212 Ok(Self {
213 interface_collection,
214 control_channel,
215 output_channel,
216 feedback_channel,
217 input_terminal_id,
218 output_interface_idx,
219 speed: enum_info.speed(),
220 _phantom: core::marker::PhantomData,
221 })
222 }
223
224 pub async fn output(&mut self) -> Result<UacOut<'d, A>, RequestError> {
228 if self.output_channel.is_none() {
229 error!("[UAC] Output pipe not allocated");
230 return Err(RequestError::DeviceDisconnected);
231 }
232
233 let output_interface = self.output_interface();
234 let num_channels = output_interface.class_descriptor.num_channels;
235 let lock_delay = if let Some(desc) = &output_interface.audio_endpoint_descriptor {
236 if desc.lock_delay_units == 1 {
237 LockDelay::Milliseconds(desc.lock_delay)
238 } else if desc.lock_delay_units == 2 {
239 LockDelay::Samples(desc.lock_delay)
240 } else {
241 LockDelay::Samples(0)
242 }
243 } else {
244 LockDelay::Samples(0)
245 };
246 let bytes_per_sample = match output_interface.format_type_descriptor {
247 Some(descriptors::FormatTypeDescriptor::I(descriptors::FormatTypeI { subslot_size, .. })) => {
248 subslot_size as usize
249 }
250 _ => return Err(RequestError::NoSupportedInterface),
251 };
252 let max_bytes_per_packet = output_interface.endpoint_descriptor.unwrap().max_packet_size as usize;
253 let mut num_retries = 3;
255 let sampling_freq = loop {
256 let sampling_freq = self.get_sampling_freq(self.input_terminal().clock_source_id()).await;
257 if let Err(e) = sampling_freq {
258 num_retries -= 1;
259 if num_retries == 0 {
260 error!("[UAC] Failed to get sampling frequency after 3 retries: {:#?}", e);
261 return Err(e);
262 }
263 Timer::after(Duration::from_millis(10)).await;
264 continue;
265 }
266 break sampling_freq.unwrap();
267 };
268 let samples_per_microframe = sampling_freq as f32
269 / match self.speed {
270 Speed::High => 8000.0,
271 _ => 1000.0,
272 };
273
274 Ok(UacOut::<'d, A> {
275 output_channel: self.output_channel.take().unwrap(),
276 feedback_channel: self.feedback_channel.take(),
277 speed: self.speed,
278 samples_per_microframe,
279 microframes_per_microsecond: 1.0 / (if self.speed == Speed::High { 125.0 } else { 1000.0 }),
280 send_start: Instant::from_ticks(0),
281 num_frames: 0,
282 last_feedback_time: Instant::from_ticks(0),
283 lock_delay,
284 num_channels,
285 bytes_per_sample,
286 max_bytes_per_packet,
287 _phantom: core::marker::PhantomData,
288 })
289 }
290
291 pub fn input_terminal(&self) -> &descriptors::TerminalDescriptor {
293 &self.interface_collection.control_interface.terminal_descriptors[&self.input_terminal_id]
294 }
295
296 pub fn output_interface(&self) -> &descriptors::AudioStreamingInterface {
298 &self.interface_collection.audio_streaming_interfaces[self.output_interface_idx]
299 }
300
301 pub async fn get_sampling_freq(&mut self, terminal_id: u8) -> Result<u32, RequestError> {
305 self.get_curr_entity3(
306 codes::control_selector::clock_source::SAMPLING_FREQ_CONTROL,
307 0,
308 terminal_id,
309 0,
310 )
311 .await
312 }
313
314 pub async fn get_supported_language(&mut self) -> Result<u16, RequestError> {
322 let packet = SetupPacket {
323 request_type: RequestType {
324 direction: Direction::In,
325 control_type: ControlType::Standard,
326 recipient: Recipient::Device,
327 },
328 request: Request::GET_DESCRIPTOR,
329 value: 0x0300, index: 0x00,
331 length: 4,
332 };
333
334 let mut buf = Aligned::<A4, _>([0; 4]);
335
336 self.control_channel
337 .control_in(&packet.to_bytes(), buf.as_mut_slice())
338 .await
339 .map_err(|e| RequestError::RequestFailed(e))?;
340
341 Ok(u16::from_le_bytes([buf[2], buf[3]]))
342 }
343
344 pub async fn get_string(
352 &mut self,
353 index: crate::descriptor::StringIndex,
354 lang_id: u16,
355 ) -> Result<String<MAX_STRING_LENGTH>, RequestError> {
356 let packet = SetupPacket {
358 request_type: RequestType {
359 direction: Direction::In,
360 control_type: ControlType::Standard,
361 recipient: Recipient::Device,
362 },
363 request: Request::GET_DESCRIPTOR,
364 value: (0x03 << 8) | index as u16,
365 index: lang_id,
366 length: 2, };
368
369 let mut length_buf = Aligned::<A4, _>([0; 2]);
370 self.control_channel
371 .control_in(&packet.to_bytes(), length_buf.as_mut_slice())
372 .await
373 .map_err(|e| RequestError::RequestFailed(e))?;
374
375 if length_buf[1] != 0x03 {
376 return Err(RequestError::InvalidResponse);
377 }
378
379 let total_length = length_buf[0] as u16;
380 if total_length == 0 || total_length > MAX_STRING_BUF_SIZE as u16 {
381 return Err(RequestError::InvalidResponse);
382 }
383
384 let packet = SetupPacket {
386 request_type: RequestType {
387 direction: Direction::In,
388 control_type: ControlType::Standard,
389 recipient: Recipient::Device,
390 },
391 request: Request::GET_DESCRIPTOR,
392 value: (0x03 << 8) | index as u16,
393 index: lang_id,
394 length: total_length,
395 };
396
397 let mut buf = Aligned::<A4, _>([0; MAX_STRING_BUF_SIZE]);
398 self.control_channel
399 .control_in(&packet.to_bytes(), &mut buf.as_mut_slice()[..total_length as usize])
400 .await
401 .map_err(|e| RequestError::RequestFailed(e))?;
402
403 let mut buf = &buf.as_mut_slice()[2..total_length as usize];
405 let mut str = String::new();
406 while buf.len() >= 2 {
407 let b = u16::from_le_bytes([buf[0], buf[1]]);
408 if b == 0 {
409 break;
410 }
411 if let Some(c) = char::from_u32(b as u32) {
412 str.push(c).unwrap(); } else {
414 return Err(RequestError::InvalidResponse);
415 }
416 buf = &buf[2..];
417 }
418
419 Ok(str)
420 }
421
422 pub async fn get_curr_entity1(
432 &mut self,
433 control_selector: u16,
434 channel: u8,
435 entity: u8,
436 interface: u8,
437 ) -> Result<u8, RequestError> {
438 let packet = SetupPacket {
439 request_type: RequestType {
440 direction: Direction::In,
441 control_type: ControlType::Class,
442 recipient: Recipient::Interface,
443 },
444 request: codes::request_code::CUR,
445 value: (channel as u16) << 8 | control_selector as u16,
446 index: (entity as u16) << 8 | interface as u16,
447 length: 1,
448 };
449
450 let mut buf = Aligned::<A4, _>([0; 1]);
451
452 self.control_channel
453 .control_in(&packet.to_bytes(), buf.as_mut_slice())
454 .await
455 .map_err(|e| RequestError::RequestFailed(e))?;
456
457 Ok(buf[0])
458 }
459
460 pub async fn get_curr_entity2(
470 &mut self,
471 control_selector: u16,
472 channel: u8,
473 entity: u8,
474 interface: u8,
475 ) -> Result<u16, RequestError> {
476 let packet = SetupPacket {
477 request_type: RequestType {
478 direction: Direction::In,
479 control_type: ControlType::Class,
480 recipient: Recipient::Interface,
481 },
482 request: codes::request_code::CUR,
483 value: (channel as u16) << 8 | control_selector,
484 index: (entity as u16) << 8 | interface as u16,
485 length: 2,
486 };
487
488 let mut buf = Aligned::<A4, _>([0; 2]);
489
490 self.control_channel
491 .control_in(&packet.to_bytes(), buf.as_mut_slice())
492 .await
493 .map_err(|e| RequestError::RequestFailed(e))?;
494
495 Ok(u16::from_le_bytes([buf[0], buf[1]]))
496 }
497
498 pub async fn get_curr_entity3(
508 &mut self,
509 control_selector: u16,
510 channel: u8,
511 entity: u8,
512 interface: u8,
513 ) -> Result<u32, RequestError> {
514 let packet = SetupPacket {
515 request_type: RequestType {
516 direction: Direction::In,
517 control_type: ControlType::Class,
518 recipient: Recipient::Interface,
519 },
520 request: codes::request_code::CUR,
521 value: (channel as u16) << 8 | control_selector,
522 index: (entity as u16) << 8 | interface as u16,
523 length: 4,
524 };
525
526 let mut buf = Aligned::<A4, _>([0; 4]);
527
528 self.control_channel
529 .control_in(&packet.to_bytes(), buf.as_mut_slice())
530 .await
531 .map_err(|e| RequestError::RequestFailed(e))?;
532
533 Ok(u32::from_le_bytes([buf[0], buf[1], buf[2], buf[3]]))
534 }
535
536 pub async fn get_range_entity1(
546 &mut self,
547 control_selector: u16,
548 channel: u8,
549 entity: u8,
550 interface: u8,
551 ) -> Result<Layout1ParameterBlock, RequestError> {
552 let packet = SetupPacket {
553 request_type: RequestType {
554 direction: Direction::In,
555 control_type: ControlType::Class,
556 recipient: Recipient::Interface,
557 },
558 request: codes::request_code::RANGE,
559 value: (channel as u16) << 8 | control_selector,
560 index: (entity as u16) << 8 | interface as u16,
561 length: size_of::<Layout1ParameterBlock>() as u16,
562 };
563
564 let mut buf = Aligned::<A4, _>([0; size_of::<Layout1ParameterBlock>()]);
565
566 self.control_channel
567 .control_in(&packet.to_bytes(), buf.as_mut_slice())
568 .await
569 .map_err(|e| RequestError::RequestFailed(e))?;
570
571 let layout = Layout1ParameterBlock::try_from_bytes(buf.as_slice()).ok_or(RequestError::InvalidResponse)?;
572
573 Ok(layout)
574 }
575
576 pub async fn get_range_entity2(
586 &mut self,
587 control_selector: u16,
588 channel: u8,
589 entity: u8,
590 interface: u8,
591 ) -> Result<Layout2ParameterBlock, RequestError> {
592 let packet = SetupPacket {
593 request_type: RequestType {
594 direction: Direction::In,
595 control_type: ControlType::Class,
596 recipient: Recipient::Interface,
597 },
598 request: codes::request_code::RANGE,
599 value: (channel as u16) << 8 | control_selector,
600 index: (entity as u16) << 8 | interface as u16,
601 length: size_of::<Layout2ParameterBlock>() as u16,
602 };
603
604 let mut buf = Aligned::<A4, _>([0; size_of::<Layout2ParameterBlock>()]);
605
606 self.control_channel
607 .control_in(&packet.to_bytes(), buf.as_mut_slice())
608 .await
609 .map_err(|e| RequestError::RequestFailed(e))?;
610
611 let layout = Layout2ParameterBlock::try_from_bytes(buf.as_slice()).ok_or(RequestError::InvalidResponse)?;
612
613 Ok(layout)
614 }
615
616 pub async fn get_range_entity3(
626 &mut self,
627 control_selector: u16,
628 channel: u8,
629 entity: u8,
630 interface: u8,
631 ) -> Result<Layout3ParameterBlock, RequestError> {
632 let packet = SetupPacket {
633 request_type: RequestType {
634 direction: Direction::In,
635 control_type: ControlType::Class,
636 recipient: Recipient::Interface,
637 },
638 request: codes::request_code::RANGE,
639 value: (channel as u16) << 8 | control_selector,
640 index: (entity as u16) << 8 | interface as u16,
641 length: size_of::<Layout3ParameterBlock>() as u16,
642 };
643
644 let mut buf = Aligned::<A4, _>([0; size_of::<Layout3ParameterBlock>()]);
645
646 self.control_channel
647 .control_in(&packet.to_bytes(), buf.as_mut_slice())
648 .await
649 .map_err(|e| RequestError::RequestFailed(e))?;
650
651 let layout = Layout3ParameterBlock::try_from_bytes(buf.as_slice()).ok_or(RequestError::InvalidResponse)?;
652
653 Ok(layout)
654 }
655}
656
657pub struct UacOut<'d, A: UsbHostAllocator<'d>> {
665 pub output_channel: A::Pipe<pipe::Isochronous, pipe::Out>,
667 pub feedback_channel: Option<A::Pipe<pipe::Isochronous, pipe::In>>,
669 speed: Speed,
670 samples_per_microframe: f32,
671 microframes_per_microsecond: f32,
672 send_start: Instant,
673 num_frames: u64,
674 last_feedback_time: Instant,
675 lock_delay: LockDelay,
676 num_channels: u8,
677 bytes_per_sample: usize,
678 max_bytes_per_packet: usize,
679 _phantom: core::marker::PhantomData<&'d ()>,
680}
681
682enum LockDelay {
683 Milliseconds(u16),
684 Samples(u16),
685}
686
687impl<'d, A: UsbHostAllocator<'d>> UacOut<'d, A> {
688 pub async fn output_stream(
693 &mut self,
694 is_connected: impl Fn() -> bool,
695 callback: impl FnMut(&mut [u8]),
696 ) -> Result<(), RequestError> {
697 let mut output_stream_future = pin!(self.output_stream_inner(callback));
698
699 poll_fn(|cx| {
700 if !is_connected() {
702 return Poll::Ready(Err(RequestError::DeviceDisconnected));
703 }
704
705 match output_stream_future.as_mut().poll(cx) {
706 Poll::Ready(result) => Poll::Ready(result),
707 Poll::Pending => {
708 cx.waker().wake_by_ref();
709 Poll::Pending
710 }
711 }
712 })
713 .await
714 }
715
716 async fn output_stream_inner(&mut self, mut callback: impl FnMut(&mut [u8])) -> Result<(), RequestError> {
717 self.update_sampling_freq().await?;
719
720 let mut output_buffer = Aligned::<A4, _>([0; 1024]);
721 let lock_delay = self.lock_delay_samples();
722
723 let data = &output_buffer.as_mut_slice()
725 [..(lock_delay as usize * self.bytes_per_sample).min(self.max_bytes_per_packet)]; self.output_channel
727 .request_out(data, true)
728 .await
729 .map_err(|e| RequestError::RequestFailed(e))?;
730
731 debug!(
732 "[UAC] Lock request sent, starting stream with sampling frequency: {} samples/microframe",
733 self.samples_per_microframe
734 );
735
736 let bytes_per_frame = self.bytes_per_sample * self.num_channels as usize;
738 let max_samples_per_packet = self.max_bytes_per_packet / bytes_per_frame;
739 trace!(
740 "[UAC] Max bytes per packet: {}; max samples per packet: {}",
741 self.max_bytes_per_packet, max_samples_per_packet
742 );
743 let mut sample_accumulator = 0.0;
744 loop {
745 if self.feedback_channel.is_some() && self.last_feedback_time.elapsed() > Duration::from_millis(1) {
747 self.update_sampling_freq().await?;
748 }
749 let mut microframes_elapsed = self.microframes_elapsed_since_last_frame();
750
751 if microframes_elapsed < 1.0 {
753 Timer::after(Duration::from_micros(
754 ((1.0 - microframes_elapsed) / self.microframes_per_microsecond) as u64,
755 ))
756 .await;
757 microframes_elapsed = self.microframes_elapsed_since_last_frame();
758 }
759 let num_microframes_elapsed = microframes_elapsed as u64;
760
761 sample_accumulator += self.samples_per_microframe * num_microframes_elapsed as f32;
763 let samples_to_send = sample_accumulator as usize;
764 sample_accumulator -= samples_to_send as f32;
765 let mut bytes_to_send = samples_to_send * bytes_per_frame;
766 while bytes_to_send > 0 {
769 let num_bytes = self.max_bytes_per_packet.min(bytes_to_send);
770 let data = &mut output_buffer.as_mut_slice()[..num_bytes];
772 data.fill(0);
773
774 callback(data);
775 bytes_to_send -= num_bytes;
776
777 let _len = self
779 .output_channel
780 .request_out(data, true)
781 .await
782 .map_err(|e| RequestError::RequestFailed(e))?;
783 }
784
785 self.num_frames += num_microframes_elapsed;
786 }
787 }
788
789 pub async fn update_sampling_freq(&mut self) -> Result<(), RequestError> {
793 if self.feedback_channel.is_none() {
794 return Ok(());
795 }
796
797 let mut feedback_buffer = Aligned::<A4, _>([0; 4]);
798 let _ = self
799 .feedback_channel
800 .as_mut()
801 .unwrap()
802 .request_in(feedback_buffer.as_mut_slice())
803 .await
804 .map_err(|e| RequestError::RequestFailed(e))?;
805 if let Some(samples_per_microframe) = parse_feedback(self.speed, &feedback_buffer.as_slice()) {
806 self.samples_per_microframe = samples_per_microframe;
807 trace!("[UAC] Samples per microframe: {}", self.samples_per_microframe);
808 }
809 self.last_feedback_time = Instant::now();
810 Ok(())
811 }
812
813 fn microframes_elapsed_since_last_frame(&self) -> f32 {
814 if self.send_start == Instant::from_ticks(0) {
815 1.0
817 } else {
818 (self.send_start.elapsed().as_micros() - (self.num_frames * self.microseconds_per_microframe())) as f32
819 * self.microframes_per_microsecond
820 }
821 }
822
823 fn microseconds_per_microframe(&self) -> u64 {
824 if self.speed == Speed::High { 125 } else { 1000 }
825 }
826
827 fn lock_delay_samples(&self) -> u16 {
828 match self.lock_delay {
829 LockDelay::Milliseconds(ms) => (ms as f32 * self.samples_per_frame()) as u16,
830 LockDelay::Samples(samples) => samples,
831 }
832 }
833
834 fn microframes_per_frame(&self) -> u16 {
835 if self.speed == Speed::High { 8 } else { 1 }
836 }
837
838 fn samples_per_frame(&self) -> f32 {
839 self.samples_per_microframe * self.microframes_per_frame() as f32
840 }
841}
842
843pub fn parse_feedback(speed: Speed, data: &[u8]) -> Option<f32> {
848 match speed {
849 Speed::Low => None, Speed::High => {
852 if data.len() < 4 {
853 return None;
854 }
855
856 let fractional_part = u16::from_le_bytes([data[0], data[1]]);
857 let integer_part = u16::from_le_bytes([data[2], data[3]]);
858 Some(integer_part as f32 + (fractional_part as f32 / 65536.0))
860 }
861
862 Speed::Full => {
863 if data.len() < 3 {
864 return None;
865 }
866
867 let raw = ((data[2] as u32) << 16) | ((data[1] as u32) << 8) | data[0] as u32;
870 let shifted = raw << 2;
871
872 let fractional_part = (shifted & 0xFFFF) as u16;
873 let integer_part = (shifted >> 16) as u16;
874 Some(integer_part as f32 + (fractional_part as f32 / 65536.0))
876 }
877 }
878}
879
880#[derive(Debug)]
886pub struct Layout1ParameterBlock {
887 pub ranges: Vec<Range1, MAX_RANGES>,
889}
890
891impl Layout1ParameterBlock {
892 pub fn try_from_bytes(bytes: &[u8]) -> Option<Self> {
895 if bytes.len() < 5 {
896 return None;
897 }
898 let num_ranges = u16::from_le_bytes([bytes[0], bytes[1]]);
899 if num_ranges > MAX_RANGES as u16 {
900 warn!(
901 "Number of ranges in Get Range response is greater than the maximum allowed: {}",
902 num_ranges
903 );
904 return None;
905 }
906 let mut ranges = Vec::new();
907 let mut bytes = &bytes[2..];
908 for _ in 0..num_ranges {
909 let range = Range1 {
910 min: bytes[0],
911 max: bytes[1],
912 step: bytes[2],
913 };
914 ranges.push(range).unwrap();
915 bytes = &bytes[3..];
916 }
917 Some(Self { ranges })
918 }
919}
920
921#[derive(Debug)]
923pub struct Layout2ParameterBlock {
924 pub ranges: Vec<Range2, MAX_RANGES>,
926}
927
928impl Layout2ParameterBlock {
929 pub fn try_from_bytes(bytes: &[u8]) -> Option<Self> {
932 if bytes.len() < 8 {
933 return None;
934 }
935 let num_ranges = u16::from_le_bytes([bytes[0], bytes[1]]);
936 if num_ranges > MAX_RANGES as u16 {
937 warn!(
938 "Number of ranges in Get Range response is greater than the maximum allowed: {}",
939 num_ranges
940 );
941 return None;
942 }
943 let mut ranges = Vec::new();
944 let mut bytes = &bytes[2..];
945 for _ in 0..num_ranges {
946 let range = Range2 {
947 min: u16::from_le_bytes([bytes[0], bytes[1]]),
948 max: u16::from_le_bytes([bytes[2], bytes[3]]),
949 step: u16::from_le_bytes([bytes[4], bytes[5]]),
950 };
951 ranges.push(range).unwrap();
952 bytes = &bytes[6..];
953 }
954 Some(Self { ranges })
955 }
956}
957
958#[derive(Debug)]
960pub struct Layout3ParameterBlock {
961 pub ranges: Vec<Range4, MAX_RANGES>,
963}
964
965impl Layout3ParameterBlock {
966 pub fn try_from_bytes(bytes: &[u8]) -> Option<Self> {
969 if bytes.len() < 14 {
970 return None;
971 }
972 let mut ranges = Vec::new();
973 let num_ranges = u16::from_le_bytes([bytes[0], bytes[1]]);
974 if num_ranges > MAX_RANGES as u16 {
975 warn!(
976 "Number of ranges in Get Range response is greater than the maximum allowed: {}",
977 num_ranges
978 );
979 return None;
980 }
981 let mut bytes = &bytes[2..];
982 for _ in 0..num_ranges {
983 let range = Range4 {
984 min: u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]),
985 max: u32::from_le_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]),
986 step: u32::from_le_bytes([bytes[8], bytes[9], bytes[10], bytes[11]]),
987 };
988 ranges.push(range).unwrap();
989 bytes = &bytes[12..];
990 }
991 Some(Self { ranges })
992 }
993}
994
995#[derive(Debug)]
997pub struct Range4 {
998 pub min: u32,
1000 pub max: u32,
1002 pub step: u32,
1004}
1005
1006#[derive(Debug)]
1008pub struct Range2 {
1009 pub min: u16,
1011 pub max: u16,
1013 pub step: u16,
1015}
1016
1017#[derive(Debug)]
1019pub struct Range1 {
1020 pub min: u8,
1022 pub max: u8,
1024 pub step: u8,
1026}