1#![allow(dead_code)]
11
12#[cfg(feature = "alloc")]
13extern crate alloc;
14
15#[cfg(feature = "alloc")]
16use alloc::vec::Vec;
17use core::sync::atomic::{AtomicU32, Ordering};
18
19use crate::error::KernelError;
20
21mod scsi_opcodes {
27 pub const TEST_UNIT_READY: u8 = 0x00;
28 pub const REQUEST_SENSE: u8 = 0x03;
29 pub const INQUIRY: u8 = 0x12;
30 pub const READ_CAPACITY_10: u8 = 0x25;
31 pub const READ_10: u8 = 0x28;
32 pub const WRITE_10: u8 = 0x2A;
33}
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
41#[repr(u8)]
42pub enum SenseKey {
43 NoSense = 0x00,
44 RecoveredError = 0x01,
45 NotReady = 0x02,
46 MediumError = 0x03,
47 HardwareError = 0x04,
48 IllegalRequest = 0x05,
49 UnitAttention = 0x06,
50 DataProtect = 0x07,
51 BlankCheck = 0x08,
52 AbortedCommand = 0x0B,
53 VolumeOverflow = 0x0D,
54 Miscompare = 0x0E,
55}
56
57impl SenseKey {
58 pub fn from_byte(byte: u8) -> Self {
60 match byte & 0x0F {
61 0x00 => Self::NoSense,
62 0x01 => Self::RecoveredError,
63 0x02 => Self::NotReady,
64 0x03 => Self::MediumError,
65 0x04 => Self::HardwareError,
66 0x05 => Self::IllegalRequest,
67 0x06 => Self::UnitAttention,
68 0x07 => Self::DataProtect,
69 0x08 => Self::BlankCheck,
70 0x0B => Self::AbortedCommand,
71 0x0D => Self::VolumeOverflow,
72 0x0E => Self::Miscompare,
73 _ => Self::HardwareError,
74 }
75 }
76}
77
78pub const CBW_SIGNATURE: u32 = 0x43425355;
84
85pub const CBW_DIRECTION_OUT: u8 = 0x00;
87pub const CBW_DIRECTION_IN: u8 = 0x80;
88
89#[repr(C, packed)]
93#[derive(Debug, Clone, Copy)]
94pub struct CommandBlockWrapper {
95 pub signature: u32,
97 pub tag: u32,
99 pub data_transfer_length: u32,
101 pub flags: u8,
103 pub lun: u8,
105 pub cb_length: u8,
107 pub cb: [u8; 16],
109}
110
111impl CommandBlockWrapper {
112 pub const SIZE: usize = 31;
114
115 pub fn new(tag: u32, data_length: u32, direction: u8, lun: u8, command: &[u8]) -> Self {
117 let cb_len = command.len().min(16) as u8;
118 let mut cb = [0u8; 16];
119 let copy_len = command.len().min(16);
120 cb[..copy_len].copy_from_slice(&command[..copy_len]);
121
122 Self {
123 signature: CBW_SIGNATURE,
124 tag,
125 data_transfer_length: data_length,
126 flags: direction,
127 lun: lun & 0x0F,
128 cb_length: cb_len,
129 cb,
130 }
131 }
132
133 pub fn to_bytes(&self) -> [u8; Self::SIZE] {
135 let mut buf = [0u8; Self::SIZE];
136 let sig = self.signature.to_le_bytes();
137 buf[0..4].copy_from_slice(&sig);
138 let tag = self.tag.to_le_bytes();
139 buf[4..8].copy_from_slice(&tag);
140 let dtl = self.data_transfer_length.to_le_bytes();
141 buf[8..12].copy_from_slice(&dtl);
142 buf[12] = self.flags;
143 buf[13] = self.lun;
144 buf[14] = self.cb_length;
145 buf[15..31].copy_from_slice(&self.cb);
146 buf
147 }
148
149 pub fn from_bytes(data: &[u8]) -> Result<Self, KernelError> {
151 if data.len() < Self::SIZE {
152 return Err(KernelError::InvalidArgument {
153 name: "cbw_data",
154 value: "buffer too small for CBW",
155 });
156 }
157 let signature = u32::from_le_bytes([data[0], data[1], data[2], data[3]]);
158 if signature != CBW_SIGNATURE {
159 return Err(KernelError::InvalidArgument {
160 name: "cbw_signature",
161 value: "invalid CBW signature",
162 });
163 }
164 let tag = u32::from_le_bytes([data[4], data[5], data[6], data[7]]);
165 let data_transfer_length = u32::from_le_bytes([data[8], data[9], data[10], data[11]]);
166 let flags = data[12];
167 let lun = data[13];
168 let cb_length = data[14];
169 let mut cb = [0u8; 16];
170 cb.copy_from_slice(&data[15..31]);
171
172 Ok(Self {
173 signature,
174 tag,
175 data_transfer_length,
176 flags,
177 lun,
178 cb_length,
179 cb,
180 })
181 }
182}
183
184pub const CSW_SIGNATURE: u32 = 0x53425355;
190
191#[derive(Debug, Clone, Copy, PartialEq, Eq)]
193#[repr(u8)]
194pub enum CswStatus {
195 Passed = 0x00,
197 Failed = 0x01,
199 PhaseError = 0x02,
201}
202
203impl CswStatus {
204 pub fn from_byte(byte: u8) -> Self {
206 match byte {
207 0x00 => Self::Passed,
208 0x01 => Self::Failed,
209 _ => Self::PhaseError,
210 }
211 }
212}
213
214#[repr(C, packed)]
218#[derive(Debug, Clone, Copy)]
219pub struct CommandStatusWrapper {
220 pub signature: u32,
222 pub tag: u32,
224 pub data_residue: u32,
226 pub status: u8,
228}
229
230impl CommandStatusWrapper {
231 pub const SIZE: usize = 13;
233
234 pub fn from_bytes(data: &[u8]) -> Result<Self, KernelError> {
236 if data.len() < Self::SIZE {
237 return Err(KernelError::InvalidArgument {
238 name: "csw_data",
239 value: "buffer too small for CSW",
240 });
241 }
242 let signature = u32::from_le_bytes([data[0], data[1], data[2], data[3]]);
243 if signature != CSW_SIGNATURE {
244 return Err(KernelError::InvalidArgument {
245 name: "csw_signature",
246 value: "invalid CSW signature",
247 });
248 }
249 let tag = u32::from_le_bytes([data[4], data[5], data[6], data[7]]);
250 let data_residue = u32::from_le_bytes([data[8], data[9], data[10], data[11]]);
251 let status = data[12];
252
253 Ok(Self {
254 signature,
255 tag,
256 data_residue,
257 status,
258 })
259 }
260
261 pub fn to_bytes(&self) -> [u8; Self::SIZE] {
263 let mut buf = [0u8; Self::SIZE];
264 buf[0..4].copy_from_slice(&self.signature.to_le_bytes());
265 buf[4..8].copy_from_slice(&self.tag.to_le_bytes());
266 buf[8..12].copy_from_slice(&self.data_residue.to_le_bytes());
267 buf[12] = self.status;
268 buf
269 }
270
271 pub fn get_status(&self) -> CswStatus {
273 CswStatus::from_byte(self.status)
274 }
275}
276
277#[derive(Debug, Clone, Copy)]
283pub struct SenseData {
284 pub response_code: u8,
286 pub sense_key: SenseKey,
288 pub asc: u8,
290 pub ascq: u8,
292}
293
294impl SenseData {
295 pub fn from_bytes(data: &[u8]) -> Result<Self, KernelError> {
297 if data.len() < 14 {
298 return Err(KernelError::InvalidArgument {
299 name: "sense_data",
300 value: "buffer too small for sense data",
301 });
302 }
303 Ok(Self {
304 response_code: data[0] & 0x7F,
305 sense_key: SenseKey::from_byte(data[2]),
306 asc: data[12],
307 ascq: data[13],
308 })
309 }
310
311 pub fn is_ok(&self) -> bool {
313 self.sense_key == SenseKey::NoSense
314 }
315}
316
317#[derive(Debug, Clone, Copy)]
323pub struct InquiryData {
324 pub device_type: u8,
326 pub removable: bool,
328 pub version: u8,
330 pub vendor: [u8; 8],
332 pub product: [u8; 16],
334 pub revision: [u8; 4],
336}
337
338impl InquiryData {
339 pub fn from_bytes(data: &[u8]) -> Result<Self, KernelError> {
341 if data.len() < 36 {
342 return Err(KernelError::InvalidArgument {
343 name: "inquiry_data",
344 value: "buffer too small for inquiry response",
345 });
346 }
347 let mut vendor = [0u8; 8];
348 vendor.copy_from_slice(&data[8..16]);
349 let mut product = [0u8; 16];
350 product.copy_from_slice(&data[16..32]);
351 let mut revision = [0u8; 4];
352 revision.copy_from_slice(&data[32..36]);
353
354 Ok(Self {
355 device_type: data[0] & 0x1F,
356 removable: (data[1] & 0x80) != 0,
357 version: data[2],
358 vendor,
359 product,
360 revision,
361 })
362 }
363}
364
365#[derive(Debug, Clone, Copy, PartialEq, Eq)]
371pub enum MassStorageState {
372 Uninitialized,
374 Ready,
376 Error,
378}
379
380pub trait BlockDevice {
386 fn read_blocks(&self, lba: u64, count: u32, buf: &mut [u8]) -> Result<usize, KernelError>;
389
390 fn write_blocks(&self, lba: u64, count: u32, buf: &[u8]) -> Result<usize, KernelError>;
393
394 fn block_size(&self) -> u32;
396
397 fn total_blocks(&self) -> u64;
399}
400
401static NEXT_TAG: AtomicU32 = AtomicU32::new(1);
407
408fn next_tag() -> u32 {
410 NEXT_TAG.fetch_add(1, Ordering::Relaxed)
411}
412
413#[derive(Debug)]
415pub struct MassStorageDevice {
416 pub device_address: u8,
418 pub bulk_in_ep: u8,
420 pub bulk_out_ep: u8,
422 pub lun: u8,
424 pub max_lun: u8,
426 pub cached_block_size: u32,
428 pub cached_total_blocks: u64,
430 pub state: MassStorageState,
432 pub last_sense: Option<SenseData>,
434}
435
436impl MassStorageDevice {
437 pub fn new(device_address: u8, bulk_in_ep: u8, bulk_out_ep: u8) -> Self {
443 Self {
444 device_address,
445 bulk_in_ep,
446 bulk_out_ep,
447 lun: 0,
448 max_lun: 0,
449 cached_block_size: 0,
450 cached_total_blocks: 0,
451 state: MassStorageState::Uninitialized,
452 last_sense: None,
453 }
454 }
455
456 pub fn set_lun(&mut self, lun: u8) {
458 self.lun = lun;
459 }
460
461 pub fn build_inquiry_cdb(allocation_length: u8) -> [u8; 6] {
463 [
464 scsi_opcodes::INQUIRY,
465 0, 0, 0, allocation_length,
469 0, ]
471 }
472
473 pub fn build_test_unit_ready_cdb() -> [u8; 6] {
475 [
476 scsi_opcodes::TEST_UNIT_READY,
477 0,
478 0,
479 0,
480 0,
481 0, ]
483 }
484
485 pub fn build_request_sense_cdb(allocation_length: u8) -> [u8; 6] {
487 [
488 scsi_opcodes::REQUEST_SENSE,
489 0,
490 0,
491 0,
492 allocation_length,
493 0, ]
495 }
496
497 pub fn build_read_capacity_10_cdb() -> [u8; 10] {
499 [
500 scsi_opcodes::READ_CAPACITY_10,
501 0,
502 0,
503 0,
504 0,
505 0,
506 0,
507 0,
508 0,
509 0, ]
511 }
512
513 pub fn build_read_10_cdb(lba: u32, transfer_length: u16) -> [u8; 10] {
515 let lba_bytes = lba.to_be_bytes();
516 let len_bytes = transfer_length.to_be_bytes();
517 [
518 scsi_opcodes::READ_10,
519 0, lba_bytes[0],
521 lba_bytes[1],
522 lba_bytes[2],
523 lba_bytes[3],
524 0, len_bytes[0],
526 len_bytes[1],
527 0, ]
529 }
530
531 pub fn build_write_10_cdb(lba: u32, transfer_length: u16) -> [u8; 10] {
533 let lba_bytes = lba.to_be_bytes();
534 let len_bytes = transfer_length.to_be_bytes();
535 [
536 scsi_opcodes::WRITE_10,
537 0, lba_bytes[0],
539 lba_bytes[1],
540 lba_bytes[2],
541 lba_bytes[3],
542 0, len_bytes[0],
544 len_bytes[1],
545 0, ]
547 }
548
549 fn build_cbw(&self, command: &[u8], data_length: u32, direction: u8) -> CommandBlockWrapper {
551 CommandBlockWrapper::new(next_tag(), data_length, direction, self.lun, command)
552 }
553
554 fn validate_csw(
556 &mut self,
557 csw_bytes: &[u8],
558 expected_tag: u32,
559 ) -> Result<CommandStatusWrapper, KernelError> {
560 let csw = CommandStatusWrapper::from_bytes(csw_bytes)?;
561 if csw.tag != expected_tag {
562 self.state = MassStorageState::Error;
563 return Err(KernelError::HardwareError {
564 device: "usb-mass-storage",
565 code: 0x10, });
567 }
568 match csw.get_status() {
569 CswStatus::Passed => Ok(csw),
570 CswStatus::Failed => {
571 Err(KernelError::HardwareError {
573 device: "usb-mass-storage",
574 code: 0x11, })
576 }
577 CswStatus::PhaseError => {
578 self.state = MassStorageState::Error;
579 Err(KernelError::HardwareError {
580 device: "usb-mass-storage",
581 code: 0x12, })
583 }
584 }
585 }
586
587 pub fn initialize(&mut self) -> Result<InquiryData, KernelError> {
592 let inquiry_cdb = Self::build_inquiry_cdb(36);
594 let cbw = self.build_cbw(&inquiry_cdb, 36, CBW_DIRECTION_IN);
595 let inquiry_data = self.execute_command_in(&cbw, 36)?;
596 let inquiry = InquiryData::from_bytes(&inquiry_data)?;
597
598 if inquiry.device_type != 0x00 {
600 self.state = MassStorageState::Error;
601 return Err(KernelError::HardwareError {
602 device: "usb-mass-storage",
603 code: 0x20, });
605 }
606
607 let tur_cdb = Self::build_test_unit_ready_cdb();
609 let cbw = self.build_cbw(&tur_cdb, 0, CBW_DIRECTION_OUT);
610 if let Err(_e) = self.execute_command_none(&cbw) {
611 let _sense = self.request_sense();
613 let cbw = self.build_cbw(&tur_cdb, 0, CBW_DIRECTION_OUT);
615 self.execute_command_none(&cbw)?;
616 }
617
618 let rc_cdb = Self::build_read_capacity_10_cdb();
620 let cbw = self.build_cbw(&rc_cdb, 8, CBW_DIRECTION_IN);
621 let cap_data = self.execute_command_in(&cbw, 8)?;
622
623 if cap_data.len() >= 8 {
624 let last_lba = u32::from_be_bytes([cap_data[0], cap_data[1], cap_data[2], cap_data[3]]);
625 let block_size =
626 u32::from_be_bytes([cap_data[4], cap_data[5], cap_data[6], cap_data[7]]);
627
628 self.cached_total_blocks = (last_lba as u64) + 1;
629 self.cached_block_size = block_size;
630 }
631
632 self.state = MassStorageState::Ready;
633 Ok(inquiry)
634 }
635
636 pub fn request_sense(&mut self) -> Result<SenseData, KernelError> {
638 let cdb = Self::build_request_sense_cdb(18);
639 let cbw = self.build_cbw(&cdb, 18, CBW_DIRECTION_IN);
640 let sense_bytes = self.execute_command_in(&cbw, 18)?;
641 let sense = SenseData::from_bytes(&sense_bytes)?;
642 self.last_sense = Some(sense);
643 Ok(sense)
644 }
645
646 fn execute_command_in(
653 &mut self,
654 cbw: &CommandBlockWrapper,
655 expected_len: u32,
656 ) -> Result<Vec<u8>, KernelError> {
657 let _cbw_bytes = cbw.to_bytes();
659
660 let data = alloc::vec![0u8; expected_len as usize];
668 Ok(data)
669 }
670
671 fn execute_command_none(&mut self, cbw: &CommandBlockWrapper) -> Result<(), KernelError> {
673 let _cbw_bytes = cbw.to_bytes();
674
675 Ok(())
681 }
682
683 fn execute_command_out(
685 &mut self,
686 cbw: &CommandBlockWrapper,
687 data: &[u8],
688 ) -> Result<(), KernelError> {
689 let _cbw_bytes = cbw.to_bytes();
690 let _data_out = data;
691
692 Ok(())
699 }
700}
701
702impl BlockDevice for MassStorageDevice {
703 fn read_blocks(&self, lba: u64, count: u32, buf: &mut [u8]) -> Result<usize, KernelError> {
704 if self.state != MassStorageState::Ready {
705 return Err(KernelError::InvalidState {
706 expected: "Ready",
707 actual: "not Ready",
708 });
709 }
710
711 if self.cached_block_size == 0 {
712 return Err(KernelError::InvalidState {
713 expected: "initialized (block_size > 0)",
714 actual: "block_size is 0",
715 });
716 }
717
718 let total_bytes = (count as usize) * (self.cached_block_size as usize);
719 if buf.len() < total_bytes {
720 return Err(KernelError::InvalidArgument {
721 name: "buf",
722 value: "buffer too small for requested blocks",
723 });
724 }
725
726 if lba.saturating_add(count as u64) > self.cached_total_blocks {
728 return Err(KernelError::InvalidArgument {
729 name: "lba+count",
730 value: "exceeds device capacity",
731 });
732 }
733
734 let lba32 = lba as u32;
736 let cdb = Self::build_read_10_cdb(lba32, count as u16);
737 let cbw = CommandBlockWrapper::new(
738 next_tag(),
739 total_bytes as u32,
740 CBW_DIRECTION_IN,
741 self.lun,
742 &cdb,
743 );
744 let _cbw_bytes = cbw.to_bytes();
745
746 for byte in buf[..total_bytes].iter_mut() {
749 *byte = 0;
750 }
751
752 Ok(total_bytes)
753 }
754
755 fn write_blocks(&self, lba: u64, count: u32, buf: &[u8]) -> Result<usize, KernelError> {
756 if self.state != MassStorageState::Ready {
757 return Err(KernelError::InvalidState {
758 expected: "Ready",
759 actual: "not Ready",
760 });
761 }
762
763 if self.cached_block_size == 0 {
764 return Err(KernelError::InvalidState {
765 expected: "initialized (block_size > 0)",
766 actual: "block_size is 0",
767 });
768 }
769
770 let total_bytes = (count as usize) * (self.cached_block_size as usize);
771 if buf.len() < total_bytes {
772 return Err(KernelError::InvalidArgument {
773 name: "buf",
774 value: "buffer too small for requested blocks",
775 });
776 }
777
778 if lba.saturating_add(count as u64) > self.cached_total_blocks {
780 return Err(KernelError::InvalidArgument {
781 name: "lba+count",
782 value: "exceeds device capacity",
783 });
784 }
785
786 let lba32 = lba as u32;
787 let cdb = Self::build_write_10_cdb(lba32, count as u16);
788 let cbw = CommandBlockWrapper::new(
789 next_tag(),
790 total_bytes as u32,
791 CBW_DIRECTION_OUT,
792 self.lun,
793 &cdb,
794 );
795 let _cbw_bytes = cbw.to_bytes();
796
797 Ok(total_bytes)
799 }
800
801 fn block_size(&self) -> u32 {
802 self.cached_block_size
803 }
804
805 fn total_blocks(&self) -> u64 {
806 self.cached_total_blocks
807 }
808}
809
810#[cfg(test)]
815mod tests {
816 use super::*;
817
818 #[test]
819 fn test_cbw_signature() {
820 assert_eq!(CBW_SIGNATURE, 0x43425355);
821 }
822
823 #[test]
824 fn test_csw_signature() {
825 assert_eq!(CSW_SIGNATURE, 0x53425355);
826 }
827
828 #[test]
829 fn test_cbw_serialization_roundtrip() {
830 let command = [0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00];
831 let cbw = CommandBlockWrapper::new(42, 4096, CBW_DIRECTION_IN, 0, &command);
832 let bytes = cbw.to_bytes();
833
834 assert_eq!(bytes.len(), CommandBlockWrapper::SIZE);
835 assert_eq!(bytes[0], 0x55); assert_eq!(bytes[1], 0x53); assert_eq!(bytes[2], 0x42); assert_eq!(bytes[3], 0x43); let parsed = CommandBlockWrapper::from_bytes(&bytes).unwrap();
841 let tag = parsed.tag;
843 let dtl = parsed.data_transfer_length;
844 let flags = parsed.flags;
845 let lun = parsed.lun;
846 let cb0 = parsed.cb[0];
847 assert_eq!(tag, 42);
848 assert_eq!(dtl, 4096);
849 assert_eq!(flags, CBW_DIRECTION_IN);
850 assert_eq!(lun, 0);
851 assert_eq!(cb0, 0x28); }
853
854 #[test]
855 fn test_cbw_from_bytes_invalid_signature() {
856 let mut bytes = [0u8; 31];
857 bytes[0] = 0xFF; let result = CommandBlockWrapper::from_bytes(&bytes);
859 assert!(result.is_err());
860 }
861
862 #[test]
863 fn test_cbw_from_bytes_too_short() {
864 let bytes = [0u8; 10];
865 let result = CommandBlockWrapper::from_bytes(&bytes);
866 assert!(result.is_err());
867 }
868
869 #[test]
870 fn test_csw_serialization_roundtrip() {
871 let csw = CommandStatusWrapper {
872 signature: CSW_SIGNATURE,
873 tag: 42,
874 data_residue: 0,
875 status: CswStatus::Passed as u8,
876 };
877 let bytes = csw.to_bytes();
878 assert_eq!(bytes.len(), CommandStatusWrapper::SIZE);
879
880 let parsed = CommandStatusWrapper::from_bytes(&bytes).unwrap();
881 let tag = parsed.tag;
883 let residue = parsed.data_residue;
884 assert_eq!(tag, 42);
885 assert_eq!(residue, 0);
886 assert_eq!(parsed.get_status(), CswStatus::Passed);
887 }
888
889 #[test]
890 fn test_csw_failed_status() {
891 let csw = CommandStatusWrapper {
892 signature: CSW_SIGNATURE,
893 tag: 1,
894 data_residue: 512,
895 status: CswStatus::Failed as u8,
896 };
897 let bytes = csw.to_bytes();
898 let parsed = CommandStatusWrapper::from_bytes(&bytes).unwrap();
899 assert_eq!(parsed.get_status(), CswStatus::Failed);
900 let residue = parsed.data_residue;
901 assert_eq!(residue, 512);
902 }
903
904 #[test]
905 fn test_csw_phase_error() {
906 let status = CswStatus::from_byte(0x02);
907 assert_eq!(status, CswStatus::PhaseError);
908 let unknown = CswStatus::from_byte(0xFF);
910 assert_eq!(unknown, CswStatus::PhaseError);
911 }
912
913 #[test]
914 fn test_sense_key_parsing() {
915 assert_eq!(SenseKey::from_byte(0x00), SenseKey::NoSense);
916 assert_eq!(SenseKey::from_byte(0x02), SenseKey::NotReady);
917 assert_eq!(SenseKey::from_byte(0x05), SenseKey::IllegalRequest);
918 assert_eq!(SenseKey::from_byte(0x03), SenseKey::MediumError);
919 assert_eq!(SenseKey::from_byte(0xF5), SenseKey::IllegalRequest);
921 }
922
923 #[test]
924 fn test_sense_data_parsing() {
925 let mut raw = [0u8; 18];
926 raw[0] = 0x70; raw[2] = 0x05; raw[12] = 0x24; raw[13] = 0x00; let sense = SenseData::from_bytes(&raw).unwrap();
931 assert_eq!(sense.response_code, 0x70);
932 assert_eq!(sense.sense_key, SenseKey::IllegalRequest);
933 assert_eq!(sense.asc, 0x24);
934 assert_eq!(sense.ascq, 0x00);
935 assert!(!sense.is_ok());
936 }
937
938 #[test]
939 fn test_sense_data_no_sense() {
940 let mut raw = [0u8; 18];
941 raw[0] = 0x70;
942 raw[2] = 0x00; let sense = SenseData::from_bytes(&raw).unwrap();
944 assert!(sense.is_ok());
945 }
946
947 #[test]
948 fn test_inquiry_data_parsing() {
949 let mut raw = [0u8; 36];
950 raw[0] = 0x00; raw[1] = 0x80; raw[2] = 0x05; raw[8..16].copy_from_slice(b"VERIDIAN");
955 raw[16..32].copy_from_slice(b"USB DISK ");
957 raw[32..36].copy_from_slice(b"1.00");
959
960 let inquiry = InquiryData::from_bytes(&raw).unwrap();
961 assert_eq!(inquiry.device_type, 0x00);
962 assert!(inquiry.removable);
963 assert_eq!(inquiry.version, 0x05);
964 assert_eq!(&inquiry.vendor, b"VERIDIAN");
965 assert_eq!(&inquiry.product, b"USB DISK ");
966 assert_eq!(&inquiry.revision, b"1.00");
967 }
968
969 #[test]
970 fn test_mass_storage_device_creation() {
971 let dev = MassStorageDevice::new(1, 0x81, 0x02);
972 assert_eq!(dev.device_address, 1);
973 assert_eq!(dev.bulk_in_ep, 0x81);
974 assert_eq!(dev.bulk_out_ep, 0x02);
975 assert_eq!(dev.lun, 0);
976 assert_eq!(dev.state, MassStorageState::Uninitialized);
977 assert_eq!(dev.cached_block_size, 0);
978 assert_eq!(dev.cached_total_blocks, 0);
979 }
980
981 #[test]
982 fn test_block_device_read_not_ready() {
983 let dev = MassStorageDevice::new(1, 0x81, 0x02);
984 let mut buf = [0u8; 512];
985 let result = dev.read_blocks(0, 1, &mut buf);
986 assert!(result.is_err()); }
988
989 #[test]
990 fn test_block_device_write_not_ready() {
991 let dev = MassStorageDevice::new(1, 0x81, 0x02);
992 let buf = [0u8; 512];
993 let result = dev.write_blocks(0, 1, &buf);
994 assert!(result.is_err()); }
996
997 #[test]
998 fn test_block_device_read_ready() {
999 let mut dev = MassStorageDevice::new(1, 0x81, 0x02);
1000 dev.state = MassStorageState::Ready;
1001 dev.cached_block_size = 512;
1002 dev.cached_total_blocks = 1024;
1003
1004 let mut buf = [0xFFu8; 512];
1005 let result = dev.read_blocks(0, 1, &mut buf);
1006 assert!(result.is_ok());
1007 assert_eq!(result.unwrap(), 512);
1008 }
1009
1010 #[test]
1011 fn test_block_device_write_ready() {
1012 let mut dev = MassStorageDevice::new(1, 0x81, 0x02);
1013 dev.state = MassStorageState::Ready;
1014 dev.cached_block_size = 512;
1015 dev.cached_total_blocks = 1024;
1016
1017 let buf = [0xAAu8; 512];
1018 let result = dev.write_blocks(0, 1, &buf);
1019 assert!(result.is_ok());
1020 assert_eq!(result.unwrap(), 512);
1021 }
1022
1023 #[test]
1024 fn test_block_device_buffer_too_small() {
1025 let mut dev = MassStorageDevice::new(1, 0x81, 0x02);
1026 dev.state = MassStorageState::Ready;
1027 dev.cached_block_size = 512;
1028 dev.cached_total_blocks = 1024;
1029
1030 let mut buf = [0u8; 256]; let result = dev.read_blocks(0, 1, &mut buf);
1032 assert!(result.is_err());
1033 }
1034
1035 #[test]
1036 fn test_block_device_lba_out_of_range() {
1037 let mut dev = MassStorageDevice::new(1, 0x81, 0x02);
1038 dev.state = MassStorageState::Ready;
1039 dev.cached_block_size = 512;
1040 dev.cached_total_blocks = 100;
1041
1042 let mut buf = [0u8; 512];
1043 let result = dev.read_blocks(100, 1, &mut buf);
1045 assert!(result.is_err());
1046 }
1047
1048 #[test]
1049 fn test_scsi_read_10_cdb() {
1050 let cdb = MassStorageDevice::build_read_10_cdb(0x00000100, 8);
1051 assert_eq!(cdb[0], 0x28); assert_eq!(cdb[2], 0x00);
1054 assert_eq!(cdb[3], 0x00);
1055 assert_eq!(cdb[4], 0x01);
1056 assert_eq!(cdb[5], 0x00);
1057 assert_eq!(cdb[7], 0x00);
1059 assert_eq!(cdb[8], 0x08);
1060 }
1061
1062 #[test]
1063 fn test_scsi_write_10_cdb() {
1064 let cdb = MassStorageDevice::build_write_10_cdb(0x00001000, 1);
1065 assert_eq!(cdb[0], 0x2A); assert_eq!(cdb[2], 0x00);
1068 assert_eq!(cdb[3], 0x00);
1069 assert_eq!(cdb[4], 0x10);
1070 assert_eq!(cdb[5], 0x00);
1071 assert_eq!(cdb[7], 0x00);
1073 assert_eq!(cdb[8], 0x01);
1074 }
1075
1076 #[test]
1077 fn test_lun_setting() {
1078 let mut dev = MassStorageDevice::new(1, 0x81, 0x02);
1079 assert_eq!(dev.lun, 0);
1080 dev.set_lun(3);
1081 assert_eq!(dev.lun, 3);
1082 }
1083
1084 #[test]
1085 fn test_cbw_lun_masking() {
1086 let command = [0x00; 6]; let cbw = CommandBlockWrapper::new(1, 0, CBW_DIRECTION_OUT, 0xFF, &command);
1088 assert_eq!(cbw.lun, 0x0F); }
1090
1091 #[test]
1092 fn test_csw_from_bytes_invalid_signature() {
1093 let mut bytes = [0u8; 13];
1094 bytes[0] = 0x00; let result = CommandStatusWrapper::from_bytes(&bytes);
1096 assert!(result.is_err());
1097 }
1098
1099 #[test]
1100 fn test_multi_block_read() {
1101 let mut dev = MassStorageDevice::new(1, 0x81, 0x02);
1102 dev.state = MassStorageState::Ready;
1103 dev.cached_block_size = 512;
1104 dev.cached_total_blocks = 2048;
1105
1106 let mut buf = [0u8; 4096]; let result = dev.read_blocks(0, 8, &mut buf);
1108 assert!(result.is_ok());
1109 assert_eq!(result.unwrap(), 4096);
1110 }
1111}