aboutsummaryrefslogtreecommitdiffstats
path: root/usbh
diff options
context:
space:
mode:
authorBrian Cully <bjc@kublai.com>2019-07-28 07:23:28 -0400
committerBrian Cully <bjc@kublai.com>2019-07-28 07:23:28 -0400
commit35cfd10b6a22816dbf55fe960abf61986a746b1b (patch)
tree9ee9a4371c40f2053c49de8401a150414fc3098b /usbh
parentfab524e9e2253ab6b11b0a03bf7bf4f9435d9b37 (diff)
downloadsamd21-demo-35cfd10b6a22816dbf55fe960abf61986a746b1b.tar.gz
samd21-demo-35cfd10b6a22816dbf55fe960abf61986a746b1b.zip
WIP: read keyboard report (doesn't work)
Diffstat (limited to 'usbh')
-rw-r--r--usbh/src/device.rs67
-rw-r--r--usbh/src/pipe.rs4
2 files changed, 68 insertions, 3 deletions
diff --git a/usbh/src/device.rs b/usbh/src/device.rs
index ac48c14..f14203d 100644
--- a/usbh/src/device.rs
+++ b/usbh/src/device.rs
@@ -1,8 +1,8 @@
-use super::pipe::{DataBuf, PipeErr, PipeTable};
+use super::pipe::{DataBuf, Pipe, PipeErr, PipeTable};
use super::usbproto::*;
use core::convert::TryInto;
-use log::{debug, error, trace};
+use log::{debug, error, info, trace};
// FIXME: once again, this doesn't belong here. The issue is that
// we're using `pipe_for`, which requires it.
@@ -204,15 +204,76 @@ impl Device {
)?;
debug!(" -- configuration set");
+ debug!("+++ setting idle");
+ pipe.control_req(
+ BMRequestType::from((
+ USBSetupDirection::HostToDevice,
+ USBSetupType::Class,
+ USBSetupRecipient::Interface,
+ )),
+ USBRequest::GetInterface, // This is also idle, but can't have two enums with the same value.
+ WValue::from((0, 0)),
+ 0,
+ None,
+ self.millis,
+ )?;
+ debug!(" -- idle set");
+
+ debug!("+++ setting report");
+ let mut rep_res: u8 = 0;
+ pipe.control_req(
+ BMRequestType::from((
+ USBSetupDirection::HostToDevice,
+ USBSetupType::Class,
+ USBSetupRecipient::Interface,
+ )),
+ USBRequest::SetConfiguration,
+ WValue::from((0, 2)),
+ 0,
+ Some(DataBuf::from(&mut rep_res)),
+ self.millis,
+ )?;
+ debug!(" -- report set: {}", rep_res);
+
self.state = FSM::Steady
}
FSM::Steady => {
- // Now we should be able to access it normally.
+ // For now, just do an IN transfer to see if we can
+ // get some keyboard reports without further setup.
+
+ // EP 1 is boot proto keyboard.
+ let mut pipe = pipe_table.pipe_for(host, self.addr, 1);
+ pipe.regs.cfg.write(|w| unsafe { w.ptype().bits(0x4) });
+ pipe.regs.statusclr.write(|w| unsafe {
+ // No function for this. FIXME: need to patch the SVD for
+ // PSTATUSCLR.DTGL at bit0. No? This is in the SVD, but
+ // not the rust output.
+ w.bits(1)
+ });
+ self.read_report(&mut pipe, 1);
+
+ // EP 2 is consumer control keys.
+ //let mut pipe = pipe_table.pipe_for(host, self.addr, 2);
+ //pipe.regs.cfg.write(|w| unsafe { w.ptype().bits(0x4) });
+ //self.read_report(&mut pipe, 2);
}
}
Ok(())
}
+
+ fn read_report(&mut self, pipe: &mut Pipe, id: u8) {
+ let mut buf: core::mem::MaybeUninit<[u8; 64]> = core::mem::MaybeUninit::uninit();
+ let mut db = DataBuf::from(&mut buf);
+ match pipe.in_transfer(&mut db, 15, self.millis) {
+ Ok(bytes_received) => {
+ let tmp = unsafe { &(buf.assume_init())[..bytes_received] };
+ info!("report {}: {:?}", id, tmp);
+ }
+
+ Err(e) => info!("error {}: {:?}", id, e),
+ }
+ }
}
pub struct Endpoint {
diff --git a/usbh/src/pipe.rs b/usbh/src/pipe.rs
index 4910c3e..e17bec5 100644
--- a/usbh/src/pipe.rs
+++ b/usbh/src/pipe.rs
@@ -36,6 +36,7 @@ pub(crate) enum PipeErr {
InvalidToken,
Stall,
TransferFail,
+ PipeErr,
Flow,
HWTimeout,
DataToggle,
@@ -356,6 +357,9 @@ impl Pipe<'_, '_> {
} else if self.regs.intflag.read().trfail().bit_is_set() {
self.regs.intflag.write(|w| w.trfail().set_bit());
Err(PipeErr::TransferFail)
+ } else if self.regs.intflag.read().perr().bit_is_set() {
+ self.regs.intflag.write(|w| w.perr().set_bit());
+ Err(PipeErr::PipeErr)
} else if self.desc.bank0.status_bk.read().errorflow().bit_is_set() {
self.desc
.bank0