aboutsummaryrefslogtreecommitdiffstats
path: root/usbh/src/lib.rs
diff options
context:
space:
mode:
authorBrian Cully <bjc@kublai.com>2019-07-27 14:52:27 -0400
committerBrian Cully <bjc@kublai.com>2019-07-27 14:52:27 -0400
commite0a9f75354564b22ef41b4a3a58e5ff321a3fc25 (patch)
treef6a1c4b5d9000c5ddc657e44ca2ec60a1aea3d9a /usbh/src/lib.rs
parent4421c02a3e98d8b9e3af8db207dfeb9d276e2962 (diff)
downloadsamd21-demo-e0a9f75354564b22ef41b4a3a58e5ff321a3fc25.tar.gz
samd21-demo-e0a9f75354564b22ef41b4a3a58e5ff321a3fc25.zip
WIP: we have lights on the keyboard!
Diffstat (limited to 'usbh/src/lib.rs')
-rwxr-xr-xusbh/src/lib.rs87
1 files changed, 66 insertions, 21 deletions
diff --git a/usbh/src/lib.rs b/usbh/src/lib.rs
index 8c19a3c..63b5581 100755
--- a/usbh/src/lib.rs
+++ b/usbh/src/lib.rs
@@ -1,9 +1,11 @@
#![no_std]
#![allow(dead_code)]
+mod device;
mod pipe;
mod usbproto;
+use device::DeviceTable;
use pipe::{DataBuf, PipeErr, PipeTable, USBPipeType, USBToken};
use rb::{Reader, RingBuffer, Writer};
use usbproto::*;
@@ -55,7 +57,6 @@ enum TaskState {
Steady(SteadyState),
}
-const MAX_DEVICES: usize = 16;
const SETTLE_DELAY: usize = 205; // Delay in sec/1024
const NAK_LIMIT: usize = 15;
@@ -78,6 +79,8 @@ where
// register.
pipe_table: PipeTable,
+ devices: DeviceTable,
+
// need sof 1kHz pad?
_sof_pad: gpio::Pa23<gpio::PfG>,
_dm_pad: gpio::Pa24<gpio::PfG>,
@@ -104,13 +107,18 @@ where
millis: &'static F,
) -> (Self, impl FnMut()) {
let (eventr, mut eventw) = unsafe { EVENTS.split() };
+
let mut rc = Self {
usb: usb,
+
events: eventr,
task_state: TaskState::Detached(DetachedState::Initialize),
delay: 0,
+
pipe_table: PipeTable::new(),
+ devices: DeviceTable::new(),
+
_sof_pad: sof_pin.into_function_g(port),
_dm_pad: dm_pin.into_function_g(port),
_dp_pad: dp_pin.into_function_g(port),
@@ -265,9 +273,7 @@ where
}
}
- fn poll_devices(&mut self) {
- for _ in 0..MAX_DEVICES {}
- }
+ fn poll_devices(&mut self) {}
fn fsm(&mut self) {
// respond to events from interrupt.
@@ -353,10 +359,7 @@ where
}
fn configure_dev(&mut self, _parent: u32, _port: u32, _low_speed: u32) -> Result<(), PipeErr> {
- // addr: 0x20007774
- let tmp: USBDeviceDescriptor = Default::default();
- // addr: 0x20007788
- let mut vol_descr = ::vcell::VolatileCell::new(tmp);
+ let mut vol_descr = ::vcell::VolatileCell::<USBDeviceDescriptor>::new(Default::default());
self.control_req(
0,
0,
@@ -373,7 +376,7 @@ where
// Assign address to this device and:
// - Stash bMaxPacketSize
// Then SET_ADDRESS(newAddr)
- let new_address: u8 = 1;
+ let new_address: u8 = 5;
debug!("Setting address to {}.", new_address);
self.control_req(
0,
@@ -388,26 +391,62 @@ where
let until = (self.millis)() + 300;
while (self.millis)() < until {}
- debug!("getting config with array");
- //let tmp: USBConfigurationDescriptor = Default::default();
- let mut tmp: [u8; 9] = [0; 9];
- //let vol_descr = ::vcell::VolatileCell::new(tmp);
+ // 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::GetConfiguration,
- WValue::from((0, 0)),
+ USBRequest::GetDescriptor,
+ WValue::from((0, USBDescriptor::Device as u8)),
0,
- Some(DataBuf::from(&mut tmp)),
+ 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);
- //let desc = vol_descr.get();
- debug!("cdesc.len: {}, type: {}", tmp[0], tmp[1]);
+ // 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 = 0;
+ let conf: u8 = 1;
self.control_req(
new_address,
0,
@@ -439,6 +478,9 @@ where
assert!(b.len <= 65_535);
}
+ // Pipe data toggles for control pipes defined in SAMD21 data
+ // sheet ยง32.6.3.9
+
/*
* Setup stage.
*/
@@ -453,6 +495,7 @@ where
},
};
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),
@@ -463,6 +506,7 @@ where
/*
* Data stage.
*/
+ pipe.dtgl_set();
if let Some(b) = buf {
match bm_request_type.direction() {
USBSetupDirection::DeviceToHost => {
@@ -480,9 +524,10 @@ where
/*
* Status stage.
*/
+ pipe.dtgl_set();
pipe.desc.bank0.pcksize.write(|w| {
- // FIXME: see note in `Pipe.send`.
- unsafe { w.bits(0) }
+ unsafe { w.byte_count().bits(0) };
+ unsafe { w.multi_packet_size().bits(0) }
});
// PSTATUSSET.DTGL set -- TODO: figure out if this is