From 35cfd10b6a22816dbf55fe960abf61986a746b1b Mon Sep 17 00:00:00 2001 From: Brian Cully Date: Sun, 28 Jul 2019 07:23:28 -0400 Subject: WIP: read keyboard report (doesn't work) --- usbh/src/device.rs | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++--- usbh/src/pipe.rs | 4 ++++ 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 -- cgit v1.2.3