mirror of
https://github.com/ferrous-systems/embedded-trainings-2020.git
synced 2025-01-10 00:05:45 +00:00
first sketch: pre-impl set_address to make ws work for mac os users (works; not ported, not cleaned up)
This commit is contained in:
parent
886487dee6
commit
e5728a440f
3 changed files with 90 additions and 21 deletions
|
@ -4,7 +4,6 @@
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[cfg(TODO)]
|
|
||||||
use core::num::NonZeroU8;
|
use core::num::NonZeroU8;
|
||||||
|
|
||||||
/// Standard USB request
|
/// Standard USB request
|
||||||
|
@ -21,7 +20,6 @@ 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<NonZeroU8>,
|
||||||
|
@ -43,14 +41,48 @@ 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)
|
||||||
Err(())
|
const SET_ADDRESS: u8 = 5;
|
||||||
|
const GET_DESCRIPTOR: u8 = 6; // todo deleteme
|
||||||
|
|
||||||
|
// TODO löschen und durch instructions ersetzen
|
||||||
|
if bmrequesttype == 0b10000000 && brequest == GET_DESCRIPTOR {
|
||||||
|
// see table 9-5
|
||||||
|
const DEVICE: u8 = 1;
|
||||||
|
|
||||||
|
let desc_ty = (wvalue >> 8) as u8;
|
||||||
|
let desc_index = wvalue as u8;
|
||||||
|
let langid = windex;
|
||||||
|
|
||||||
|
if desc_ty == DEVICE && desc_index == 0 && langid == 0 {
|
||||||
|
Ok(Request::GetDescriptor {
|
||||||
|
descriptor: Descriptor::Device,
|
||||||
|
length: wlength,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
} else if bmrequesttype == 0b00000000 && brequest == SET_ADDRESS {
|
||||||
|
|
||||||
|
// Set the device address for all future accesses.
|
||||||
|
// Needed to successfully init when using Apple devices.
|
||||||
|
if wvalue < 128 && windex == 0 && wlength == 0 {
|
||||||
|
Ok(Request::SetAddress {
|
||||||
|
address: NonZeroU8::new(wvalue as u8),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,9 +101,27 @@ pub enum Descriptor {
|
||||||
// there are even more descriptor types but we don't need to support them
|
// there are even more descriptor types but we don't need to support them
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Device address assigned by the host; will be in the range 1..=127
|
||||||
|
pub type Address = NonZeroU8;
|
||||||
|
/// The state of the USB device
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
pub enum DeviceState {
|
||||||
|
/// The default state
|
||||||
|
Default,
|
||||||
|
/// The address-ed state
|
||||||
|
Address(Address),
|
||||||
|
/// The configured state
|
||||||
|
Configured {
|
||||||
|
/// The address of the device
|
||||||
|
address: Address,
|
||||||
|
/// The configuration value
|
||||||
|
value: NonZeroU8,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[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};
|
||||||
|
|
|
@ -6,11 +6,12 @@ use dk::{
|
||||||
usbd::{self, Event},
|
usbd::{self, Event},
|
||||||
};
|
};
|
||||||
use panic_log as _; // panic handler
|
use panic_log as _; // panic handler
|
||||||
use usb::{Descriptor, Request};
|
use usb::{Descriptor, Request, DeviceState};
|
||||||
|
|
||||||
#[rtic::app(device = dk)]
|
#[rtic::app(device = dk)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
|
state: DeviceState,
|
||||||
usbd: USBD,
|
usbd: USBD,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,20 +21,24 @@ const APP: () = {
|
||||||
|
|
||||||
usbd::init(board.power, &board.usbd);
|
usbd::init(board.power, &board.usbd);
|
||||||
|
|
||||||
init::LateResources { usbd: board.usbd }
|
init::LateResources {
|
||||||
|
usbd: board.usbd,
|
||||||
|
state: DeviceState::Default,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(binds = USBD, resources = [usbd])]
|
#[task(binds = USBD, resources = [state, usbd])]
|
||||||
fn main(cx: main::Context) {
|
fn main(cx: main::Context) {
|
||||||
let usbd = cx.resources.usbd;
|
let usbd = cx.resources.usbd;
|
||||||
|
let state = cx.resources.state; // used to store the device address sent by the host
|
||||||
|
|
||||||
while let Some(event) = usbd::next_event(usbd) {
|
while let Some(event) = usbd::next_event(usbd) {
|
||||||
on_event(usbd, event)
|
on_event(usbd, state, event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fn on_event(usbd: &USBD, event: Event) {
|
fn on_event(usbd: &USBD, state: &mut DeviceState, event: Event) {
|
||||||
log::info!("USB: {:?} @ {:?}", event, dk::uptime());
|
log::info!("USB: {:?} @ {:?}", event, dk::uptime());
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
|
@ -62,16 +67,31 @@ fn on_event(usbd: &USBD, event: Event) {
|
||||||
wvalue
|
wvalue
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Ok(Request::GetDescriptor { descriptor, length }) =
|
// todo handle less indentedly?
|
||||||
Request::parse(bmrequesttype, brequest, wvalue, windex, wlength)
|
if let Ok(request) = Request::parse(bmrequesttype, brequest, wvalue, windex, wlength) {
|
||||||
{
|
match request {
|
||||||
match descriptor {
|
Request::GetDescriptor { descriptor, length }
|
||||||
Descriptor::Device => {
|
if 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 { address } => {
|
||||||
|
log::info!("SETUP: device state is {:?}", state);
|
||||||
|
|
||||||
|
// todo hide this in a helper?
|
||||||
|
// todo check for state configured -> err
|
||||||
|
if let Some(address) = address {
|
||||||
|
log::info!("SETUP: assigning address {}", address);
|
||||||
|
*state = DeviceState::Address(address);
|
||||||
|
} else {
|
||||||
|
log::info!("SETUP: address was None; assigning Default");
|
||||||
|
*state = DeviceState::Default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unreachable!(), // we don't handle any other Requests
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unreachable!() // don't care about this for now
|
unreachable!() // don't care about this for now
|
||||||
|
|
|
@ -103,7 +103,6 @@ fn ep0setup(usbd: &USBD, ep0in: &mut Ep0In, _state: &mut usb2::State) -> Result<
|
||||||
// TODO Configuration descriptor
|
// TODO Configuration descriptor
|
||||||
// Descriptor::Configuration => todo!(),
|
// Descriptor::Configuration => todo!(),
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
// Request::SetAddress { .. } => todo!(),
|
// Request::SetAddress { .. } => todo!(),
|
||||||
// Request::SetConfiguration { .. } => todo!(),
|
// Request::SetConfiguration { .. } => todo!(),
|
||||||
|
|
Loading…
Reference in a new issue