aboutsummaryrefslogtreecommitdiffstats
path: root/usbh/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'usbh/src/lib.rs')
-rwxr-xr-xusbh/src/lib.rs205
1 files changed, 27 insertions, 178 deletions
diff --git a/usbh/src/lib.rs b/usbh/src/lib.rs
index 63b5581..38d1327 100755
--- a/usbh/src/lib.rs
+++ b/usbh/src/lib.rs
@@ -6,7 +6,7 @@ mod pipe;
mod usbproto;
use device::DeviceTable;
-use pipe::{DataBuf, PipeErr, PipeTable, USBPipeType, USBToken};
+use pipe::{DataBuf, PipeErr, PipeTable, USBPipeType};
use rb::{Reader, RingBuffer, Writer};
use usbproto::*;
@@ -265,7 +265,6 @@ where
// };
}
- self.poll_devices();
self.fsm();
unsafe {
@@ -342,8 +341,7 @@ where
fn steady_fsm(&mut self, s: SteadyState) {
match s {
SteadyState::Configuring => {
- let low_speed = 0;
- self.task_state = match self.configure_dev(0, 0, low_speed) {
+ self.task_state = match self.configure_dev() {
Ok(_) => TaskState::Steady(SteadyState::Running),
Err(e) => {
warn!("Enumeration error: {:?}", e);
@@ -352,198 +350,49 @@ where
}
}
- SteadyState::Running => {}
+ SteadyState::Running => {
+ self.devices.run(&mut self.pipe_table, self.usb.host_mut());
+ }
SteadyState::Error => {}
}
}
- fn configure_dev(&mut self, _parent: u32, _port: u32, _low_speed: u32) -> Result<(), PipeErr> {
+ fn configure_dev(&mut self) -> Result<(), PipeErr> {
+ let mut pipe = self.pipe_table.pipe_for(self.usb.host_mut(), 0, 0);
let mut vol_descr = ::vcell::VolatileCell::<USBDeviceDescriptor>::new(Default::default());
- self.control_req(
- 0,
- 0,
+ pipe.control_req(
BMRequestType::get_descr(),
USBRequest::GetDescriptor,
WValue::from((0, USBDescriptor::Device as u8)),
0,
Some(DataBuf::from(&mut vol_descr)),
+ self.millis,
)?;
let desc = vol_descr.get();
trace!(" -- devDesc: {:?}", desc);
- // Assign address to this device and:
- // - Stash bMaxPacketSize
- // Then SET_ADDRESS(newAddr)
- let new_address: u8 = 5;
- debug!("Setting address to {}.", new_address);
- self.control_req(
- 0,
- 0,
- BMRequestType::set(),
- USBRequest::SetAddress,
- WValue::from((new_address, 0)),
- 0,
- None,
- )?;
- // Delay according to §9.2.6.3 of USB 2.0
- let until = (self.millis)() + 300;
- while (self.millis)() < until {}
-
- // Everything after this point is what linux does. So do that?
-
- // Dunno why we get the device descriptor a second time.
- trace!(
- " -- getting devDesc2 from {}:{}: {:?}",
- new_address,
- 0,
- desc
- );
- let tmp: USBDeviceDescriptor = Default::default();
- let mut vol_descr = ::vcell::VolatileCell::new(tmp);
- self.control_req(
- new_address,
- 0,
- BMRequestType::get_descr(),
- USBRequest::GetDescriptor,
- WValue::from((0, USBDescriptor::Device as u8)),
- 0,
- Some(DataBuf::from(&mut vol_descr)),
- )?;
-
- let desc = vol_descr.get();
- trace!(" -- devDesc2: {:?}", desc);
-
- // Get config descriptor with minimal data, to see how much we need to allocate for the full descriptor.
- let mut vol_descr =
- ::vcell::VolatileCell::<USBConfigurationDescriptor>::new(Default::default());
- self.control_req(
- new_address,
- 0,
- BMRequestType::get_descr(),
- USBRequest::GetDescriptor,
- WValue::from((0, USBDescriptor::Configuration as u8)),
- 0,
- Some(DataBuf::from(&mut vol_descr)),
- )?;
- let desc = vol_descr.get();
- debug!("config: {:?}", desc);
-
- // TODO: do real allocation later.
- assert!(desc.w_total_length < 64);
- let buf: [u8; 64] = [0; 64];
- let mut tmp = &buf[..desc.w_total_length as usize];
- self.control_req(
- new_address,
- 0,
- BMRequestType::get_descr(),
- USBRequest::GetDescriptor,
- WValue::from((0, USBDescriptor::Configuration as u8)),
- 0,
- Some(DataBuf::from(&mut tmp)),
- )?;
-
- // Once addressed, SET_CONFIGURATION(0)
- debug!("+++ setting configuration");
- let conf: u8 = 1;
- self.control_req(
- new_address,
- 0,
- BMRequestType::set(),
- USBRequest::SetConfiguration,
- WValue::from((conf, 0)),
- 0,
- None,
- )?;
- debug!(" -- configuration set");
-
- // Now we should be able to access it normally.
-
- Ok(())
- }
-
- fn control_req(
- &mut self,
- addr: u8,
- ep: u8,
- bm_request_type: BMRequestType,
- b_request: USBRequest,
- w_value: WValue,
- w_index: u16,
- buf: Option<DataBuf>,
- ) -> Result<(), PipeErr> {
- if let Some(ref b) = buf {
- assert!(b.ptr as usize & 0x3 == 0);
- assert!(b.len <= 65_535);
- }
-
- // Pipe data toggles for control pipes defined in SAMD21 data
- // sheet §32.6.3.9
-
- /*
- * Setup stage.
- */
- let mut setup_packet = USBSetupPacket {
- bm_request_type: bm_request_type,
- b_request: b_request,
- w_value: w_value,
- w_index: w_index,
- w_length: match buf {
- None => 0,
- Some(ref b) => b.len as u16,
- },
- };
- let mut pipe = self.pipe_table.pipe_for(self.usb.host_mut(), addr, ep);
- pipe.dtgl_clear();
- pipe.send(
- USBToken::Setup,
- &DataBuf::from(&mut setup_packet),
- NAK_LIMIT,
- self.millis,
- )?;
-
- /*
- * Data stage.
- */
- pipe.dtgl_set();
- if let Some(b) = buf {
- match bm_request_type.direction() {
- USBSetupDirection::DeviceToHost => {
- trace!("buf0: {:?}", &b);
- pipe.in_transfer(&b, NAK_LIMIT, self.millis)?;
- trace!("buf1: {:?}", &b);
- }
-
- USBSetupDirection::HostToDevice => {
- debug!("Should OUT for {}b", b.len);
- }
+ match self.devices.next(self.millis) {
+ // TODO: new error for being out of devices.
+ None => return Err(PipeErr::Other),
+ Some(device) => {
+ device.max_packet_size = desc.b_max_packet_size;
+ debug!("Setting address to {}.", device.addr);
+ pipe.control_req(
+ BMRequestType::set(),
+ USBRequest::SetAddress,
+ WValue::from((device.addr, 0)),
+ 0,
+ None,
+ self.millis,
+ )?;
+
+ // Now that the device is addressed, `Device` can handle the
+ // rest of the setup in its FSM.
+ Ok(())
}
}
-
- /*
- * Status stage.
- */
- pipe.dtgl_set();
- pipe.desc.bank0.pcksize.write(|w| {
- unsafe { w.byte_count().bits(0) };
- unsafe { w.multi_packet_size().bits(0) }
- });
-
- // PSTATUSSET.DTGL set -- TODO: figure out if this is
- // necessary.
- pipe.regs.statusset.write(|w| w.dtgl().set_bit());
-
- let token = match bm_request_type.direction() {
- USBSetupDirection::DeviceToHost => USBToken::Out,
- USBSetupDirection::HostToDevice => USBToken::In,
- };
-
- // TODO: should probably make `pipe.send` have optional
- // `DataBuf`, rather than exposing `dispatch_retries`.
- trace!("dispatching status stage");
- pipe.dispatch_retries(token, NAK_LIMIT, self.millis)?;
- Ok(())
}
// Set up a default pipe for the control endpoint 0 on pipe 0.