diff --git a/embassy-usb/src/class/msc/transport/bulk_only/mod.rs b/embassy-usb/src/class/msc/transport/bulk_only/mod.rs index 1e02468f..4ea7bcbf 100644 --- a/embassy-usb/src/class/msc/transport/bulk_only/mod.rs +++ b/embassy-usb/src/class/msc/transport/bulk_only/mod.rs @@ -9,9 +9,10 @@ use self::cbw::CommandBlockWrapper; use self::csw::{CommandStatus, CommandStatusWrapper}; use super::{CommandError, CommandSetHandler, DataPipeError, DataPipeIn, DataPipeOut}; use crate::class::msc::{MscProtocol, USB_CLASS_MSC}; -use crate::control::{ControlHandler, InResponse, Request, RequestType}; +use crate::control::{InResponse, Request, RequestType}; use crate::driver::Driver; -use crate::Builder; +use crate::types::InterfaceNumber; +use crate::{Builder, Handler}; const REQ_GET_MAX_LUN: u8 = 0xFE; const REQ_BULK_ONLY_RESET: u8 = 0xFF; @@ -30,21 +31,26 @@ impl Default for State { pub struct Control { max_lun: u8, + if_num: InterfaceNumber, } -impl ControlHandler for Control { - fn control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> { +impl Handler for Control { + fn control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> Option> { + if req.index != self.if_num.0 as u16 { + return None; + } + match (req.request_type, req.request) { (RequestType::Class, REQ_GET_MAX_LUN) => { debug!("REQ_GET_MAX_LUN"); buf[0] = self.max_lun; - InResponse::Accepted(&buf[..1]) + Some(InResponse::Accepted(&buf[..1])) } (RequestType::Class, REQ_BULK_ONLY_RESET) => { debug!("REQ_BULK_ONLY_RESET"); - InResponse::Accepted(&[]) + Some(InResponse::Accepted(&[])) } - _ => InResponse::Rejected, + _ => Some(InResponse::Rejected), } } } @@ -60,20 +66,25 @@ impl<'d, D: Driver<'d>, C: CommandSetHandler> BulkOnlyTransport<'d, D, C> { pub fn new(builder: &mut Builder<'d, D>, state: &'d mut State, max_packet_size: u16, handler: C) -> Self { assert!(C::MAX_LUN < 16, "BulkOnlyTransport supports maximum 16 LUNs"); - let control = state.control.write(Control { max_lun: C::MAX_LUN }); - let subclass = C::MSC_SUBCLASS as u8; let mut func = builder.function(USB_CLASS_MSC, subclass, MscProtocol::BulkOnlyTransport as _); // Control interface let mut iface = func.interface(); - iface.handler(control); - let mut alt = iface.alt_setting(USB_CLASS_MSC, subclass, MscProtocol::BulkOnlyTransport as _); + let mut alt = iface.alt_setting(USB_CLASS_MSC, subclass, MscProtocol::BulkOnlyTransport as _, None); let read_ep = alt.endpoint_bulk_out(max_packet_size); let write_ep = alt.endpoint_bulk_in(max_packet_size); + let control = state.control.write(Control { + max_lun: C::MAX_LUN, + if_num: iface.interface_number(), + }); + + drop(func); + builder.handler(control); + Self { read_ep, write_ep, diff --git a/examples/stm32f4/src/bin/usb_msc_sdmmc.rs b/examples/stm32f4/src/bin/usb_msc_sdmmc.rs index 877a8927..e29850ca 100644 --- a/examples/stm32f4/src/bin/usb_msc_sdmmc.rs +++ b/examples/stm32f4/src/bin/usb_msc_sdmmc.rs @@ -5,10 +5,10 @@ use core::cell::RefCell; -use defmt::*; +use defmt::{panic, *}; use embassy_executor::Spawner; use embassy_stm32::peripherals::{DMA2_CH6, SDIO}; -use embassy_stm32::sdmmc::{self, Sdmmc}; +use embassy_stm32::sdmmc::Sdmmc; use embassy_stm32::time::{mhz, Hertz}; use embassy_stm32::usb_otg::Driver; use embassy_stm32::{interrupt, Config}; @@ -44,6 +44,13 @@ impl<'d> BlockDevice for SdmmcBlockDevice<'d> { } async fn read_block(&self, lba: u32, block: &mut [u8]) -> Result<(), BlockDeviceError> { + if block.as_ptr() as usize % 4 != 0 { + panic!("Invalid block alignment for SDMMC"); + } + + let block: &mut [u8; BLOCK_SIZE] = block.try_into().unwrap(); + let block = unsafe { core::mem::transmute(block) }; + self.sdmmc.borrow_mut().read_block(lba, block).await.map_err(|e| { error!("SDMMC read error: {:?}", e); BlockDeviceError::ReadError @@ -51,6 +58,13 @@ impl<'d> BlockDevice for SdmmcBlockDevice<'d> { } async fn write_block(&mut self, lba: u32, block: &[u8]) -> Result<(), BlockDeviceError> { + if block.as_ptr() as usize % 4 != 0 { + panic!("Invalid block alignment for SDMMC"); + } + + let block: &[u8; BLOCK_SIZE] = block.try_into().unwrap(); + let block = unsafe { core::mem::transmute(block) }; + self.sdmmc.borrow_mut().write_block(lba, block).await.map_err(|e| { error!("SDMMC write error: {:?}", e); BlockDeviceError::WriteError @@ -71,8 +85,6 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(config); - let mut config = sdmmc::Config::default(); - // config.data_transfer_timeout = 20_000_000; let mut sdmmc = Sdmmc::new_4bit( p.SDIO, interrupt::take!(SDIO), @@ -83,7 +95,7 @@ async fn main(_spawner: Spawner) { p.PC9, p.PC10, p.PC11, - config, + Default::default(), ); sdmmc.init_card(SDIO_FREQ).await.expect("SD card init failed"); @@ -123,7 +135,6 @@ async fn main(_spawner: Spawner) { &mut config_descriptor, &mut bos_descriptor, &mut control_buf, - None, ); // Create SCSI target for our block device