103 lines
2.7 KiB
Rust
103 lines
2.7 KiB
Rust
use libk::error::Error;
|
|
|
|
use crate::device::ScsiDeviceType;
|
|
|
|
pub trait ScsiCommand {
|
|
type Response;
|
|
const REQUEST_LEN: usize;
|
|
const RESPONSE_LEN: usize;
|
|
|
|
fn into_bytes(self) -> [u8; Self::REQUEST_LEN];
|
|
fn parse_response(bytes: &[u8]) -> Result<Self::Response, Error>;
|
|
}
|
|
|
|
// Add more info when needed
|
|
pub struct ScsiInquiry;
|
|
#[derive(Debug)]
|
|
pub struct ScsiInquiryResponse {
|
|
pub device_type: ScsiDeviceType,
|
|
}
|
|
|
|
impl ScsiCommand for ScsiInquiry {
|
|
type Response = ScsiInquiryResponse;
|
|
const REQUEST_LEN: usize = 6;
|
|
const RESPONSE_LEN: usize = 36;
|
|
|
|
fn into_bytes(self) -> [u8; Self::REQUEST_LEN] {
|
|
[0x12, 0x00, 0x00, 0x00, 0x00, 0x00]
|
|
}
|
|
|
|
fn parse_response(bytes: &[u8]) -> Result<Self::Response, Error> {
|
|
if bytes.len() != 36 {
|
|
return Err(Error::InvalidArgument);
|
|
}
|
|
let device_type = ScsiDeviceType::try_from(bytes[0] & 0x1F).unwrap_or_default();
|
|
Ok(ScsiInquiryResponse { device_type })
|
|
}
|
|
}
|
|
|
|
pub struct ScsiTestUnitReady;
|
|
#[derive(Debug)]
|
|
pub struct ScsiTestUnitReadyResponse;
|
|
|
|
impl ScsiCommand for ScsiTestUnitReady {
|
|
type Response = ScsiTestUnitReadyResponse;
|
|
const RESPONSE_LEN: usize = 0;
|
|
const REQUEST_LEN: usize = 6;
|
|
|
|
fn into_bytes(self) -> [u8; Self::REQUEST_LEN] {
|
|
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
|
|
}
|
|
|
|
fn parse_response(_bytes: &[u8]) -> Result<Self::Response, Error> {
|
|
Ok(ScsiTestUnitReadyResponse)
|
|
}
|
|
}
|
|
|
|
pub struct ScsiRequestSense;
|
|
#[derive(Debug)]
|
|
pub struct ScsiRequestSenseResponse;
|
|
|
|
impl ScsiCommand for ScsiRequestSense {
|
|
type Response = ScsiRequestSenseResponse;
|
|
const RESPONSE_LEN: usize = 0;
|
|
const REQUEST_LEN: usize = 6;
|
|
|
|
fn into_bytes(self) -> [u8; Self::REQUEST_LEN] {
|
|
[0x03, 0x00, 0x00, 0x00, 0x00, 0x00]
|
|
}
|
|
|
|
fn parse_response(_bytes: &[u8]) -> Result<Self::Response, Error> {
|
|
Ok(ScsiRequestSenseResponse)
|
|
}
|
|
}
|
|
|
|
pub struct ScsiReadCapacity;
|
|
#[derive(Debug)]
|
|
pub struct ScsiReadCapacityResponse {
|
|
pub block_size: u32,
|
|
pub block_count: u32,
|
|
}
|
|
|
|
impl ScsiCommand for ScsiReadCapacity {
|
|
type Response = ScsiReadCapacityResponse;
|
|
const REQUEST_LEN: usize = 10;
|
|
const RESPONSE_LEN: usize = 8;
|
|
|
|
fn into_bytes(self) -> [u8; Self::REQUEST_LEN] {
|
|
[0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
|
|
}
|
|
|
|
fn parse_response(bytes: &[u8]) -> Result<Self::Response, Error> {
|
|
if bytes.len() != 8 {
|
|
return Err(Error::InvalidArgument);
|
|
}
|
|
let block_count = u32::from_be_bytes(bytes[0..4].try_into().unwrap());
|
|
let block_size = u32::from_be_bytes(bytes[4..8].try_into().unwrap());
|
|
Ok(ScsiReadCapacityResponse {
|
|
block_size,
|
|
block_count,
|
|
})
|
|
}
|
|
}
|