scsir/command/
set_timestamp.rs

1#![allow(dead_code)]
2
3use modular_bitfield_msb::prelude::*;
4
5use crate::{
6    command::bitfield_bound_check,
7    data_wrapper::{AnyType, VecBufferWrapper},
8    result_data::ResultData,
9    Command, DataDirection, Scsi,
10};
11
12#[derive(Clone, Debug)]
13pub struct SetTimestampCommand<'a> {
14    interface: &'a Scsi,
15    command_buffer: CommandBuffer,
16    data_buffer: Vec<u8>,
17}
18
19impl<'a> SetTimestampCommand<'a> {
20    fn new(interface: &'a Scsi) -> Self {
21        Self {
22            interface,
23            command_buffer: CommandBuffer::new()
24                .with_operation_code(OPERATION_CODE)
25                .with_service_action(SERVICE_ACTION),
26            data_buffer: vec![],
27        }
28    }
29
30    pub fn control(&mut self, value: u8) -> &mut Self {
31        self.command_buffer.set_control(value);
32        self
33    }
34
35    pub fn parameter(&mut self, value: &[u8]) -> &mut Self {
36        self.data_buffer = value.to_owned();
37        self.command_buffer
38            .set_parameter_list_length(value.len() as u32);
39        self
40    }
41
42    pub fn issue(&mut self) -> crate::Result<()> {
43        bitfield_bound_check!(self.data_buffer.len(), 32, "parameter list length")?;
44
45        self.interface.issue(&ThisCommand {
46            command_buffer: self.command_buffer,
47            data_buffer: self.data_buffer.clone().into(),
48        })
49    }
50}
51
52impl Scsi {
53    pub fn set_timestamp(&self) -> SetTimestampCommand {
54        SetTimestampCommand::new(self)
55    }
56}
57
58const OPERATION_CODE: u8 = 0xA4;
59const SERVICE_ACTION: u8 = 0x0F;
60
61#[bitfield]
62#[derive(Clone, Copy, Debug)]
63struct CommandBuffer {
64    operation_code: B8,
65    reserved_0: B3,
66    service_action: B5,
67    reserved_1: B32,
68    parameter_list_length: B32,
69    reserved_2: B8,
70    control: B8,
71}
72
73struct ThisCommand {
74    command_buffer: CommandBuffer,
75    data_buffer: VecBufferWrapper,
76}
77
78impl Command for ThisCommand {
79    type CommandBuffer = CommandBuffer;
80
81    type DataBuffer = AnyType;
82
83    type DataBufferWrapper = VecBufferWrapper;
84
85    type ReturnType = crate::Result<()>;
86
87    fn direction(&self) -> DataDirection {
88        DataDirection::ToDevice
89    }
90
91    fn command(&self) -> Self::CommandBuffer {
92        self.command_buffer
93    }
94
95    fn data(&self) -> Self::DataBufferWrapper {
96        self.data_buffer.clone()
97    }
98
99    fn data_size(&self) -> u32 {
100        self.data_buffer.len() as u32
101    }
102
103    fn process_result(&self, result: ResultData<Self::DataBufferWrapper>) -> Self::ReturnType {
104        result.check_ioctl_error()?;
105        result.check_common_error()?;
106
107        Ok(())
108    }
109}
110
111#[cfg(test)]
112mod tests {
113    use super::*;
114    use std::mem::size_of;
115
116    const COMMAND_LENGTH: usize = 12;
117
118    #[test]
119    fn layout_test() {
120        assert_eq!(
121            size_of::<CommandBuffer>(),
122            COMMAND_LENGTH,
123            concat!("Size of: ", stringify!(CommandBuffer))
124        );
125    }
126}