scsir/command/
set_timestamp.rs1#![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}