1use byteorder::{ByteOrder, BE};
2use error::{ErrorCause, ScsiError};
3use scsi::commands::{Command, CommandBlockWrapper, Direction};
4use traits::{BufferPullable, BufferPushable};
5
6#[derive(Clone, Copy, Eq, PartialEq, Debug)]
8pub struct InquiryCommand {
9 pub allocation_length: u8,
14}
15
16impl Default for InquiryCommand {
17 fn default() -> Self {
18 InquiryCommand::new(36)
19 }
20}
21
22impl InquiryCommand {
23 pub fn new(allocation_length: u8) -> InquiryCommand {
26 InquiryCommand { allocation_length }
27 }
28}
29
30impl BufferPushable for InquiryCommand {
31 fn push_to_buffer<B: AsMut<[u8]>>(&self, mut buffer: B) -> Result<usize, ScsiError> {
32 let mut buffer = buffer.as_mut();
33 let cur_idx = self.wrapper().push_to_buffer(&mut buffer)?;
34 buffer[cur_idx] = InquiryCommand::opcode();
35 buffer[cur_idx + 1] = 0;
36 buffer[cur_idx + 2] = 0;
37 buffer[cur_idx + 3] = 0;
38 buffer[cur_idx + 4] = self.allocation_length;
39 Ok(cur_idx + 5)
40 }
41}
42
43impl BufferPullable for InquiryCommand {
44 fn pull_from_buffer<B: AsRef<[u8]>>(buffer: B) -> Result<Self, ScsiError> {
45 let buffer = buffer.as_ref();
46 let header = CommandBlockWrapper::pull_from_buffer(buffer)?;
47 let opcode = buffer[15];
48 if opcode != InquiryCommand::opcode() {
49 return Err(ScsiError::from_cause(ErrorCause::ParseError));
50 }
51 let allocation_length_with_padding = BE::read_u32(&buffer[16..]);
52
53 let allocation_length = allocation_length_with_padding as u8;
54
55 if !header.data_transfer_length == allocation_length_with_padding
56 || header.direction != Direction::IN
57 || header.cb_length != InquiryCommand::length()
58 {
59 Err(ScsiError::from_cause(ErrorCause::ParseError))
60 } else {
61 Ok(InquiryCommand::new(allocation_length))
62 }
63 }
64}
65
66impl Command for InquiryCommand {
67 fn wrapper(&self) -> CommandBlockWrapper {
68 CommandBlockWrapper::new(
69 u32::from(self.allocation_length),
70 Direction::IN,
71 0,
72 InquiryCommand::length(),
73 )
74 }
75
76 fn opcode() -> u8 {
77 0x12
78 }
79
80 fn length() -> u8 {
81 0x6
82 }
83}
84
85#[derive(Clone, Copy, Eq, PartialEq, Debug, Default)]
90pub struct InquiryResponse {
91 pub device_qualifier: u8,
110
111 pub device_type: u8,
117
118 pub removable_flags: u8,
125
126 pub spc_version: u8,
133
134 pub response_format: u8,
138}
139
140impl BufferPullable for InquiryResponse {
141 fn pull_from_buffer<B: AsRef<[u8]>>(buffer: B) -> Result<InquiryResponse, ScsiError> {
142 let buffer = buffer.as_ref();
143 let bt = buffer[0];
144 let device_qualifier = bt & 0xe0;
145 let device_type = bt & 0x1f;
146 let removable_flags = buffer[1];
147 let spc_version = buffer[2];
148 let response_format = buffer[3];
149 Ok(InquiryResponse {
150 device_qualifier,
151 device_type,
152 removable_flags,
153 spc_version,
154 response_format,
155 })
156 }
157}
158
159impl BufferPushable for InquiryResponse {
160 fn push_to_buffer<B: AsMut<[u8]>>(&self, mut buffer: B) -> Result<usize, ScsiError> {
161 let buffer = buffer.as_mut();
162 let bt = self.device_qualifier | self.device_type;
163 buffer[0] = bt;
164 buffer[1] = self.removable_flags;
165 buffer[2] = self.spc_version;
166 buffer[3] = self.response_format;
167 Ok(4)
168 }
169}
170#[cfg(test)]
171mod tests {
172 use super::{InquiryCommand, InquiryResponse};
173 use crate::{BufferPullable, BufferPushable};
174
175 #[test]
176 pub fn test_inquirycommand() {
177 let expected: [u8; 31] = [
178 0x55, 0x53, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x80, 0x00,
179 0x06, 0x12, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180 0x00, 0x00, 0x00,
181 ];
182 let mut buff = [0; 32];
183 let inquiry_command = InquiryCommand::new(0x5);
184 let pushed = inquiry_command.push_to_buffer(&mut buff).unwrap();
185 assert_eq!(pushed, 20);
186 assert_eq!(&buff[0..pushed], &expected[0..pushed]);
187
188 let pulled = InquiryCommand::pull_from_buffer(&mut buff).unwrap();
189 assert_eq!(pulled, inquiry_command);
190 }
191 #[test]
192 pub fn test_inquiryresponse() {
193 let expected: [u8; 31] = [
194 0xab, 0x56, 0x78, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x80, 0x00,
195 0x06, 0x12, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196 0x00, 0x00, 0x00,
197 ];
198 let mut buff = [0; 32];
199 let inquiry_command = InquiryResponse {
200 device_qualifier: 0xa0,
201 device_type: 0x0b,
202 removable_flags: 0x56,
203 spc_version: 0x78,
204 response_format: 0x9a,
205 };
206 let pushed = inquiry_command.push_to_buffer(&mut buff).unwrap();
207 assert_eq!(pushed, 4);
208 assert_eq!(&buff[0..pushed], &expected[0..pushed]);
209
210 let pulled = InquiryResponse::pull_from_buffer(&mut buff).unwrap();
211 assert_eq!(pulled, inquiry_command);
212 }
213}