Add handlers for standard reqs to ControlHandler
This commit is contained in:
parent
13370c28db
commit
d40ebcccf6
2 changed files with 63 additions and 37 deletions
|
@ -1,5 +1,7 @@
|
||||||
use core::mem;
|
use core::mem;
|
||||||
|
|
||||||
|
use crate::DEFAULT_ALTERNATE_SETTING;
|
||||||
|
|
||||||
use super::types::*;
|
use super::types::*;
|
||||||
|
|
||||||
/// Control request type.
|
/// Control request type.
|
||||||
|
@ -153,6 +155,7 @@ pub trait ControlHandler {
|
||||||
/// * `req` - The request from the SETUP packet.
|
/// * `req` - The request from the SETUP packet.
|
||||||
/// * `data` - The data from the request.
|
/// * `data` - The data from the request.
|
||||||
fn control_out(&mut self, req: Request, data: &[u8]) -> OutResponse {
|
fn control_out(&mut self, req: Request, data: &[u8]) -> OutResponse {
|
||||||
|
let _ = (req, data);
|
||||||
OutResponse::Rejected
|
OutResponse::Rejected
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,6 +168,26 @@ pub trait ControlHandler {
|
||||||
///
|
///
|
||||||
/// * `req` - The request from the SETUP packet.
|
/// * `req` - The request from the SETUP packet.
|
||||||
fn control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> {
|
fn control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> {
|
||||||
|
let _ = (req, buf);
|
||||||
InResponse::Rejected
|
InResponse::Rejected
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_interface(&mut self, alternate_setting: u16) -> OutResponse {
|
||||||
|
if alternate_setting == u16::from(DEFAULT_ALTERNATE_SETTING) {
|
||||||
|
OutResponse::Accepted
|
||||||
|
} else {
|
||||||
|
OutResponse::Rejected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_interface<'a>(&'a mut self, buf: &'a mut [u8]) -> InResponse<'a> {
|
||||||
|
buf[0] = DEFAULT_ALTERNATE_SETTING;
|
||||||
|
InResponse::Accepted(&buf[0..1])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_status<'a>(&'a mut self, buf: &'a mut [u8]) -> InResponse {
|
||||||
|
let status: u16 = 0;
|
||||||
|
buf[0..2].copy_from_slice(&status.to_le_bytes());
|
||||||
|
InResponse::Accepted(&buf[0..2])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,7 +155,14 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
|
||||||
async fn handle_control_out(&mut self, req: Request) {
|
async fn handle_control_out(&mut self, req: Request) {
|
||||||
const CONFIGURATION_NONE_U16: u16 = CONFIGURATION_NONE as u16;
|
const CONFIGURATION_NONE_U16: u16 = CONFIGURATION_NONE as u16;
|
||||||
const CONFIGURATION_VALUE_U16: u16 = CONFIGURATION_VALUE as u16;
|
const CONFIGURATION_VALUE_U16: u16 = CONFIGURATION_VALUE as u16;
|
||||||
const DEFAULT_ALTERNATE_SETTING_U16: u16 = DEFAULT_ALTERNATE_SETTING as u16;
|
|
||||||
|
// If the request has a data state, we must read it.
|
||||||
|
let data = if req.length > 0 {
|
||||||
|
let size = self.control.data_out(self.control_buf).await.unwrap();
|
||||||
|
&self.control_buf[0..size]
|
||||||
|
} else {
|
||||||
|
&[]
|
||||||
|
};
|
||||||
|
|
||||||
match (req.request_type, req.recipient) {
|
match (req.request_type, req.recipient) {
|
||||||
(RequestType::Standard, Recipient::Device) => match (req.request, req.value) {
|
(RequestType::Standard, Recipient::Device) => match (req.request, req.value) {
|
||||||
|
@ -186,13 +193,6 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
|
||||||
},
|
},
|
||||||
_ => self.control.reject(),
|
_ => self.control.reject(),
|
||||||
},
|
},
|
||||||
(RequestType::Standard, Recipient::Interface) => match (req.request, req.value) {
|
|
||||||
(Request::SET_INTERFACE, DEFAULT_ALTERNATE_SETTING_U16) => {
|
|
||||||
// TODO: do something when alternate settings are implemented
|
|
||||||
self.control.accept();
|
|
||||||
}
|
|
||||||
_ => self.control.reject(),
|
|
||||||
},
|
|
||||||
(RequestType::Standard, Recipient::Endpoint) => match (req.request, req.value) {
|
(RequestType::Standard, Recipient::Endpoint) => match (req.request, req.value) {
|
||||||
(Request::SET_FEATURE, Request::FEATURE_ENDPOINT_HALT) => {
|
(Request::SET_FEATURE, Request::FEATURE_ENDPOINT_HALT) => {
|
||||||
let ep_addr = ((req.index as u8) & 0x8f).into();
|
let ep_addr = ((req.index as u8) & 0x8f).into();
|
||||||
|
@ -206,24 +206,26 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
|
||||||
}
|
}
|
||||||
_ => self.control.reject(),
|
_ => self.control.reject(),
|
||||||
},
|
},
|
||||||
(RequestType::Class, Recipient::Interface) => {
|
(_, Recipient::Interface) => {
|
||||||
let data = if req.length > 0 {
|
|
||||||
let size = self.control.data_out(self.control_buf).await.unwrap();
|
|
||||||
&self.control_buf[0..size]
|
|
||||||
} else {
|
|
||||||
&[]
|
|
||||||
};
|
|
||||||
|
|
||||||
let handler = self
|
let handler = self
|
||||||
.interfaces
|
.interfaces
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|(i, _)| req.index == *i as _)
|
.find(|(i, _)| req.index == *i as _)
|
||||||
.map(|(_, h)| h);
|
.map(|(_, h)| h);
|
||||||
|
|
||||||
match handler {
|
match handler {
|
||||||
Some(handler) => match handler.control_out(req, data) {
|
Some(handler) => {
|
||||||
OutResponse::Accepted => return self.control.accept(),
|
let response = match (req.request_type, req.request) {
|
||||||
OutResponse::Rejected => return self.control.reject(),
|
(RequestType::Standard, Request::SET_INTERFACE) => {
|
||||||
},
|
handler.set_interface(req.value)
|
||||||
|
}
|
||||||
|
_ => handler.control_out(req, data),
|
||||||
|
};
|
||||||
|
match response {
|
||||||
|
OutResponse::Accepted => self.control.accept(),
|
||||||
|
OutResponse::Rejected => self.control.reject(),
|
||||||
|
}
|
||||||
|
}
|
||||||
None => self.control.reject(),
|
None => self.control.reject(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,18 +258,6 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
|
||||||
}
|
}
|
||||||
_ => self.control.reject(),
|
_ => self.control.reject(),
|
||||||
},
|
},
|
||||||
(RequestType::Standard, Recipient::Interface) => match req.request {
|
|
||||||
Request::GET_STATUS => {
|
|
||||||
let status: u16 = 0x0000;
|
|
||||||
self.control.accept_in(&status.to_le_bytes()).await;
|
|
||||||
}
|
|
||||||
Request::GET_INTERFACE => {
|
|
||||||
// TODO: change when alternate settings are implemented
|
|
||||||
let status = DEFAULT_ALTERNATE_SETTING;
|
|
||||||
self.control.accept_in(&status.to_le_bytes()).await;
|
|
||||||
}
|
|
||||||
_ => self.control.reject(),
|
|
||||||
},
|
|
||||||
(RequestType::Standard, Recipient::Endpoint) => match req.request {
|
(RequestType::Standard, Recipient::Endpoint) => match req.request {
|
||||||
Request::GET_STATUS => {
|
Request::GET_STATUS => {
|
||||||
let ep_addr: EndpointAddress = ((req.index as u8) & 0x8f).into();
|
let ep_addr: EndpointAddress = ((req.index as u8) & 0x8f).into();
|
||||||
|
@ -279,17 +269,30 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
|
||||||
}
|
}
|
||||||
_ => self.control.reject(),
|
_ => self.control.reject(),
|
||||||
},
|
},
|
||||||
(RequestType::Class, Recipient::Interface) => {
|
(_, Recipient::Interface) => {
|
||||||
let handler = self
|
let handler = self
|
||||||
.interfaces
|
.interfaces
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|(i, _)| req.index == *i as _)
|
.find(|(i, _)| req.index == *i as _)
|
||||||
.map(|(_, h)| h);
|
.map(|(_, h)| h);
|
||||||
|
|
||||||
match handler {
|
match handler {
|
||||||
Some(handler) => match handler.control_in(req, self.control_buf) {
|
Some(handler) => {
|
||||||
InResponse::Accepted(data) => self.control.accept_in(data).await,
|
let response = match (req.request_type, req.request) {
|
||||||
InResponse::Rejected => self.control.reject(),
|
(RequestType::Standard, Request::GET_STATUS) => {
|
||||||
},
|
handler.get_status(self.control_buf)
|
||||||
|
}
|
||||||
|
(RequestType::Standard, Request::GET_INTERFACE) => {
|
||||||
|
handler.get_interface(self.control_buf)
|
||||||
|
}
|
||||||
|
_ => handler.control_in(req, self.control_buf),
|
||||||
|
};
|
||||||
|
|
||||||
|
match response {
|
||||||
|
InResponse::Accepted(data) => self.control.accept_in(data).await,
|
||||||
|
InResponse::Rejected => self.control.reject(),
|
||||||
|
}
|
||||||
|
}
|
||||||
None => self.control.reject(),
|
None => self.control.reject(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue