usb_device/
device.rs

1use crate::bus::{InterfaceNumber, PollResult, StringIndex, UsbBus, UsbBusAllocator};
2use crate::class::{ControlIn, ControlOut, UsbClass};
3use crate::control;
4use crate::control_pipe::ControlPipe;
5use crate::descriptor::{descriptor_type, lang_id::LangID, BosWriter, DescriptorWriter};
6pub use crate::device_builder::{StringDescriptors, UsbDeviceBuilder, UsbVidPid};
7use crate::endpoint::{EndpointAddress, EndpointType};
8use crate::{Result, UsbDirection};
9
10/// The global state of the USB device.
11///
12/// In general class traffic is only possible in the `Configured` state.
13#[repr(u8)]
14#[derive(PartialEq, Eq, Copy, Clone, Debug)]
15#[cfg_attr(feature = "defmt", derive(defmt::Format))]
16pub enum UsbDeviceState {
17    /// The USB device has just been created or reset.
18    Default,
19
20    /// The USB device has received an address from the host.
21    Addressed,
22
23    /// The USB device has been configured and is fully functional.
24    Configured,
25
26    /// The USB device has been suspended by the host or it has been unplugged from the USB bus.
27    Suspend,
28}
29
30// Maximum number of endpoints in one direction. Specified by the USB specification.
31const MAX_ENDPOINTS: usize = 16;
32
33/// Usb spec revision.
34#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
35#[repr(u16)]
36pub enum UsbRev {
37    /// USB 2.0 compliance
38    Usb200 = 0x200,
39    /// USB 2.1 compliance.
40    ///
41    /// Typically adds support for BOS requests.
42    Usb210 = 0x210,
43}
44
45/// A USB device consisting of one or more device classes.
46pub struct UsbDevice<'a, B: UsbBus> {
47    bus: &'a B,
48    config: Config<'a>,
49    control: ControlPipe<'a, B>,
50    device_state: UsbDeviceState,
51    remote_wakeup_enabled: bool,
52    self_powered: bool,
53    suspended_device_state: Option<UsbDeviceState>,
54    pending_address: u8,
55}
56
57pub(crate) struct Config<'a> {
58    pub device_class: u8,
59    pub device_sub_class: u8,
60    pub device_protocol: u8,
61    pub max_packet_size_0: u8,
62    pub vendor_id: u16,
63    pub product_id: u16,
64    pub usb_rev: UsbRev,
65    pub device_release: u16,
66    pub string_descriptors: heapless::Vec<StringDescriptors<'a>, 16>,
67    pub self_powered: bool,
68    pub supports_remote_wakeup: bool,
69    pub composite_with_iads: bool,
70    pub max_power: u8,
71}
72
73/// The bConfiguration value for the not configured state.
74pub const CONFIGURATION_NONE: u8 = 0;
75
76/// The bConfiguration value for the single configuration supported by this device.
77pub const CONFIGURATION_VALUE: u8 = 1;
78
79/// The default value for bAlternateSetting for all interfaces.
80pub const DEFAULT_ALTERNATE_SETTING: u8 = 0;
81
82type ClassList<'a, B> = [&'a mut dyn UsbClass<B>];
83
84impl<B: UsbBus> UsbDevice<'_, B> {
85    pub(crate) fn build<'a>(alloc: &'a UsbBusAllocator<B>, config: Config<'a>) -> UsbDevice<'a, B> {
86        let control_out = alloc
87            .alloc(
88                Some(0x00.into()),
89                EndpointType::Control,
90                config.max_packet_size_0 as u16,
91                0,
92            )
93            .expect("failed to alloc control endpoint");
94
95        let control_in = alloc
96            .alloc(
97                Some(0x80.into()),
98                EndpointType::Control,
99                config.max_packet_size_0 as u16,
100                0,
101            )
102            .expect("failed to alloc control endpoint");
103
104        let bus = alloc.freeze();
105
106        UsbDevice {
107            bus,
108            config,
109            control: ControlPipe::new(control_out, control_in),
110            device_state: UsbDeviceState::Default,
111            remote_wakeup_enabled: false,
112            self_powered: false,
113            suspended_device_state: None,
114            pending_address: 0,
115        }
116    }
117
118    /// Gets a reference to the [`UsbBus`] implementation used by this `UsbDevice`. You can use this
119    /// to call platform-specific methods on the `UsbBus`.
120    ///
121    /// While it is also possible to call the standard `UsbBus` trait methods through this
122    /// reference, this is not recommended as it can cause the device to misbehave.
123    pub fn bus(&self) -> &B {
124        self.bus
125    }
126
127    /// Gets the current state of the device.
128    ///
129    /// In general class traffic is only possible in the `Configured` state.
130    pub fn state(&self) -> UsbDeviceState {
131        self.device_state
132    }
133
134    /// Gets whether host remote wakeup has been enabled by the host.
135    pub fn remote_wakeup_enabled(&self) -> bool {
136        self.remote_wakeup_enabled
137    }
138
139    /// Gets whether the device is currently self powered.
140    pub fn self_powered(&self) -> bool {
141        self.self_powered
142    }
143
144    /// Sets whether the device is currently self powered.
145    pub fn set_self_powered(&mut self, is_self_powered: bool) {
146        self.self_powered = is_self_powered;
147    }
148
149    /// Simulates a disconnect from the USB bus, causing the host to reset and re-enumerate the
150    /// device.
151    ///
152    /// Mostly useful for development. Calling this at the start of your program ensures that the
153    /// host re-enumerates your device after a new program has been flashed.
154    pub fn force_reset(&mut self) -> Result<()> {
155        self.bus.force_reset()
156    }
157
158    /// Polls the [`UsbBus`] for new events and dispatches them to the provided classes. Returns
159    /// true if one of the classes may have data available for reading or be ready for writing,
160    /// false otherwise. This should be called periodically as often as possible for the best data
161    /// rate, or preferably from an interrupt handler. Must be called at least once every 10
162    /// milliseconds while connected to the USB host to be USB compliant.
163    ///
164    /// Note: The list of classes passed in must be the same classes in the same order for every
165    /// call while the device is configured, or the device may enumerate incorrectly or otherwise
166    /// misbehave. The easiest way to do this is to call the `poll` method in only one place in your
167    /// code, as follows:
168    ///
169    /// ``` ignore
170    /// usb_dev.poll(&mut [&mut class1, &mut class2]);
171    /// ```
172    ///
173    /// Strictly speaking the list of classes is allowed to change between polls if the device has
174    /// been reset, which is indicated by `state` being equal to [`UsbDeviceState::Default`].
175    pub fn poll(&mut self, classes: &mut ClassList<'_, B>) -> bool {
176        let pr = self.bus.poll();
177
178        if self.device_state == UsbDeviceState::Suspend {
179            match pr {
180                PollResult::Suspend | PollResult::None => {
181                    return false;
182                }
183                _ => {
184                    self.bus.resume();
185
186                    self.device_state = self
187                        .suspended_device_state
188                        .expect("Unknown state before suspend");
189                    self.suspended_device_state = None;
190                }
191            }
192        }
193
194        match pr {
195            PollResult::None => {}
196            PollResult::Reset => self.reset(classes),
197            PollResult::Data {
198                ep_out,
199                ep_in_complete,
200                ep_setup,
201            } => {
202                // Combine bit fields for quick tests
203                let mut eps = ep_out | ep_in_complete | ep_setup;
204
205                // Pending events for endpoint 0?
206                if (eps & 1) != 0 {
207                    usb_debug!(
208                        "EP0: setup={}, in_complete={}, out={}",
209                        ep_setup & 1,
210                        ep_in_complete & 1,
211                        ep_out & 1
212                    );
213
214                    let req = if (ep_setup & 1) != 0 {
215                        self.control.handle_setup()
216                    } else if (ep_out & 1) != 0 {
217                        match self.control.handle_out() {
218                            Ok(req) => req,
219                            Err(_err) => {
220                                // TODO: Propagate error out of `poll()`
221                                usb_debug!("Failed to handle EP0: {:?}", _err);
222                                None
223                            }
224                        }
225                    } else {
226                        None
227                    };
228
229                    match req {
230                        Some(req) if req.direction == UsbDirection::In => {
231                            if let Err(_err) = self.control_in(classes, req) {
232                                // TODO: Propagate error out of `poll()`
233                                usb_debug!("Failed to handle input control request: {:?}", _err);
234                            }
235                        }
236                        Some(req) if req.direction == UsbDirection::Out => {
237                            if let Err(_err) = self.control_out(classes, req) {
238                                // TODO: Propagate error out of `poll()`
239                                usb_debug!("Failed to handle output control request: {:?}", _err);
240                            }
241                        }
242
243                        None if ((ep_in_complete & 1) != 0) => {
244                            // We only handle EP0-IN completion if there's no other request being
245                            // processed. EP0-IN tokens may be issued due to completed STATUS
246                            // phases of the control transfer. If we just got a SETUP packet or
247                            // an OUT token, we can safely ignore the IN-COMPLETE indication and
248                            // continue with the next transfer.
249                            let completed = match self.control.handle_in_complete() {
250                                Ok(completed) => completed,
251                                Err(_err) => {
252                                    // TODO: Propagate this out of `poll()`
253                                    usb_debug!(
254                                        "Failed to process control-input complete: {:?}",
255                                        _err
256                                    );
257                                    false
258                                }
259                            };
260
261                            if !B::QUIRK_SET_ADDRESS_BEFORE_STATUS
262                                && completed
263                                && self.pending_address != 0
264                            {
265                                self.bus.set_device_address(self.pending_address);
266                                self.pending_address = 0;
267
268                                self.device_state = UsbDeviceState::Addressed;
269                            }
270                        }
271
272                        _ => (),
273                    };
274
275                    eps &= !1;
276                }
277
278                // Pending events for other endpoints?
279                if eps != 0 {
280                    let mut bit = 2u16;
281
282                    for i in 1..MAX_ENDPOINTS {
283                        if (ep_setup & bit) != 0 {
284                            for cls in classes.iter_mut() {
285                                usb_trace!("Handling EP{}-SETUP", i);
286                                cls.endpoint_setup(EndpointAddress::from_parts(
287                                    i,
288                                    UsbDirection::Out,
289                                ));
290                            }
291                        } else if (ep_out & bit) != 0 {
292                            usb_trace!("Handling EP{}-OUT", i);
293                            for cls in classes.iter_mut() {
294                                cls.endpoint_out(EndpointAddress::from_parts(i, UsbDirection::Out));
295                            }
296                        }
297
298                        if (ep_in_complete & bit) != 0 {
299                            usb_trace!("Handling EP{}-IN", i);
300                            for cls in classes.iter_mut() {
301                                cls.endpoint_in_complete(EndpointAddress::from_parts(
302                                    i,
303                                    UsbDirection::In,
304                                ));
305                            }
306                        }
307
308                        eps &= !bit;
309
310                        if eps == 0 {
311                            // No more pending events for higher endpoints
312                            break;
313                        }
314
315                        bit <<= 1;
316                    }
317                }
318
319                for cls in classes.iter_mut() {
320                    cls.poll();
321                }
322
323                return true;
324            }
325            PollResult::Resume => {}
326            PollResult::Suspend => {
327                usb_debug!("Suspending bus");
328                self.bus.suspend();
329                self.suspended_device_state = Some(self.device_state);
330                self.device_state = UsbDeviceState::Suspend;
331            }
332        }
333
334        false
335    }
336
337    fn control_in(&mut self, classes: &mut ClassList<'_, B>, req: control::Request) -> Result<()> {
338        use crate::control::{Recipient, Request};
339
340        for cls in classes.iter_mut() {
341            cls.control_in(ControlIn::new(&mut self.control, &req));
342
343            if !self.control.waiting_for_response() {
344                return Ok(());
345            }
346        }
347
348        if req.request_type == control::RequestType::Standard {
349            let xfer = ControlIn::new(&mut self.control, &req);
350
351            match (req.recipient, req.request) {
352                (Recipient::Device, Request::GET_STATUS) => {
353                    usb_trace!("Processing Device::GetStatus");
354                    let status: u16 = if self.self_powered { 0x0001 } else { 0x0000 }
355                        | if self.remote_wakeup_enabled {
356                            0x0002
357                        } else {
358                            0x0000
359                        };
360
361                    xfer.accept_with(&status.to_le_bytes())?;
362                }
363
364                (Recipient::Interface, Request::GET_STATUS) => {
365                    usb_trace!("Processing Interface::GetStatus");
366                    let status: u16 = 0x0000;
367
368                    xfer.accept_with(&status.to_le_bytes())?;
369                }
370
371                (Recipient::Endpoint, Request::GET_STATUS) => {
372                    usb_trace!("Processing EP::GetStatus");
373                    let ep_addr = ((req.index as u8) & 0x8f).into();
374
375                    let status: u16 = if self.bus.is_stalled(ep_addr) {
376                        0x0001
377                    } else {
378                        0x0000
379                    };
380
381                    xfer.accept_with(&status.to_le_bytes())?;
382                }
383
384                (Recipient::Device, Request::GET_DESCRIPTOR) => {
385                    usb_trace!("Processing Device::GetDescriptor");
386                    UsbDevice::get_descriptor(&self.config, classes, xfer)?;
387                }
388
389                (Recipient::Device, Request::GET_CONFIGURATION) => {
390                    usb_trace!("Processing Device::GetConfiguration");
391                    let config = match self.device_state {
392                        UsbDeviceState::Configured => CONFIGURATION_VALUE,
393                        _ => CONFIGURATION_NONE,
394                    };
395
396                    xfer.accept_with(&config.to_le_bytes())?;
397                }
398
399                (Recipient::Interface, Request::GET_INTERFACE) => {
400                    usb_trace!("Processing Interface::GetInterface");
401                    // Reject interface numbers bigger than 255
402                    if req.index > core::u8::MAX.into() {
403                        return xfer.reject();
404                    }
405
406                    // Ask class implementations, whether they know the alternate setting
407                    // of the interface in question
408                    for cls in classes {
409                        if let Some(setting) = cls.get_alt_setting(InterfaceNumber(req.index as u8))
410                        {
411                            return xfer.accept_with(&setting.to_le_bytes());
412                        }
413                    }
414
415                    // If no class returned an alternate setting, return the default value
416                    xfer.accept_with(&DEFAULT_ALTERNATE_SETTING.to_le_bytes())?;
417                }
418
419                _ => {}
420            };
421        }
422
423        if self.control.waiting_for_response() {
424            usb_debug!("Rejecting control transfer because we were waiting for a response");
425            self.control.reject()?;
426        }
427
428        Ok(())
429    }
430
431    fn control_out(&mut self, classes: &mut ClassList<'_, B>, req: control::Request) -> Result<()> {
432        use crate::control::{Recipient, Request};
433
434        for cls in classes.iter_mut() {
435            cls.control_out(ControlOut::new(&mut self.control, &req));
436
437            if !self.control.waiting_for_response() {
438                return Ok(());
439            }
440        }
441
442        if req.request_type == control::RequestType::Standard {
443            let xfer = ControlOut::new(&mut self.control, &req);
444
445            const CONFIGURATION_NONE_U16: u16 = CONFIGURATION_NONE as u16;
446            const CONFIGURATION_VALUE_U16: u16 = CONFIGURATION_VALUE as u16;
447            const DEFAULT_ALTERNATE_SETTING_U16: u16 = DEFAULT_ALTERNATE_SETTING as u16;
448
449            match (req.recipient, req.request, req.value) {
450                (
451                    Recipient::Device,
452                    Request::CLEAR_FEATURE,
453                    Request::FEATURE_DEVICE_REMOTE_WAKEUP,
454                ) => {
455                    usb_debug!("Remote wakeup disabled");
456                    self.remote_wakeup_enabled = false;
457                    xfer.accept()?;
458                }
459
460                (Recipient::Endpoint, Request::CLEAR_FEATURE, Request::FEATURE_ENDPOINT_HALT) => {
461                    usb_debug!("EP{} halt removed", req.index & 0x8f);
462                    self.bus
463                        .set_stalled(((req.index as u8) & 0x8f).into(), false);
464                    xfer.accept()?;
465                }
466
467                (
468                    Recipient::Device,
469                    Request::SET_FEATURE,
470                    Request::FEATURE_DEVICE_REMOTE_WAKEUP,
471                ) => {
472                    usb_debug!("Remote wakeup enabled");
473                    self.remote_wakeup_enabled = true;
474                    xfer.accept()?;
475                }
476
477                (Recipient::Endpoint, Request::SET_FEATURE, Request::FEATURE_ENDPOINT_HALT) => {
478                    usb_debug!("EP{} halted", req.index & 0x8f);
479                    self.bus
480                        .set_stalled(((req.index as u8) & 0x8f).into(), true);
481                    xfer.accept()?;
482                }
483
484                (Recipient::Device, Request::SET_ADDRESS, 1..=127) => {
485                    usb_debug!("Setting device address to {}", req.value);
486                    if B::QUIRK_SET_ADDRESS_BEFORE_STATUS {
487                        self.bus.set_device_address(req.value as u8);
488                        self.device_state = UsbDeviceState::Addressed;
489                    } else {
490                        self.pending_address = req.value as u8;
491                    }
492                    xfer.accept()?;
493                }
494
495                (Recipient::Device, Request::SET_CONFIGURATION, CONFIGURATION_VALUE_U16) => {
496                    usb_debug!("Device configured");
497                    self.device_state = UsbDeviceState::Configured;
498                    xfer.accept()?;
499                }
500
501                (Recipient::Device, Request::SET_CONFIGURATION, CONFIGURATION_NONE_U16) => {
502                    usb_debug!("Device deconfigured");
503                    match self.device_state {
504                        UsbDeviceState::Default => {
505                            xfer.accept()?;
506                        }
507                        _ => {
508                            self.device_state = UsbDeviceState::Addressed;
509                            xfer.accept()?;
510                        }
511                    }
512                }
513
514                (Recipient::Interface, Request::SET_INTERFACE, alt_setting) => {
515                    // Reject interface numbers and alt settings bigger than 255
516                    if req.index > core::u8::MAX.into() || alt_setting > core::u8::MAX.into() {
517                        xfer.reject()?;
518                        return Ok(());
519                    }
520
521                    // Ask class implementations, whether they accept the alternate interface setting.
522                    for cls in classes {
523                        if cls.set_alt_setting(InterfaceNumber(req.index as u8), alt_setting as u8)
524                        {
525                            xfer.accept()?;
526                            return Ok(());
527                        }
528                    }
529
530                    // Default behaviour, if no class implementation accepted the alternate setting.
531                    if alt_setting == DEFAULT_ALTERNATE_SETTING_U16 {
532                        usb_debug!("Accepting unused alternate settings");
533                        xfer.accept()?;
534                    } else {
535                        usb_debug!("Rejecting unused alternate settings");
536                        xfer.reject()?;
537                    }
538                }
539
540                _ => {
541                    xfer.reject()?;
542                    return Ok(());
543                }
544            }
545        }
546
547        if self.control.waiting_for_response() {
548            usb_debug!("Rejecting control transfer due to waiting response");
549            self.control.reject()?;
550        }
551
552        Ok(())
553    }
554
555    fn get_descriptor(
556        config: &Config,
557        classes: &mut ClassList<'_, B>,
558        xfer: ControlIn<B>,
559    ) -> Result<()> {
560        let req = *xfer.request();
561
562        let (dtype, index) = req.descriptor_type_index();
563
564        fn accept_writer<B: UsbBus>(
565            xfer: ControlIn<B>,
566            f: impl FnOnce(&mut DescriptorWriter) -> Result<()>,
567        ) -> Result<()> {
568            xfer.accept(|buf| {
569                let mut writer = DescriptorWriter::new(buf);
570                f(&mut writer)?;
571                Ok(writer.position())
572            })?;
573
574            Ok(())
575        }
576
577        match dtype {
578            descriptor_type::BOS if config.usb_rev > UsbRev::Usb200 => accept_writer(xfer, |w| {
579                let mut bw = BosWriter::new(w);
580                bw.bos()?;
581
582                for cls in classes {
583                    cls.get_bos_descriptors(&mut bw)?;
584                }
585
586                bw.end_bos();
587
588                Ok(())
589            })?,
590
591            descriptor_type::DEVICE => accept_writer(xfer, |w| w.device(config))?,
592
593            descriptor_type::CONFIGURATION => accept_writer(xfer, |w| {
594                w.configuration(config)?;
595
596                for cls in classes {
597                    cls.get_configuration_descriptors(w)?;
598                    w.end_class();
599                }
600
601                w.end_configuration();
602
603                Ok(())
604            })?,
605
606            descriptor_type::STRING => match index {
607                // first STRING Request
608                0 => {
609                    let mut lang_id_bytes = [0u8; 32];
610                    for (lang, buf) in config
611                        .string_descriptors
612                        .iter()
613                        .zip(lang_id_bytes.chunks_exact_mut(2))
614                    {
615                        buf.copy_from_slice(&u16::from(lang.id).to_le_bytes());
616                    }
617                    accept_writer(xfer, |w| {
618                        w.write(
619                            descriptor_type::STRING,
620                            &lang_id_bytes[..config.string_descriptors.len() * 2],
621                        )
622                    })?;
623                }
624
625                // rest STRING Requests
626                _ => {
627                    let lang_id = LangID::from(req.index);
628
629                    let string = match index {
630                        // Manufacturer, product, and serial are handled directly here.
631                        1..=3 => {
632                            let Some(lang) = config
633                                .string_descriptors
634                                .iter()
635                                .find(|lang| lang.id == lang_id)
636                            else {
637                                xfer.reject()?;
638                                return Ok(());
639                            };
640
641                            match index {
642                                1 => lang.manufacturer,
643                                2 => lang.product,
644                                3 => lang.serial,
645                                _ => unreachable!(),
646                            }
647                        }
648                        _ => {
649                            let index = StringIndex::new(index);
650                            classes
651                                .iter()
652                                .find_map(|cls| cls.get_string(index, lang_id))
653                        }
654                    };
655
656                    if let Some(string_descriptor) = string {
657                        accept_writer(xfer, |w| w.string(string_descriptor))?;
658                    } else {
659                        xfer.reject()?;
660                    }
661                }
662            },
663
664            _ => {
665                xfer.reject()?;
666            }
667        };
668
669        Ok(())
670    }
671
672    fn reset(&mut self, classes: &mut ClassList<'_, B>) {
673        self.bus.reset();
674
675        self.device_state = UsbDeviceState::Default;
676        self.suspended_device_state = None; // We may reset during Suspend
677        self.remote_wakeup_enabled = false;
678        self.pending_address = 0;
679
680        self.control.reset();
681
682        for cls in classes {
683            cls.reset();
684        }
685    }
686}