mirror of
https://github.com/ferrous-systems/embedded-trainings-2020.git
synced 2025-01-10 08:15:36 +00:00
Merge pull request #15 from ferrous-systems/usb_set_address
pre-implement USB SET_ADDRESS request handling
This commit is contained in:
commit
2dd5d8d73f
9 changed files with 236 additions and 148 deletions
|
@ -256,10 +256,12 @@ So that's what we'll do here. In the `advanced/common/usb` folder you'll find st
|
||||||
|
|
||||||
To sum up the work to do here:
|
To sum up the work to do here:
|
||||||
|
|
||||||
1. write a SETUP data parser in `advanced/common/usb`. You only need to handle the GET_DESCRIPTOR request and make the `get_descriptor_device` test pass for now.
|
1. write a SETUP data parser in `advanced/common/usb`. You only need to handle the GET_DESCRIPTOR request and make the `get_descriptor_device` test pass for now. Note that the parser already handles SET_ADDRESS requests.
|
||||||
|
|
||||||
2. modify `usb-1` to read (USBD registers) and parse the SETUP data when the EPSETUP event is received.
|
2. modify `usb-1` to read (USBD registers) and parse the SETUP data when the EPSETUP event is received.
|
||||||
|
|
||||||
|
> Note: If you're using a Mac, you need to catch `SetAddress` requests returned by the parser as these are sent before the first GetDescriptor request. You can handle them by doing nothing.
|
||||||
|
|
||||||
3. when you have successfully received a GET_DESCRIPTOR request for a Device descriptor you are done and can move to the next section.
|
3. when you have successfully received a GET_DESCRIPTOR request for a Device descriptor you are done and can move to the next section.
|
||||||
|
|
||||||
Alternatively, you can start from `usb-2` instead of `usb-1`. In either case, the tasks are the same.
|
Alternatively, you can start from `usb-2` instead of `usb-1`. In either case, the tasks are the same.
|
||||||
|
@ -269,6 +271,7 @@ If you are logging like the `usb-2` starter code does then you should see an out
|
||||||
``` console
|
``` console
|
||||||
INFO:usb_2 -- USB: UsbReset @ 438.842772ms
|
INFO:usb_2 -- USB: UsbReset @ 438.842772ms
|
||||||
INFO:usb_2 -- USB: UsbEp0Setup @ 514.984128ms
|
INFO:usb_2 -- USB: UsbEp0Setup @ 514.984128ms
|
||||||
|
...
|
||||||
INFO:usb_2 -- SETUP: bmrequesttype: 128, brequest: 6, wlength: 64, windex: 0, wvalue: 256
|
INFO:usb_2 -- SETUP: bmrequesttype: 128, brequest: 6, wlength: 64, windex: 0, wvalue: 256
|
||||||
INFO:usb_2 -- GET_DESCRIPTOR Device [length=64]
|
INFO:usb_2 -- GET_DESCRIPTOR Device [length=64]
|
||||||
INFO:usb_2 -- Goal reached; move to the next section
|
INFO:usb_2 -- Goal reached; move to the next section
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
//! Some USB 2.0 data types
|
//! Some USB 2.0 data types
|
||||||
// NOTE this is a solution to exercise `usb-2`
|
// NOTE this is a solution to exercise `usb-3`
|
||||||
|
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[cfg(TODO)]
|
|
||||||
use core::num::NonZeroU8;
|
use core::num::NonZeroU8;
|
||||||
|
|
||||||
|
/// Device address assigned by the host; will be in the range 1..=127
|
||||||
|
pub type Address = NonZeroU8;
|
||||||
|
|
||||||
/// Standard USB request
|
/// Standard USB request
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub enum Request {
|
pub enum Request {
|
||||||
|
@ -22,10 +24,9 @@ pub enum Request {
|
||||||
|
|
||||||
/// SET_ADDRESS
|
/// SET_ADDRESS
|
||||||
// see section 9.4.6 of the USB specification
|
// see section 9.4.6 of the USB specification
|
||||||
#[cfg(TODO)]
|
|
||||||
SetAddress {
|
SetAddress {
|
||||||
/// New device address, in the range `1..=127`
|
/// New device address, in the range `1..=127`
|
||||||
address: Option<NonZeroU8>,
|
address: Option<Address>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// SET_CONFIGURATION
|
/// SET_CONFIGURATION
|
||||||
|
@ -50,7 +51,8 @@ impl Request {
|
||||||
windex: u16,
|
windex: u16,
|
||||||
wlength: u16,
|
wlength: u16,
|
||||||
) -> Result<Self, ()> {
|
) -> Result<Self, ()> {
|
||||||
// see table 9-4
|
// see table 9-4 (USB specification)
|
||||||
|
const SET_ADDRESS: u8 = 5;
|
||||||
const GET_DESCRIPTOR: u8 = 6;
|
const GET_DESCRIPTOR: u8 = 6;
|
||||||
|
|
||||||
if bmrequesttype == 0b10000000 && brequest == GET_DESCRIPTOR {
|
if bmrequesttype == 0b10000000 && brequest == GET_DESCRIPTOR {
|
||||||
|
@ -75,6 +77,18 @@ impl Request {
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
} else if bmrequesttype == 0b00000000 && brequest == SET_ADDRESS {
|
||||||
|
// Set the device address for all future accesses.
|
||||||
|
// (Needed to successfully init when conected to Apple devices)
|
||||||
|
// Section 9.4.6 Set Address of the USB specification explains which values for wvalue,
|
||||||
|
// windex and wlength are valid.
|
||||||
|
if wvalue < 128 && windex == 0 && wlength == 0 {
|
||||||
|
Ok(Request::SetAddress {
|
||||||
|
address: NonZeroU8::new(wvalue as u8),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
@ -97,7 +111,6 @@ pub enum Descriptor {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#[cfg(TODO)]
|
|
||||||
use core::num::NonZeroU8;
|
use core::num::NonZeroU8;
|
||||||
|
|
||||||
use crate::{Descriptor, Request};
|
use crate::{Descriptor, Request};
|
||||||
|
@ -122,23 +135,6 @@ mod tests {
|
||||||
// ^^^^
|
// ^^^^
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn get_descriptor_configuration() {
|
|
||||||
// OK: GET_DESCRIPTOR Configuration 0 [length=9]
|
|
||||||
assert_eq!(
|
|
||||||
Request::parse(0b1000_0000, 0x06, 0x02_00, 0, 9),
|
|
||||||
Ok(Request::GetDescriptor {
|
|
||||||
descriptor: Descriptor::Configuration { index: 0 },
|
|
||||||
length: 9
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
// has language ID but shouldn't
|
|
||||||
assert!(Request::parse(0b1000_0000, 0x06, 0x02_00, 1033, 9).is_err());
|
|
||||||
// ^^^^
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(TODO)]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn set_address() {
|
fn set_address() {
|
||||||
// OK: SET_ADDRESS 16
|
// OK: SET_ADDRESS 16
|
||||||
|
@ -168,6 +164,22 @@ mod tests {
|
||||||
// ^
|
// ^
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_descriptor_configuration() {
|
||||||
|
// OK: GET_DESCRIPTOR Configuration 0 [length=9]
|
||||||
|
assert_eq!(
|
||||||
|
Request::parse(0b1000_0000, 0x06, 0x02_00, 0, 9),
|
||||||
|
Ok(Request::GetDescriptor {
|
||||||
|
descriptor: Descriptor::Configuration { index: 0 },
|
||||||
|
length: 9
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// has language ID but shouldn't
|
||||||
|
assert!(Request::parse(0b1000_0000, 0x06, 0x02_00, 1033, 9).is_err());
|
||||||
|
// ^^^^
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(TODO)]
|
#[cfg(TODO)]
|
||||||
#[test]
|
#[test]
|
||||||
fn set_configuration() {
|
fn set_configuration() {
|
||||||
|
|
|
@ -5,9 +5,11 @@
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[cfg(TODO)]
|
|
||||||
use core::num::NonZeroU8;
|
use core::num::NonZeroU8;
|
||||||
|
|
||||||
|
/// Device address assigned by the host; will be in the range 1..=127
|
||||||
|
pub type Address = NonZeroU8;
|
||||||
|
|
||||||
/// Standard USB request
|
/// Standard USB request
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub enum Request {
|
pub enum Request {
|
||||||
|
@ -22,10 +24,9 @@ pub enum Request {
|
||||||
|
|
||||||
/// SET_ADDRESS
|
/// SET_ADDRESS
|
||||||
// see section 9.4.6 of the USB specification
|
// see section 9.4.6 of the USB specification
|
||||||
#[cfg(TODO)]
|
|
||||||
SetAddress {
|
SetAddress {
|
||||||
/// New device address, in the range `1..=127`
|
/// New device address, in the range `1..=127`
|
||||||
address: Option<NonZeroU8>,
|
address: Option<Address>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// SET_CONFIGURATION
|
/// SET_CONFIGURATION
|
||||||
|
@ -50,17 +51,24 @@ impl Request {
|
||||||
windex: u16,
|
windex: u16,
|
||||||
wlength: u16,
|
wlength: u16,
|
||||||
) -> Result<Self, ()> {
|
) -> Result<Self, ()> {
|
||||||
// see table 9-4
|
// see table 9-4 (USB specification)
|
||||||
|
const SET_ADDRESS: u8 = 5;
|
||||||
const GET_DESCRIPTOR: u8 = 6;
|
const GET_DESCRIPTOR: u8 = 6;
|
||||||
|
|
||||||
|
|
||||||
if bmrequesttype == 0b10000000 && brequest == GET_DESCRIPTOR {
|
if bmrequesttype == 0b10000000 && brequest == GET_DESCRIPTOR {
|
||||||
// see table 9-5
|
// see table 9-5
|
||||||
const DEVICE: u8 = 1;
|
const DEVICE: u8 = 1;
|
||||||
|
|
||||||
|
// 1. get descriptor type and descriptor index from wValue
|
||||||
let desc_ty = (wvalue >> 8) as u8;
|
let desc_ty = (wvalue >> 8) as u8;
|
||||||
let desc_index = wvalue as u8;
|
let desc_index = wvalue as u8;
|
||||||
let langid = windex;
|
let langid = windex;
|
||||||
|
|
||||||
|
// 2. confirm that the descriptor
|
||||||
|
// - is of type DEVICE and
|
||||||
|
// - has descriptor index 0 (i.e. it is the first implemented descriptor for this type) and
|
||||||
|
// - has wIndex 0 (i.e. no language ID since it's not a string descriptor)
|
||||||
if desc_ty == DEVICE && desc_index == 0 && langid == 0 {
|
if desc_ty == DEVICE && desc_index == 0 && langid == 0 {
|
||||||
Ok(Request::GetDescriptor {
|
Ok(Request::GetDescriptor {
|
||||||
descriptor: Descriptor::Device,
|
descriptor: Descriptor::Device,
|
||||||
|
@ -69,6 +77,18 @@ impl Request {
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
} else if bmrequesttype == 0b00000000 && brequest == SET_ADDRESS {
|
||||||
|
// Set the device address for all future accesses.
|
||||||
|
// (Needed to successfully init when conected to Apple devices)
|
||||||
|
// Section 9.4.6 Set Address of the USB specification explains which values for wvalue,
|
||||||
|
// windex and wlength are valid.
|
||||||
|
if wvalue < 128 && windex == 0 && wlength == 0 {
|
||||||
|
Ok(Request::SetAddress {
|
||||||
|
address: NonZeroU8::new(wvalue as u8),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
@ -92,7 +112,6 @@ pub enum Descriptor {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#[cfg(TODO)]
|
|
||||||
use core::num::NonZeroU8;
|
use core::num::NonZeroU8;
|
||||||
|
|
||||||
use crate::{Descriptor, Request};
|
use crate::{Descriptor, Request};
|
||||||
|
@ -117,24 +136,6 @@ mod tests {
|
||||||
// ^^^^
|
// ^^^^
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(TODO)]
|
|
||||||
#[test]
|
|
||||||
fn get_descriptor_configuration() {
|
|
||||||
// OK: GET_DESCRIPTOR Configuration 0 [length=9]
|
|
||||||
assert_eq!(
|
|
||||||
Request::parse(0b1000_0000, 0x06, 0x02_00, 0, 9),
|
|
||||||
Ok(Request::GetDescriptor {
|
|
||||||
descriptor: Descriptor::Configuration { index: 0 },
|
|
||||||
length: 9
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
// has language ID but shouldn't
|
|
||||||
assert!(Request::parse(0b1000_0000, 0x06, 0x02_00, 1033, 9).is_err());
|
|
||||||
// ^^^^
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(TODO)]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn set_address() {
|
fn set_address() {
|
||||||
// OK: SET_ADDRESS 16
|
// OK: SET_ADDRESS 16
|
||||||
|
@ -164,6 +165,23 @@ mod tests {
|
||||||
// ^
|
// ^
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(TODO)]
|
||||||
|
#[test]
|
||||||
|
fn get_descriptor_configuration() {
|
||||||
|
// OK: GET_DESCRIPTOR Configuration 0 [length=9]
|
||||||
|
assert_eq!(
|
||||||
|
Request::parse(0b1000_0000, 0x06, 0x02_00, 0, 9),
|
||||||
|
Ok(Request::GetDescriptor {
|
||||||
|
descriptor: Descriptor::Configuration { index: 0 },
|
||||||
|
length: 9
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// has language ID but shouldn't
|
||||||
|
assert!(Request::parse(0b1000_0000, 0x06, 0x02_00, 1033, 9).is_err());
|
||||||
|
// ^^^^
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(TODO)]
|
#[cfg(TODO)]
|
||||||
#[test]
|
#[test]
|
||||||
fn set_configuration() {
|
fn set_configuration() {
|
||||||
|
|
|
@ -4,9 +4,11 @@
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[cfg(TODO)]
|
|
||||||
use core::num::NonZeroU8;
|
use core::num::NonZeroU8;
|
||||||
|
|
||||||
|
/// Device address assigned by the host; will be in the range 1..=127
|
||||||
|
pub type Address = NonZeroU8;
|
||||||
|
|
||||||
/// Standard USB request
|
/// Standard USB request
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub enum Request {
|
pub enum Request {
|
||||||
|
@ -21,10 +23,9 @@ pub enum Request {
|
||||||
|
|
||||||
/// SET_ADDRESS
|
/// SET_ADDRESS
|
||||||
// see section 9.4.6 of the USB specification
|
// see section 9.4.6 of the USB specification
|
||||||
#[cfg(TODO)]
|
|
||||||
SetAddress {
|
SetAddress {
|
||||||
/// New device address, in the range `1..=127`
|
/// New device address, in the range `1..=127`
|
||||||
address: Option<NonZeroU8>,
|
address: Option<Address>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// SET_CONFIGURATION
|
/// SET_CONFIGURATION
|
||||||
|
@ -43,15 +44,40 @@ impl Request {
|
||||||
/// Returns `Err` if the SETUP data doesn't match a supported standard request
|
/// Returns `Err` if the SETUP data doesn't match a supported standard request
|
||||||
// see section 9.4 of the USB specification; in particular tables 9-3, 9-4 and 9-5
|
// see section 9.4 of the USB specification; in particular tables 9-3, 9-4 and 9-5
|
||||||
pub fn parse(
|
pub fn parse(
|
||||||
_bmrequesttype: u8,
|
bmrequesttype: u8,
|
||||||
_brequest: u8,
|
brequest: u8,
|
||||||
_wvalue: u16,
|
wvalue: u16,
|
||||||
_windex: u16,
|
windex: u16,
|
||||||
_wlength: u16,
|
wlength: u16,
|
||||||
) -> Result<Self, ()> {
|
) -> Result<Self, ()> {
|
||||||
// FIXME
|
// see table 9-4 (USB specification)
|
||||||
|
const SET_ADDRESS: u8 = 5;
|
||||||
|
|
||||||
|
// TODO implement another branch handling GET_DESCRIPTOR requests:
|
||||||
|
|
||||||
|
// 1. get descriptor type and descriptor index from wValue
|
||||||
|
|
||||||
|
// 2. confirm that the descriptor
|
||||||
|
// - is of type DEVICE and
|
||||||
|
// - has descriptor index 0 (i.e. it is the first implemented descriptor for this type) and
|
||||||
|
// - has wIndex 0 (i.e. no language ID since it's not a string descriptor)
|
||||||
|
|
||||||
|
if bmrequesttype == 0b00000000 && brequest == SET_ADDRESS {
|
||||||
|
// Set the device address for all future accesses.
|
||||||
|
// (Needed to successfully init when conected to Apple devices)
|
||||||
|
// Section 9.4.6 Set Address of the USB specification explains which values for wvalue,
|
||||||
|
// windex and wlength are valid.
|
||||||
|
if wvalue < 128 && windex == 0 && wlength == 0 {
|
||||||
|
Ok(Request::SetAddress {
|
||||||
|
address: NonZeroU8::new(wvalue as u8),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Descriptor types that appear in GET_DESCRIPTOR requests
|
/// Descriptor types that appear in GET_DESCRIPTOR requests
|
||||||
|
@ -71,7 +97,6 @@ pub enum Descriptor {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#[cfg(TODO)]
|
|
||||||
use core::num::NonZeroU8;
|
use core::num::NonZeroU8;
|
||||||
|
|
||||||
use crate::{Descriptor, Request};
|
use crate::{Descriptor, Request};
|
||||||
|
@ -96,24 +121,6 @@ mod tests {
|
||||||
// ^^^^
|
// ^^^^
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(TODO)]
|
|
||||||
#[test]
|
|
||||||
fn get_descriptor_configuration() {
|
|
||||||
// OK: GET_DESCRIPTOR Configuration 0 [length=9]
|
|
||||||
assert_eq!(
|
|
||||||
Request::parse(0b1000_0000, 0x06, 0x02_00, 0, 9),
|
|
||||||
Ok(Request::GetDescriptor {
|
|
||||||
descriptor: Descriptor::Configuration { index: 0 },
|
|
||||||
length: 9
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
// has language ID but shouldn't
|
|
||||||
assert!(Request::parse(0b1000_0000, 0x06, 0x02_00, 1033, 9).is_err());
|
|
||||||
// ^^^^
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(TODO)]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn set_address() {
|
fn set_address() {
|
||||||
// OK: SET_ADDRESS 16
|
// OK: SET_ADDRESS 16
|
||||||
|
@ -143,6 +150,23 @@ mod tests {
|
||||||
// ^
|
// ^
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(TODO)]
|
||||||
|
#[test]
|
||||||
|
fn get_descriptor_configuration() {
|
||||||
|
// OK: GET_DESCRIPTOR Configuration 0 [length=9]
|
||||||
|
assert_eq!(
|
||||||
|
Request::parse(0b1000_0000, 0x06, 0x02_00, 0, 9),
|
||||||
|
Ok(Request::GetDescriptor {
|
||||||
|
descriptor: Descriptor::Configuration { index: 0 },
|
||||||
|
length: 9
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// has language ID but shouldn't
|
||||||
|
assert!(Request::parse(0b1000_0000, 0x06, 0x02_00, 1033, 9).is_err());
|
||||||
|
// ^^^^
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(TODO)]
|
#[cfg(TODO)]
|
||||||
#[test]
|
#[test]
|
||||||
fn set_configuration() {
|
fn set_configuration() {
|
||||||
|
|
|
@ -62,19 +62,23 @@ fn on_event(usbd: &USBD, event: Event) {
|
||||||
wvalue
|
wvalue
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Ok(Request::GetDescriptor { descriptor, length }) =
|
let request = Request::parse(bmrequesttype, brequest, wvalue, windex, wlength)
|
||||||
Request::parse(bmrequesttype, brequest, wvalue, windex, wlength)
|
.expect("Error parsing request");
|
||||||
|
match request {
|
||||||
|
Request::GetDescriptor { descriptor, length }
|
||||||
|
if descriptor == Descriptor::Device =>
|
||||||
{
|
{
|
||||||
match descriptor {
|
|
||||||
Descriptor::Device => {
|
|
||||||
log::info!("GET_DESCRIPTOR Device [length={}]", length);
|
log::info!("GET_DESCRIPTOR Device [length={}]", length);
|
||||||
|
|
||||||
log::info!("Goal reached; move to the next section");
|
log::info!("Goal reached; move to the next section");
|
||||||
dk::exit()
|
dk::exit()
|
||||||
}
|
}
|
||||||
|
Request::SetAddress { .. } => {
|
||||||
|
// On Mac OS you'll get this request before the GET_DESCRIPTOR request so we
|
||||||
|
// need to catch it here. We'll properly handle this request later
|
||||||
|
// but for now it's OK to do nothing.
|
||||||
}
|
}
|
||||||
} else {
|
_ => unreachable!(), // we don't handle any other Requests
|
||||||
unreachable!() // don't care about this for now
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,20 +60,26 @@ fn on_event(_usbd: &USBD, event: Event) {
|
||||||
wvalue
|
wvalue
|
||||||
);
|
);
|
||||||
|
|
||||||
// FIXME modify `advanced/common/usb` to make this work
|
let request = Request::parse(bmrequesttype, brequest, wvalue, windex, wlength)
|
||||||
if let Ok(Request::GetDescriptor { descriptor, length }) =
|
.expect("Error parsing request");
|
||||||
Request::parse(bmrequesttype, brequest, wvalue, windex, wlength)
|
match request {
|
||||||
|
Request::GetDescriptor { descriptor, length }
|
||||||
|
if descriptor == Descriptor::Device =>
|
||||||
{
|
{
|
||||||
match descriptor {
|
// TODO modify `Request::parse()` in `advanced/common/usb/lib.rs`
|
||||||
Descriptor::Device => {
|
// so that this branch is reached
|
||||||
|
|
||||||
log::info!("GET_DESCRIPTOR Device [length={}]", length);
|
log::info!("GET_DESCRIPTOR Device [length={}]", length);
|
||||||
|
|
||||||
log::info!("Goal reached; move to the next section");
|
log::info!("Goal reached; move to the next section");
|
||||||
dk::exit()
|
dk::exit()
|
||||||
}
|
}
|
||||||
|
Request::SetAddress { .. } => {
|
||||||
|
// On Mac OS you'll get this request before the GET_DESCRIPTOR request so we
|
||||||
|
// need to catch it here. We'll properly handle this request later
|
||||||
|
// but for now it's OK to do nothing.
|
||||||
}
|
}
|
||||||
} else {
|
_ => unreachable!(), // we don't handle any other Requests
|
||||||
unreachable!() // don't care about this for now
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,11 +64,12 @@ fn on_event(usbd: &USBD, ep0in: &mut Ep0In, event: Event) {
|
||||||
wvalue
|
wvalue
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Ok(Request::GetDescriptor { descriptor, length }) =
|
let request = Request::parse(bmrequesttype, brequest, wvalue, windex, wlength)
|
||||||
Request::parse(bmrequesttype, brequest, wvalue, windex, wlength)
|
.expect("Error parsing request");
|
||||||
|
match request {
|
||||||
|
Request::GetDescriptor { descriptor, length }
|
||||||
|
if descriptor == Descriptor::Device =>
|
||||||
{
|
{
|
||||||
match descriptor {
|
|
||||||
Descriptor::Device => {
|
|
||||||
log::info!("GET_DESCRIPTOR Device [length={}]", length);
|
log::info!("GET_DESCRIPTOR Device [length={}]", length);
|
||||||
|
|
||||||
let desc = usb2::device::Descriptor {
|
let desc = usb2::device::Descriptor {
|
||||||
|
@ -85,15 +86,21 @@ fn on_event(usbd: &USBD, ep0in: &mut Ep0In, event: Event) {
|
||||||
idVendor: consts::VID,
|
idVendor: consts::VID,
|
||||||
};
|
};
|
||||||
let desc_bytes = desc.bytes();
|
let desc_bytes = desc.bytes();
|
||||||
let resp =
|
let resp = &desc_bytes[..core::cmp::min(desc_bytes.len(), usize::from(length))];
|
||||||
&desc_bytes[..core::cmp::min(desc_bytes.len(), usize::from(length))];
|
|
||||||
ep0in.start(&resp, usbd);
|
ep0in.start(&resp, usbd);
|
||||||
}
|
}
|
||||||
|
Request::SetAddress { .. } => {
|
||||||
|
// On Mac OS you'll get this request before the GET_DESCRIPTOR request so we
|
||||||
|
// need to catch it here. We'll properly handle this request later
|
||||||
|
// but for now it's OK to do nothing.
|
||||||
}
|
}
|
||||||
} else {
|
_ => {
|
||||||
log::error!("unknown request (goal achieved if GET_DESCRIPTOR Device was handled)");
|
log::error!(
|
||||||
|
"unknown request (goal achieved if GET_DESCRIPTOR Device was handled)"
|
||||||
|
);
|
||||||
dk::exit()
|
dk::exit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -64,23 +64,31 @@ fn on_event(usbd: &USBD, ep0in: &mut Ep0In, event: Event) {
|
||||||
wvalue
|
wvalue
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Ok(Request::GetDescriptor { descriptor, length }) =
|
let request = Request::parse(bmrequesttype, brequest, wvalue, windex, wlength)
|
||||||
Request::parse(bmrequesttype, brequest, wvalue, windex, wlength)
|
.expect("Error parsing request");
|
||||||
|
match request {
|
||||||
|
Request::GetDescriptor { descriptor, length }
|
||||||
|
if descriptor == Descriptor::Device =>
|
||||||
{
|
{
|
||||||
match descriptor {
|
|
||||||
Descriptor::Device => {
|
|
||||||
log::info!("GET_DESCRIPTOR Device [length={}]", length);
|
log::info!("GET_DESCRIPTOR Device [length={}]", length);
|
||||||
|
|
||||||
// FIXME send back a valid device descriptor, truncated to `length` bytes
|
// TODO send back a valid device descriptor, truncated to `length` bytes
|
||||||
// let desc = usb2::device::Descriptor { .. };
|
// let desc = usb2::device::Descriptor { .. };
|
||||||
let resp = [];
|
let resp = [];
|
||||||
ep0in.start(&resp, usbd);
|
ep0in.start(&resp, usbd);
|
||||||
}
|
}
|
||||||
|
Request::SetAddress { .. } => {
|
||||||
|
// On Mac OS you'll get this request before the GET_DESCRIPTOR request so we
|
||||||
|
// need to catch it here. We'll properly handle this request later
|
||||||
|
// but for now it's OK to do nothing.
|
||||||
}
|
}
|
||||||
} else {
|
_ => {
|
||||||
log::error!("unknown request (goal achieved if GET_DESCRIPTOR Device was handled)");
|
log::error!(
|
||||||
|
"unknown request (goal achieved if GET_DESCRIPTOR Device was handled)"
|
||||||
|
);
|
||||||
dk::exit()
|
dk::exit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -77,10 +77,11 @@ fn ep0setup(usbd: &USBD, ep0in: &mut Ep0In, _state: &mut usb2::State) -> Result<
|
||||||
wvalue
|
wvalue
|
||||||
);
|
);
|
||||||
|
|
||||||
let req = Request::parse(bmrequesttype, brequest, wvalue, windex, wlength)?;
|
let request = Request::parse(bmrequesttype, brequest, wvalue, windex, wlength)
|
||||||
log::info!("{:?}", req);
|
.expect("Error parsing request");
|
||||||
|
log::info!("EP0: {:?}", request);
|
||||||
|
|
||||||
match req {
|
match request {
|
||||||
Request::GetDescriptor { descriptor, length } => match descriptor {
|
Request::GetDescriptor { descriptor, length } => match descriptor {
|
||||||
Descriptor::Device => {
|
Descriptor::Device => {
|
||||||
let desc = usb2::device::Descriptor {
|
let desc = usb2::device::Descriptor {
|
||||||
|
@ -100,12 +101,17 @@ fn ep0setup(usbd: &USBD, ep0in: &mut Ep0In, _state: &mut usb2::State) -> Result<
|
||||||
let _ = ep0in.start(&bytes[..core::cmp::min(bytes.len(), length.into())], usbd);
|
let _ = ep0in.start(&bytes[..core::cmp::min(bytes.len(), length.into())], usbd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Configuration descriptor
|
// TODO implement Configuration descriptor
|
||||||
// Descriptor::Configuration => todo!(),
|
// Descriptor::Configuration { .. } => todo!(),
|
||||||
},
|
},
|
||||||
|
Request::SetAddress { .. } => {
|
||||||
|
// On Mac OS you'll get this request before the GET_DESCRIPTOR request so we
|
||||||
|
// need to catch it here.
|
||||||
|
|
||||||
// TODO
|
// TODO: handle this request properly now.
|
||||||
// Request::SetAddress { .. } => todo!(),
|
todo!()
|
||||||
|
}
|
||||||
|
// TODO handle SET_CONFIGURATION request
|
||||||
// Request::SetConfiguration { .. } => todo!(),
|
// Request::SetConfiguration { .. } => todo!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue