mirror of
https://github.com/ferrous-systems/embedded-trainings-2020.git
synced 2025-01-10 00:05:45 +00:00
get-descriptor-device.rs: add SET_ADDRESS handling; comments to solution
This commit is contained in:
parent
c3d680e76d
commit
44d3bfe32a
1 changed files with 41 additions and 23 deletions
|
@ -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() {
|
||||||
|
|
Loading…
Reference in a new issue