diff options
author | Brian Cully <bjc@kublai.com> | 2019-07-27 18:39:14 -0400 |
---|---|---|
committer | Brian Cully <bjc@kublai.com> | 2019-07-27 18:39:14 -0400 |
commit | 2b6941ef833cd9cfbc403d52f388065fc8d065cb (patch) | |
tree | 3177bc112c1d3ef784b3da0d66aab32c27fa18e4 /usbh/src/lib.rs | |
parent | 5759c640e06f0223e958ac49793dcf8a4af1c990 (diff) | |
download | samd21-demo-2b6941ef833cd9cfbc403d52f388065fc8d065cb.tar.gz samd21-demo-2b6941ef833cd9cfbc403d52f388065fc8d065cb.zip |
Move post-address device config to Device impl.
Diffstat (limited to 'usbh/src/lib.rs')
-rwxr-xr-x | usbh/src/lib.rs | 205 |
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. |