### Send Generic SCSI Command and Get Response Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Sends a generic SCSI command to the device and waits for a reply. Ensures the received data size matches the expected reply structure. Handles transport-level errors. ```rust pub async fn command_response( &mut self, cmd: C, ) -> Result> { let mut r = R::default(); let rc = self .transport .command( bytemuck::bytes_of(&cmd), DataPhase::In(bytemuck::bytes_of_mut(&mut r)), ) .await; match rc { Err(e) => Err(self.try_upgrade_error(e).await), Ok(sz) => { if sz < core::mem::size_of::() { Err(Error::ProtocolError) } else { Ok(r) } } } ``` -------------------------------- ### Create a new ScsiDevice Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.ScsiDevice.html Instantiates a new ScsiDevice with the provided SCSI transport. This is the entry point for interacting with a SCSI device. ```rust pub fn new(transport: T) -> Self> ``` -------------------------------- ### ScsiBlockDevice::new Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_block_device/struct.ScsiBlockDevice.html Constructs a new ScsiBlockDevice instance from a generic ScsiDevice. ```APIDOC ## `new` ### Description Construct a new block device from a generic SCSI device ### Signature ```rust pub fn new(scsi: ScsiDevice) -> Self ``` ### Parameters * `scsi`: `ScsiDevice` - The underlying SCSI device. ``` -------------------------------- ### Test Unit Ready Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Checks if the SCSI device is ready to accept commands. This is useful for devices that may take time to initialize, like hard drives spinning up. ```APIDOC ## test_unit_ready ### Description Checks if the SCSI device is ready to accept commands. ### Method `pub async fn test_unit_ready(&mut self) -> Result<(), Error>` ### Parameters None ### Response - `Ok(())` on success. - `Err(Error)` on failure. ``` -------------------------------- ### Calculate Device Size Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/async_block_device/struct.DeviceInfo.html Demonstrates how to calculate the total size of a device in bytes using the blocks and block_size fields from DeviceInfo. ```rust let device_size_in_bytes = device_info.blocks * device_info.block_size as u64; ``` -------------------------------- ### Test unit ready Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.ScsiDevice.html Checks if the SCSI device is ready to accept commands. This is useful for devices that may take time to initialize, such as hard drives spinning up. ```rust pub async fn test_unit_ready(&mut self) -> Result<(), Error>> ``` -------------------------------- ### ScsiBlockDevice::new Constructor Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_block_device/struct.ScsiBlockDevice.html Constructs a new ScsiBlockDevice instance from an existing ScsiDevice. This is the primary way to create a ScsiBlockDevice. ```rust pub fn new(scsi: ScsiDevice) -> Self ``` -------------------------------- ### ScsiBlockDevice Constructor Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_block_device.rs.html Provides a constructor for ScsiBlockDevice, taking an existing ScsiDevice as input. ```rust impl ScsiBlockDevice { /// Construct a new block device from a generic SCSI device pub fn new(scsi: ScsiDevice) -> Self { Self { scsi } } // ... other methods ``` -------------------------------- ### Default DeviceInfo Implementation Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/async_block_device/struct.DeviceInfo.html Provides a default value for DeviceInfo, useful for initialization when specific values are not yet known. ```rust fn default() -> DeviceInfo ``` -------------------------------- ### ScsiDevice::test_unit_ready Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.ScsiDevice.html Checks if the SCSI device is ready for operation. This is useful for devices that may take time to initialize, like hard drives spinning up. ```APIDOC ## ScsiDevice::test_unit_ready ### Description Is the device “ready”? For instance, hard drives might take a while to spin up to operating speed. ### Signature ```rust pub async fn test_unit_ready(&mut self) -> Result<(), Error> ``` ``` -------------------------------- ### ScsiDevice::new Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.ScsiDevice.html Creates a new ScsiDevice instance from the given transport. ```APIDOC ## ScsiDevice::new ### Description Create a new device, from the given transport. ### Signature ```rust pub fn new(transport: T) -> Self ``` ``` -------------------------------- ### CloneToUninit Trait Implementation (Nightly) Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.InquiryData.html A nightly-only experimental API for cloning InquiryData to uninitialized memory. ```rust unsafe fn clone_to_uninit(&self, dest: *mut u8) ``` -------------------------------- ### PartialEq Implementation for DeviceInfo Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/async_block_device/struct.DeviceInfo.html Enables comparison of two DeviceInfo instances for equality. This is used by the `==` operator. ```rust fn eq(&self, other: &DeviceInfo) -> bool ``` -------------------------------- ### AsyncBlockDevice: Device Info Implementation Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_block_device.rs.html Implements the device_info method for ScsiBlockDevice, retrieving capacity and block size using READ CAPACITY (10) and falling back to READ CAPACITY (16) if necessary. ```rust impl AsyncBlockDevice for ScsiBlockDevice { type E = Error; async fn device_info(&mut self) -> Result { let (blocks, block_size) = { let capacity10 = self.scsi.read_capacity_10().await?; if capacity10.0 != 0xFFFF_FFFF { (capacity10.0 as u64, capacity10.1) } else { self.scsi.read_capacity_16().await? } }; Ok(DeviceInfo { blocks, block_size }) } // ... other methods ``` -------------------------------- ### ScsiBlockDevice::query_commands Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_block_device/struct.ScsiBlockDevice.html Attempts to query supported SCSI commands on the device. Note that this command is rarely supported and often returns an error. ```rust pub async fn query_commands(&mut self) -> Result<(), Error> ``` -------------------------------- ### DeviceInfo Struct Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/async_block_device.rs.html Represents device size and granularity information. The total size is calculated as blocks * block_size. ```rust use core::future::Future; /// Device size and granularity information /// /// The total size of the device in bytes is `blocks * block_size`. #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "std", derive(Debug))] #[derive(Copy, Clone, Default, PartialEq, Eq)] pub struct DeviceInfo { /// The total number of sectors (readable/writable blocks) on the device pub blocks: u64, /// The size of each block pub block_size: u32, } ``` -------------------------------- ### ScsiBlockDevice::query_commands Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_block_device/struct.ScsiBlockDevice.html Queries the supported SCSI commands on the device. Note: This command often fails with ScsiError::InvalidCommandOperationCode. ```APIDOC ## `query_commands` ### Description For testing: query supported SCSI commands on this device. Unfortunately, “Report Supported Operation Codes”, which this relies on, is itself rarely a supported SCSI command: I haven’t found a device yet where this call works. Instead it always returns `ScsiError::InvalidCommandOperationCode`. ### Signature ```rust pub async fn query_commands(&mut self) -> Result<(), Error> ``` ### Returns * `Result<(), Error>` - Ok if successful, or an error if the command is not supported or fails. ``` -------------------------------- ### AsyncBlockDevice::device_info Implementation Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_block_device/struct.ScsiBlockDevice.html Implements the device_info method for ScsiBlockDevice, returning the capacity and block size of the device. ```rust async fn device_info(&mut self) -> Result ``` -------------------------------- ### ScsiDevice::write_16 Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.ScsiDevice.html Writes data to the device using the 64-bit LBA version. Not universally supported, but should be available on devices larger than 2TB. ```APIDOC ## ScsiDevice::write_16 ### Description Write sector(s), 64-bit LBA version. Not universally supported (but should be supported on all devices where it’s needed, i.e. devices >2TB). ### Signature ```rust pub async fn write_16( &mut self, start_block: u64, count: u32, buf: &[u8], ) -> Result> ``` ``` -------------------------------- ### Test Unit Ready Command Structure Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Defines the structure for the Test Unit Ready SCSI command. This command checks if the logical unit is ready to accept commands. ```rust struct TestUnitReady { operation_code: u8, reserved: [u8; 4], control: u8, } impl TestUnitReady { fn new() -> Self { assert!(core::mem::size_of::() == 6); Self { operation_code: 0x00, reserved: [0u8; 4], control: 0, } } } ``` -------------------------------- ### SCSI Write 10 Command Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Implements the SCSI WRITE (10) command for writing data to disk sectors. Supports 32-bit LBA, but is limited to the first 2TB on large devices. Requires a transport layer that supports command execution and data output. ```rust pub async fn write_10( &mut self, start_block: u32, count: u16, buf: &[u8], ) -> Result> { let cmd = Write10::new(start_block, count); let rc = self .transport .command(bytemuck::bytes_of(&cmd), DataPhase::Out(buf)) .await; if let Err(e) = rc { return Err(self.try_upgrade_error(e).await); } rc } ``` -------------------------------- ### ScsiDevice::read_16 Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.ScsiDevice.html Reads data from the device using the 64-bit LBA version. Not universally supported, but should be available on devices larger than 2TB. ```APIDOC ## ScsiDevice::read_16 ### Description Read sector(s), 64-bit LBA version. Not universally supported (but should be supported on all devices where it’s needed, i.e. devices >2TB). ### Signature ```rust pub async fn read_16( &mut self, start_block: u64, count: u32, buf: &mut [u8], ) -> Result> ``` ``` -------------------------------- ### CloneToUninit Trait Implementation (Nightly) Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.BlockLimitsPage.html A nightly-only experimental API that implements CloneToUninit for types T that are Clone, allowing cloning to uninitialized memory. ```rust impl CloneToUninit for T where T: Clone, ``` ```rust unsafe fn clone_to_uninit(&self, dest: *mut u8) ``` -------------------------------- ### Create a new Inquiry command Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Constructs a new SCSI Inquiry command. It takes an optional page code and allocation length, setting the operation code and control byte. ```rust impl Inquiry { fn new(evpd: Option, len: u16) -> Self { assert!(core::mem::size_of::() == 6); Self { operation_code: 0x12, evpd: evpd.is_some() as u8, page_code: evpd.unwrap_or_default(), allocation_length_be: len.to_be_bytes(), control: 0, } } } ``` -------------------------------- ### SCSI Write 16 Command Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Implements the SCSI WRITE (16) command for writing data to disk sectors. Supports 64-bit LBA, making it suitable for devices larger than 2TB. Requires a transport layer capable of executing commands and handling data output. ```rust pub async fn write_16( &mut self, start_block: u64, count: u32, buf: &[u8], ) -> Result> { let cmd = Write16::new(start_block, count); let rc = self .transport .command(bytemuck::bytes_of(&cmd), DataPhase::Out(buf)) .await; if let Err(e) = rc { return Err(self.try_upgrade_error(e).await); } rc } ``` -------------------------------- ### Clone Implementation for DeviceInfo Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/async_block_device/struct.DeviceInfo.html Allows creating a duplicate of a DeviceInfo value. This is useful for passing device information around without modifying the original. ```rust fn clone(&self) -> DeviceInfo ``` -------------------------------- ### NoUninit Implementation for Pod Types Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.BlockLimitsPage.html Implements the NoUninit trait for types T that are Pod, signifying that these types do not have uninitialized states. ```rust impl NoUninit for T where T: Pod, ``` -------------------------------- ### Crate Configuration and Module Declarations Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/lib.rs.html This snippet shows the crate-level configuration, including conditional compilation for `no_std` environments and feature flags. It also declares the main modules of the library. ```rust #![cfg_attr(not(feature = "std"), no_std)] #![doc = include_str!("../README.md")] #![warn(missing_docs)] #![warn(rustdoc::missing_crate_level_docs)] #![cfg_attr(docsrs, feature(doc_cfg))] mod debug; /// A generic SCSI device pub mod scsi_device; pub use scsi_device::{PeripheralType, ScsiDevice}; /// An abstract communication channel with a SCSI device /// /// Usually, these days, not actual SCSI hardware, but instead SCSI /// tunnelled over something else (USB, ATAPI). pub mod scsi_transport; pub use scsi_transport::{Error, ScsiTransport}; /// A generic asynchronous block device with a "read/write blocks" interface pub mod async_block_device; pub use async_block_device::{AsyncBlockDevice, DeviceInfo}; /// Implementing AsyncBlockDevice in terms of ScsiDevice pub mod scsi_block_device; pub use scsi_block_device::ScsiBlockDevice; ``` -------------------------------- ### StructuralPartialEq Implementation for BlockLimitsPage Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.BlockLimitsPage.html Provides structural equality comparison for BlockLimitsPage, useful in scenarios requiring deep comparison of struct fields. ```rust impl StructuralPartialEq for BlockLimitsPage ``` -------------------------------- ### ScsiDevice::write_10 Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.ScsiDevice.html Writes data to the device using the 32-bit LBA version. Supported by all disk devices, but limited to the first 2TB on large devices. ```APIDOC ## ScsiDevice::write_10 ### Description Write sector(s), 32-bit LBA version. All disk devices are required to support this, but on large devices it is only capable of writing within the first 2TB. ### Signature ```rust pub async fn write_10( &mut self, start_block: u32, count: u16, buf: &[u8], ) -> Result> ``` ``` -------------------------------- ### From and Into Trait Implementations Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.InquiryData.html Facilitates conversions to and from InquiryData. ```rust fn from(t: T) -> T ``` ```rust fn into(self) -> U ``` -------------------------------- ### PartialEq Implementation for BlockLimitsPage Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.BlockLimitsPage.html Enables comparison for equality between two BlockLimitsPage instances using the `==` operator and inequality using `!=`. ```rust fn eq(&self, other: &BlockLimitsPage) -> bool ``` ```rust fn ne(&self, other: &Rhs) -> bool ``` -------------------------------- ### Write sectors (64-bit LBA) Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.ScsiDevice.html Writes a specified number of sectors to the device using the 64-bit LBA version. This is required for devices larger than 2TB but is not universally supported. ```rust pub async fn write_16( &mut self, start_block: u64, count: u32, buf: &[u8], ) -> Result>> ``` -------------------------------- ### Borrow and BorrowMut Implementations Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.InquiryData.html Enables borrowing and mutable borrowing of InquiryData instances. ```rust fn borrow(&self) -> &T ``` ```rust fn borrow_mut(&mut self) -> &mut T ``` -------------------------------- ### Write sectors (32-bit LBA) Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.ScsiDevice.html Writes a specified number of sectors to the device using the 32-bit LBA version. All disk devices must support this, but it's limited to the first 2TB on large devices. ```rust pub async fn write_10( &mut self, start_block: u32, count: u16, buf: &[u8], ) -> Result>> ``` -------------------------------- ### Read Capacity (64-bit LBA) Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Retrieves the device's capacity using the 64-bit LBA version of the Read Capacity command. This version supports devices with more than 2TB of storage, but may not be universally supported. ```APIDOC ## read_capacity_16 ### Description Read capacity (64-bit LBA version, supports >2TB). Not universally supported. ### Method Signature ```rust pub async fn read_capacity_16(&mut self) -> Result<(u64, u32), Error> ``` ### Returns - `Result<(u64, u32), Error>`: A `Result` containing a tuple of `(blocks, block_size)` where `blocks` is the total number of logical blocks (u64) and `block_size` is the size of each block in bytes (u32), or an `Error` on failure. ``` -------------------------------- ### Any Trait Implementation Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.InquiryData.html Provides runtime type information for InquiryData by implementing the Any trait. ```rust fn type_id(&self) -> TypeId ``` -------------------------------- ### DeviceInfo Struct Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/async_block_device/struct.DeviceInfo.html Represents device size and granularity information. The total size of the device in bytes is calculated as blocks * block_size. ```APIDOC ## Struct DeviceInfo ### Description Device size and granularity information. The total size of the device in bytes is `blocks * block_size`. ### Fields * `blocks` (u64) - The total number of sectors (readable/writable blocks) on the device. * `block_size` (u32) - The size of each block. ``` -------------------------------- ### Zeroable Implementation for BlockLimitsPage Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.BlockLimitsPage.html Provides a method to create a BlockLimitsPage instance with all its fields zeroed out. ```rust fn zeroed() -> Self ``` -------------------------------- ### ScsiDevice::read_10 Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.ScsiDevice.html Reads data from the device using the 32-bit LBA version. Supported by all disk devices, but limited to the first 2TB on large devices. ```APIDOC ## ScsiDevice::read_10 ### Description Read sector(s), 32-bit LBA version. All disk devices are required to support this, but on large devices it is only capable of reading within the first 2TB. ### Signature ```rust pub async fn read_10( &mut self, start_block: u32, count: u16, buf: &mut [u8], ) -> Result> ``` ``` -------------------------------- ### Test Unit Ready SCSI Command Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Sends a SCSI Test Unit Ready command to check device status. Handles potential errors during the transport command. ```rust pub async fn test_unit_ready(&mut self) -> Result<(), Error> { let cmd = TestUnitReady::new(); let rc = self .transport .command(bytemuck::bytes_of(&cmd), DataPhase::None) .await; match rc { Err(e) => Err(self.try_upgrade_error(e).await), Ok(_) => Ok(()), } } ``` -------------------------------- ### Send a generic SCSI command Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.ScsiDevice.html Sends a generic SCSI command and waits for a reply. Only one command can be in flight at a time. This method is asynchronous. ```rust pub async fn command_response( &mut self, cmd: C, ) -> Result>> ``` -------------------------------- ### AsyncBlockDevice: Write Blocks Implementation Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_block_device.rs.html Implements the write_blocks method for ScsiBlockDevice. It selects between WRITE(10) and WRITE(16) based on the transfer size and offset, handling potential address range errors. ```rust async fn write_blocks( &mut self, offset: u64, count: u32, data: &[u8], ) -> Result<(), Self::E> { let end = offset .checked_add(count as u64) .ok_or(Error::Scsi(ScsiError::LogicalBlockAddressOutOfRange))?; if end < u32::MAX as u64 && count < u16::MAX as u32 { self.scsi .write_10(offset as u32, count as u16, data) .await?; } else { self.scsi.write_16(offset, count, data).await?; } Ok(()) } } ``` -------------------------------- ### Default Implementation for BlockLimitsPage Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.BlockLimitsPage.html Provides a default value for the BlockLimitsPage struct, allowing it to be created with standard default settings. ```rust fn default() -> BlockLimitsPage ``` -------------------------------- ### Read Capacity (32-bit LBA) Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Retrieves the device's capacity using the 32-bit LBA version of the Read Capacity command. This is suitable for devices with less than 2TB of storage. ```APIDOC ## read_capacity_10 ### Description Read capacity (32-bit LBA version, supports <2TB only). ### Method Signature ```rust pub async fn read_capacity_10(&mut self) -> Result<(u32, u32), Error> ``` ### Returns - `Result<(u32, u32), Error>`: A `Result` containing a tuple of `(blocks, block_size)` where `blocks` is the total number of logical blocks (u32) and `block_size` is the size of each block in bytes (u32), or an `Error` on failure. ``` -------------------------------- ### AsyncBlockDevice: Read Blocks Implementation Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_block_device.rs.html Implements the read_blocks method for ScsiBlockDevice. It uses READ(10) for smaller transfers and READ(16) for larger ones, ensuring the offset and count do not exceed limits. ```rust async fn read_blocks( &mut self, offset: u64, count: u32, data: &mut [u8], ) -> Result<(), Self::E> { let end = offset .checked_add(count as u64) .ok_or(Error::Scsi(ScsiError::LogicalBlockAddressOutOfRange))?; let sz = if end < u32::MAX as u64 && count < u16::MAX as u32 { self.scsi.read_10(offset as u32, count as u16, data).await? } else { self.scsi.read_16(offset, count, data).await? }; if sz < data.len() { return Err(Error::ProtocolError); } Ok(()) } // ... other methods ``` -------------------------------- ### ScsiDevice::command_response Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.ScsiDevice.html Sends a generic SCSI command and awaits a reply. Only one command can be in-flight at a time. ```APIDOC ## ScsiDevice::command_response ### Description Send a generic SCSI command and await a reply. Only one command is ever “in-flight” at once, so even though this function is asynchronous, nothing else happens until the reply is returned. ### Signature ```rust pub async fn command_response( &mut self, cmd: C, ) -> Result> ``` ``` -------------------------------- ### AsyncBlockDevice::write_blocks Implementation Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_block_device/struct.ScsiBlockDevice.html Implements the write_blocks method for ScsiBlockDevice, allowing writing of blocks to the device. ```rust async fn write_blocks( &mut self, offset: u64, count: u32, data: &[u8], ) -> Result<(), Self::E> ``` -------------------------------- ### Read capacity (64-bit LBA) Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.ScsiDevice.html Reads the capacity of the SCSI device using the 64-bit LBA version. This is required for devices larger than 2TB. Note that this command is not universally supported. ```rust pub async fn read_capacity_16(&mut self) -> Result<(u64, u32), Error>> ``` -------------------------------- ### PartialEq Implementation for InquiryData Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.InquiryData.html Allows for equality comparison between InquiryData instances. ```rust fn eq(&self, other: &InquiryData) -> bool ``` ```rust fn ne(&self, other: &Rhs) -> bool ``` -------------------------------- ### Clone Implementation for BlockLimitsPage Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.BlockLimitsPage.html Provides methods to create a duplicate of a BlockLimitsPage instance or perform copy-assignment from another instance. ```rust fn clone(&self) -> BlockLimitsPage ``` ```rust fn clone_from(&mut self, source: &Self) ``` -------------------------------- ### DeviceInfo Struct Definition Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/async_block_device/struct.DeviceInfo.html Defines the structure for device information, containing the total number of blocks and the size of each block. ```rust pub struct DeviceInfo { pub blocks: u64, pub block_size: u32, } ``` -------------------------------- ### ScsiTransport::command Method Signature Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_transport/trait.ScsiTransport.html The command method executes a raw SCSI command block. It takes the command bytes and a DataPhase for input/output buffers. It returns a future that resolves to the number of bytes transferred or a transport-level error. ```rust fn command( &mut self, cmd: &[u8], data: DataPhase<'_>, ) -> impl Future>> ``` -------------------------------- ### Implement Zeroable and Pod for BlockLimitsPage Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Implements safety traits for the BlockLimitsPage struct, indicating it is zeroable and a Plain Old Data type for memory operations. ```rust // SAFETY: all fields zeroable unsafe impl bytemuck::Zeroable for BlockLimitsPage {} // SAFETY: no padding, no disallowed bit patterns unsafe impl bytemuck::Pod for BlockLimitsPage {} ``` -------------------------------- ### ScsiDevice::block_limits_page Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.ScsiDevice.html Retrieves the Vital Product Data, Block Limits Page, which contains information like maximum write size and optimum write granularity. Support for this page is limited. ```APIDOC ## ScsiDevice::block_limits_page ### Description Return Vital Product Data, Block Limits Page. Which is meant to contain important information like maximum write size and optimum write granularity, but not much seems to support it. ### Signature ```rust pub async fn block_limits_page(&mut self) -> Result> ``` ``` -------------------------------- ### Inquiry Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Sends a SCSI INQUIRY command to identify the type of device (e.g., disk, CD-ROM). This is often one of the first commands sent to a new device. ```APIDOC ## inquiry ### Description Sends a SCSI INQUIRY command to retrieve device identification data. ### Method `pub async fn inquiry(&mut self) -> Result>` ### Parameters None ### Response - `Ok(InquiryData)` containing peripheral type and removability information. - `Err(Error)` on failure. ``` -------------------------------- ### Define READ CAPACITY (10) SCSI Command Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Defines the structure for the SCSI READ CAPACITY (10) command. Use this to query the capacity of a SCSI device. ```rust /// READ CAPACITY (10) /// Seagate SCSI Commands Reference Manual s3.23.2 #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "std", derive(Debug))] #[derive(Copy, Clone)] #[repr(C)] struct ReadCapacity10 { operation_code: u8, reserved1: u8, lba_be: [u8; 4], reserved6: [u8; 3], control: u8, } impl ReadCapacity10 { fn new() -> Self { assert!(core::mem::size_of::() == 10); Self { operation_code: 0x25, reserved1: 0, lba_be: [0u8; 4], reserved6: [0; 3], control: 0, } } } // SAFETY: all fields zeroable unsafe impl bytemuck::Zeroable for ReadCapacity10 {} // SAFETY: no padding, no disallowed bit patterns unsafe impl bytemuck::Pod for ReadCapacity10 {} ``` -------------------------------- ### Default Implementation for InquiryData Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.InquiryData.html Provides a default value for InquiryData, allowing for easy initialization. ```rust fn default() -> InquiryData ``` -------------------------------- ### Read 10 Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Reads sector(s) using the 32-bit Logical Block Addressing (LBA) version of the command. Capable of reading within the first 2TB of a device. ```APIDOC ## read_10 ### Description Reads sector(s) from the device using the 32-bit LBA version of the READ command. ### Method `pub async fn read_10(&mut self, start_block: u32, count: u16, buf: &mut [u8]) -> Result>` ### Parameters - **start_block** (u32) - The starting block address. - **count** (u16) - The number of sectors to read. - **buf** (&mut [u8]) - A mutable buffer to store the read data. ### Response - `Ok(usize)` representing the number of bytes read. - `Err(Error)` on failure. ``` -------------------------------- ### Clone Implementation for InquiryData Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.InquiryData.html Provides methods for cloning InquiryData instances, allowing for duplicate creation and copy-assignment. ```rust fn clone(&self) -> InquiryData ``` ```rust fn clone_from(&mut self, source: &Self) ``` -------------------------------- ### Read Capacity (32-bit LBA) Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Reads the device's capacity using the 32-bit Logical Block Addressing (LBA) method. This is suitable for devices with less than 2TB of storage. ```rust pub async fn read_capacity_10( &mut self, ) -> Result<(u32, u32), Error> { let reply: ReadCapacity10Reply = self.command_response(ReadCapacity10::new()).await?; let blocks = u32::from_be_bytes(reply.lba); let block_size = u32::from_be_bytes(reply.block_size); Ok((blocks, block_size)) ``` -------------------------------- ### Read 16 Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Reads sector(s) using the 64-bit Logical Block Addressing (LBA) version of the command. This is necessary for devices larger than 2TB. ```APIDOC ## read_16 ### Description Reads sector(s) from the device using the 64-bit LBA version of the READ command. ### Method `pub async fn read_16(&mut self, start_block: u64, count: u32, buf: &mut [u8]) -> Result>` ### Parameters - **start_block** (u64) - The starting block address. - **count** (u32) - The number of sectors to read. - **buf** (&mut [u8]) - A mutable buffer to store the read data. ### Response - `Ok(usize)` representing the number of bytes read. - `Err(Error)` on failure. ``` -------------------------------- ### Copy and Eq Implementations for BlockLimitsPage Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.BlockLimitsPage.html Indicates that BlockLimitsPage implements the Copy and Eq traits, meaning its values can be copied bitwise and are guaranteed to be comparable for equality. ```rust impl Copy for BlockLimitsPage ``` ```rust impl Eq for BlockLimitsPage ``` -------------------------------- ### Send Generic SCSI Command Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Sends a generic SCSI command to the device and awaits a reply. This method is asynchronous but ensures only one command is processed at a time. ```APIDOC ## command_response ### Description Sends a generic SCSI command and awaits a reply. Only one command is ever "in-flight" at once, so even though this function is asynchronous, nothing else happens until the reply is returned. ### Method Signature ```rust pub async fn command_response(&mut self, cmd: C) -> Result> ``` ### Parameters - `cmd`: A type `C` that implements `bytemuck::Pod`, representing the SCSI command to be sent. ### Returns - `Result>`: A `Result` containing the response of type `R` (which must implement `bytemuck::NoUninit + bytemuck::AnyBitPattern + Default`) on success, or an `Error` on failure. ``` -------------------------------- ### Read sectors (32-bit LBA) Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.ScsiDevice.html Reads a specified number of sectors from the device using the 32-bit LBA version. All disk devices must support this, but it's limited to the first 2TB on large devices. ```rust pub async fn read_10( &mut self, start_block: u32, count: u16, buf: &mut [u8], ) -> Result>> ``` -------------------------------- ### Read sectors (64-bit LBA) Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.ScsiDevice.html Reads a specified number of sectors from the device using the 64-bit LBA version. This is required for devices larger than 2TB but is not universally supported. ```rust pub async fn read_16( &mut self, start_block: u64, count: u32, buf: &mut [u8], ) -> Result>> ``` -------------------------------- ### AsyncBlockDevice for ScsiBlockDevice Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_block_device/struct.ScsiBlockDevice.html Implementations of the AsyncBlockDevice trait for ScsiBlockDevice, providing block-level read/write and device info operations. ```APIDOC ## `AsyncBlockDevice` Implementation ### Description Provides block-level operations for the `ScsiBlockDevice`. ### Methods #### `device_info` * **Description**: Return the capacity and block-size (granularity) of this device. * **Signature**: `async fn device_info(&mut self) -> Result` #### `read_blocks` * **Description**: Read a block or blocks from the device. * **Signature**: `async fn read_blocks(&mut self, offset: u64, count: u32, data: &mut [u8]) -> Result<(), Self::E>` #### `write_blocks` * **Description**: Write a block or blocks to the device. * **Signature**: `async fn write_blocks(&mut self, offset: u64, count: u32, data: &[u8]) -> Result<(), Self::E>` ### Associated Types * `E`: The type of errors which this device can report. `type E = Error<::Error>` ``` -------------------------------- ### Pod Implementation for BlockLimitsPage Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.BlockLimitsPage.html Marks BlockLimitsPage as a Plain Old Data (Pod) type, indicating it has a simple memory layout suitable for low-level operations. ```rust impl Pod for BlockLimitsPage ``` -------------------------------- ### AsyncBlockDevice::read_blocks Implementation Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_block_device/struct.ScsiBlockDevice.html Implements the read_blocks method for ScsiBlockDevice, allowing reading of blocks from the device. ```rust async fn read_blocks( &mut self, offset: u64, count: u32, data: &mut [u8], ) -> Result<(), Self::E> ``` -------------------------------- ### Read Sectors (10-bit LBA) Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Reads sectors from a device using the 10-bit Logical Block Addressing (LBA) command. This is a mandatory command for all disk devices but is limited to the first 2TB on large devices. ```rust pub async fn read_10( &mut self, start_block: u32, count: u16, buf: &mut [u8], ) -> Result> { let cmd = Read10::new(start_block, count); let rc = self .transport .command(bytemuck::bytes_of(&cmd), DataPhase::In(buf)) .await; if let Err(e) = rc { return Err(self.try_upgrade_error(e).await); } rc } ``` -------------------------------- ### Read Block Limits Page Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.ScsiDevice.html Retrieves the Vital Product Data (VPD) Block Limits Page from the device. This page contains information like maximum write size, but it's not widely supported. ```rust pub async fn block_limits_page( &mut self, ) -> Result>> ``` -------------------------------- ### Define WRITE (10) SCSI Command Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Defines the structure for the SCSI WRITE (10) command. Use this for initiating write operations with a 32-bit Logical Block Address and a 16-bit transfer length. ```rust /// WRITE (10) /// Seagate SCSI Commands Reference Manual s3.60 #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "std", derive(Debug))] #[derive(Copy, Clone)] #[repr(C)] struct Write10 { operation_code: u8, flags: u8, lba_be: [u8; 4], group: u8, transfer_length_be: [u8; 2], control: u8, } impl Write10 { fn new(lba: u32, count: u16) -> Self { assert!(core::mem::size_of::() == 10); Self { operation_code: 0x2A, flags: 0, lba_be: lba.to_be_bytes(), transfer_length_be: count.to_be_bytes(), group: 0, control: 0, } } } // SAFETY: all fields zeroable unsafe impl bytemuck::Zeroable for Write10 {} // SAFETY: no padding, no disallowed bit patterns unsafe impl bytemuck::Pod for Write10 {} ``` -------------------------------- ### AnyBitPattern Implementation for Pod Types Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.BlockLimitsPage.html Implements the AnyBitPattern trait for types T that are Pod, indicating they can be safely reinterpreted as raw bits. ```rust impl AnyBitPattern for T where T: Pod, ``` -------------------------------- ### Define WRITE (16) SCSI Command Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Defines the structure for the SCSI WRITE (16) command. Use this for write operations requiring a 64-bit Logical Block Address and a 32-bit transfer length. ```rust /// WRITE (16) /// Seagate SCSI Commands Reference Manual s3.62 #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "std", derive(Debug))] #[derive(Copy, Clone)] #[repr(C)] struct Write16 { operation_code: u8, flags: u8, lba_be: [u8; 8], transfer_length_be: [u8; 4], group: u8, control: u8, } impl Write16 { fn new(lba: u64, count: u32) -> Self { assert!(core::mem::size_of::() == 16); Self { operation_code: 0x8A, flags: 0, lba_be: lba.to_be_bytes(), transfer_length_be: count.to_be_bytes(), group: 0, control: 0, } } } // SAFETY: all fields zeroable unsafe impl bytemuck::Zeroable for Write16 {} // SAFETY: no padding, no disallowed bit patterns unsafe impl bytemuck::Pod for Write16 {} ``` -------------------------------- ### ScsiDevice::read_capacity_10 Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.ScsiDevice.html Reads the device capacity using the 32-bit LBA version, supporting devices up to 2TB. ```APIDOC ## ScsiDevice::read_capacity_10 ### Description Read capacity (32-bit LBA version, supports <2TB only). ### Signature ```rust pub async fn read_capacity_10(&mut self) -> Result<(u32, u32), Error> ``` ``` -------------------------------- ### Request Sense Reply Structure Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Defines the structure for the reply of a Request Sense SCSI command. Contains detailed error information. ```rust struct RequestSenseReply { response_code: u8, reserved1: u8, sense_key: u8, information: [u8; 4], additional_length: u8, command_specific_information: [u8; 4], additional_sense_code: u8, additional_sense_code_qualifier: u8, fru_code: u8, sense_key_specific: [u8; 3], } ``` -------------------------------- ### Report supported operation codes Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.ScsiDevice.html Checks if specific operation codes are supported by the device. This command is not widely supported by devices. ```rust pub async fn report_supported_operation_codes( &mut self, opcode: u8, service_action: Option, ) -> Result>> ``` -------------------------------- ### Read Sectors (16-bit LBA) Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Reads sectors from a device using the 16-bit Logical Block Addressing (LBA) command. This command is not universally supported but should be available on devices larger than 2TB. ```rust pub async fn read_16( &mut self, start_block: u64, count: u32, buf: &mut [u8], ) -> Result> { let cmd = Read16::new(start_block, count); let rc = self .transport .command(bytemuck::bytes_of(&cmd), DataPhase::In(buf)) .await; ``` -------------------------------- ### TryFrom and TryInto Trait Implementations Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.InquiryData.html Enables fallible conversions to and from InquiryData. ```rust type Error = Infallible ``` ```rust fn try_from(value: U) -> Result>::Error> ``` ```rust type Error = >::Error ``` ```rust fn try_into(self) -> Result>::Error> ``` -------------------------------- ### TryInto::try_into Implementation Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_block_device/struct.ScsiBlockDevice.html Implements the try_into method from the TryInto trait. This is a blanket implementation. ```rust fn try_into(self) -> Result>::Error> ``` -------------------------------- ### Query Supported SCSI Commands Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_block_device.rs.html Attempts to query supported SCSI commands using 'Report Supported Operation Codes'. Note that this command is often not supported by devices, typically returning ScsiError::InvalidCommandOperationCode. ```rust /// For testing: query supported SCSI commands on this device /// /// Unfortunately, "Report Supported Operation Codes", which this /// relies on, is itself rarely a supported SCSI command: I /// haven't found a device yet where this call works. Instead it /// always returns `ScsiError::InvalidCommandOperationCode`. pub async fn query_commands(&mut self) -> Result<(), Error> { const CMDS: &[(&str, u8)] = &[ ("READ(6)", 0x08), ("READ(10)", 0x28), ("READ(12)", 0xA8), ("READ(16)", 0x88), ("WRITE(6)", 0x0A), ("WRITE(10)", 0x2A), ("WRITE(12)", 0xAA), ("WRITE(16)", 0x8A), ("WRITE ATOMIC(16)", 0x9C), ("WRITE AND VERIFY(16)", 0x8E), ]; for c in CMDS { let ok = self .scsi .report_supported_operation_codes(c.1, None) .await?; debug::println!("{} {}", c.0, ok); } Ok(()) } } ``` -------------------------------- ### Send SCSI INQUIRY command Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/scsi_device/struct.ScsiDevice.html Sends a SCSI INQUIRY command to the device and retrieves its reply. This is typically one of the first commands issued to identify the device type. ```rust pub async fn inquiry(&mut self) -> Result>> ``` -------------------------------- ### Request Sense Command Structure Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Defines the structure for the Request Sense SCSI command. Used to retrieve sense data from a device when an error has occurred. ```rust struct RequestSense { operation_code: u8, desc: u8, reserved: [u8; 2], allocation_length: u8, control: u8, } impl RequestSense { fn new() -> Self { assert!(core::mem::size_of::() == 6); Self { operation_code: 3, desc: 0, reserved: [0; 2], allocation_length: 18, control: 0, } } } ``` -------------------------------- ### TryFrom Implementation Source: https://docs.rs/cotton-scsi/latest/cotton_scsi/async_block_device/struct.DeviceInfo.html Enables fallible conversion from type `U` to type `T`. It returns a `Result` to handle potential conversion errors. ```rust type Error = Infallible ``` ```rust fn try_from(value: U) -> Result>::Error> ``` -------------------------------- ### Implement Zeroable and Pod for Inquiry Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Implements safety traits for the Inquiry struct, indicating it is zeroable and a Plain Old Data type suitable for direct memory access. ```rust // SAFETY: all fields zeroable unsafe impl bytemuck::Zeroable for Inquiry {} // SAFETY: no padding, no disallowed bit patterns unsafe impl bytemuck::Pod for Inquiry {} ``` -------------------------------- ### write_10 Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Writes data to a SCSI device using a 32-bit Logical Block Addressing (LBA) scheme. This method is universally supported but may be limited to the first 2TB on larger devices. ```APIDOC ## write_10 ### Description Writes sector(s) using a 32-bit LBA. This is required for all disk devices, but on large devices, it is only capable of writing within the first 2TB. ### Method `async fn write_10(&mut self, start_block: u32, count: u16, buf: &[u8]) -> Result>` ### Parameters - `start_block` (u32): The starting block address for the write operation. - `count` (u16): The number of sectors to write. - `buf` (&[u8]): A slice containing the data to be written. ``` -------------------------------- ### InquiryData Struct Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Holds information obtained from the SCSI INQUIRY command. ```APIDOC ## InquiryData Struct ### Description Contains essential information about a SCSI device, typically retrieved using the `inquiry` method on a `ScsiDevice`. ### Fields - **peripheral_type** (PeripheralType): The general type of the attached SCSI device, using the `PeripheralType` enum. - **is_removable** (bool): A boolean indicating whether the SCSI device supports removable media. For example, disk drives typically do not, while CD-ROMs usually do. ``` -------------------------------- ### Implement Zeroable and Pod for StandardInquiryData Source: https://docs.rs/cotton-scsi/latest/src/cotton_scsi/scsi_device.rs.html Implements safety traits for the StandardInquiryData struct, marking it as zeroable and a Plain Old Data type for memory operations. ```rust // SAFETY: all fields zeroable unsafe impl bytemuck::Zeroable for StandardInquiryData {} // SAFETY: no padding, no disallowed bit patterns unsafe impl bytemuck::Pod for StandardInquiryData {} ```