Skip to main content

usbd_storage/
subclass.rs

1//! USB Mass Storage subclasses
2
3#[cfg(all(feature = "bbb", feature = "scsi"))]
4use crate::subclass::scsi::{Scsi, ScsiCommand};
5#[cfg(all(feature = "bbb", feature = "ufi"))]
6use crate::subclass::ufi::{Ufi, UfiCommand};
7#[cfg(all(any(feature = "scsi", feature = "ufi"), feature = "bbb"))]
8use {
9    crate::transport::bbb::{BulkOnly, BulkOnlyError},
10    crate::transport::{CommandStatus, TransportError},
11    core::borrow::BorrowMut,
12    usb_device::bus::UsbBus,
13};
14
15#[cfg(feature = "scsi")]
16pub mod scsi;
17#[cfg(feature = "ufi")]
18pub mod ufi;
19
20/// The subclass' command and a LUN it is addressed to
21pub struct Command<'a, Kind, Class> {
22    #[allow(dead_code)]
23    class: &'a mut Class,
24    pub kind: Kind,
25    pub lun: u8,
26}
27
28/// [UFI] over [Bulk Only Transport] command
29///
30/// [UFI]: crate::subclass::ufi::Ufi
31/// [Bulk Only Transport]: crate::transport::bbb::BulkOnly
32#[cfg(all(feature = "bbb", feature = "ufi"))]
33impl<'a, 'alloc, Bus: UsbBus + 'alloc, Buf: BorrowMut<[u8]>>
34    Command<'a, UfiCommand, Ufi<BulkOnly<'alloc, Bus, Buf>>>
35{
36    /// [crate::transport::bbb::BulkOnly::read_data]
37    pub fn read_data(&mut self, dst: &mut [u8]) -> Result<usize, TransportError<BulkOnlyError>> {
38        self.class.transport.read_data(dst)
39    }
40
41    /// [crate::transport::bbb::BulkOnly::write_data]
42    pub fn write_data(&mut self, src: &[u8]) -> Result<usize, TransportError<BulkOnlyError>> {
43        self.class.transport.write_data(src)
44    }
45
46    /// [crate::transport::bbb::BulkOnly::try_write_data_all]
47    pub fn try_write_data_all(&mut self, src: &[u8]) -> Result<(), TransportError<BulkOnlyError>> {
48        self.class.transport.try_write_data_all(src)
49    }
50
51    /// Mark command as successful (0x00)
52    ///
53    /// # Arguments
54    /// * num_bytes_processed - the actual number of bytes the device has actually processed.
55    ///   The `dCBWDataTransferLength - num_bytes_processed` is what is going to be sent
56    ///   in the CSW
57    pub fn pass(self, num_bytes_processed: u32) {
58        self.class
59            .transport
60            .set_status(CommandStatus::Passed, num_bytes_processed);
61    }
62
63    /// Mark command as failed (0x01)
64    ///
65    /// # Arguments
66    /// * num_bytes_processed - the actual number of bytes the device has actually processed.
67    ///   The `dCBWDataTransferLength - num_bytes_processed` is what is going to be sent
68    ///   in the CSW
69    pub fn fail(self, num_bytes_processed: u32) {
70        self.class
71            .transport
72            .set_status(CommandStatus::Failed, num_bytes_processed);
73    }
74
75    /// Mark command as phase-failed (0x02)
76    pub fn fail_phase(self) {
77        self.class
78            .transport
79            .set_status(CommandStatus::PhaseError, 0);
80    }
81}
82
83/// [SCSI] over [Bulk Only Transport] command
84///
85/// [SCSI]: crate::subclass::scsi::Scsi
86/// [Bulk Only Transport]: crate::transport::bbb::BulkOnly
87#[cfg(all(feature = "bbb", feature = "scsi"))]
88impl<'a, 'alloc, Bus: UsbBus + 'alloc, Buf: BorrowMut<[u8]>>
89    Command<'a, ScsiCommand, Scsi<BulkOnly<'alloc, Bus, Buf>>>
90{
91    /// [crate::transport::bbb::BulkOnly::read_data]
92    pub fn read_data(&mut self, dst: &mut [u8]) -> Result<usize, TransportError<BulkOnlyError>> {
93        self.class.transport.read_data(dst)
94    }
95
96    /// [crate::transport::bbb::BulkOnly::write_data]
97    pub fn write_data(&mut self, src: &[u8]) -> Result<usize, TransportError<BulkOnlyError>> {
98        self.class.transport.write_data(src)
99    }
100
101    /// [crate::transport::bbb::BulkOnly::try_write_data_all]
102    pub fn try_write_data_all(&mut self, src: &[u8]) -> Result<(), TransportError<BulkOnlyError>> {
103        self.class.transport.try_write_data_all(src)
104    }
105
106    /// Mark command as successful (0x00)
107    ///
108    /// # Arguments
109    /// * num_bytes_processed - the actual number of bytes the device has actually processed.
110    ///   The `dCBWDataTransferLength - num_bytes_processed` is what is going to be sent
111    ///   in the CSW
112    pub fn pass(self, num_bytes_processed: u32) {
113        self.class
114            .transport
115            .set_status(CommandStatus::Passed, num_bytes_processed);
116    }
117
118    /// Mark command as failed (0x01)
119    ///
120    /// # Arguments
121    /// * num_bytes_processed - the actual number of bytes the device has actually processed.
122    ///   The `dCBWDataTransferLength - num_bytes_processed` is what is going to be sent
123    ///   in the CSW
124    pub fn fail(self, num_bytes_processed: u32) {
125        self.class
126            .transport
127            .set_status(CommandStatus::Failed, num_bytes_processed);
128    }
129
130    /// Mark command as phase-failed (0x02)
131    pub fn fail_phase(self) {
132        self.class
133            .transport
134            .set_status(CommandStatus::PhaseError, 0);
135    }
136}