diff options
| -rw-r--r-- | embassy-usb/src/control.rs | 23 | ||||
| -rw-r--r-- | embassy-usb/src/lib.rs | 77 |
2 files changed, 63 insertions, 37 deletions
diff --git a/embassy-usb/src/control.rs b/embassy-usb/src/control.rs index 19c2c6776..b5077c732 100644 --- a/embassy-usb/src/control.rs +++ b/embassy-usb/src/control.rs | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | use core::mem; | 1 | use core::mem; |
| 2 | 2 | ||
| 3 | use crate::DEFAULT_ALTERNATE_SETTING; | ||
| 4 | |||
| 3 | use super::types::*; | 5 | use super::types::*; |
| 4 | 6 | ||
| 5 | /// Control request type. | 7 | /// Control request type. |
| @@ -153,6 +155,7 @@ pub trait ControlHandler { | |||
| 153 | /// * `req` - The request from the SETUP packet. | 155 | /// * `req` - The request from the SETUP packet. |
| 154 | /// * `data` - The data from the request. | 156 | /// * `data` - The data from the request. |
| 155 | fn control_out(&mut self, req: Request, data: &[u8]) -> OutResponse { | 157 | fn control_out(&mut self, req: Request, data: &[u8]) -> OutResponse { |
| 158 | let _ = (req, data); | ||
| 156 | OutResponse::Rejected | 159 | OutResponse::Rejected |
| 157 | } | 160 | } |
| 158 | 161 | ||
| @@ -165,6 +168,26 @@ pub trait ControlHandler { | |||
| 165 | /// | 168 | /// |
| 166 | /// * `req` - The request from the SETUP packet. | 169 | /// * `req` - The request from the SETUP packet. |
| 167 | fn control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> { | 170 | fn control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> { |
| 171 | let _ = (req, buf); | ||
| 168 | InResponse::Rejected | 172 | InResponse::Rejected |
| 169 | } | 173 | } |
| 174 | |||
| 175 | fn set_interface(&mut self, alternate_setting: u16) -> OutResponse { | ||
| 176 | if alternate_setting == u16::from(DEFAULT_ALTERNATE_SETTING) { | ||
| 177 | OutResponse::Accepted | ||
| 178 | } else { | ||
| 179 | OutResponse::Rejected | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 183 | fn get_interface<'a>(&'a mut self, buf: &'a mut [u8]) -> InResponse<'a> { | ||
| 184 | buf[0] = DEFAULT_ALTERNATE_SETTING; | ||
| 185 | InResponse::Accepted(&buf[0..1]) | ||
| 186 | } | ||
| 187 | |||
| 188 | fn get_status<'a>(&'a mut self, buf: &'a mut [u8]) -> InResponse { | ||
| 189 | let status: u16 = 0; | ||
| 190 | buf[0..2].copy_from_slice(&status.to_le_bytes()); | ||
| 191 | InResponse::Accepted(&buf[0..2]) | ||
| 192 | } | ||
| 170 | } | 193 | } |
diff --git a/embassy-usb/src/lib.rs b/embassy-usb/src/lib.rs index a4b7dda30..cbb909244 100644 --- a/embassy-usb/src/lib.rs +++ b/embassy-usb/src/lib.rs | |||
| @@ -155,7 +155,14 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 155 | async fn handle_control_out(&mut self, req: Request) { | 155 | async fn handle_control_out(&mut self, req: Request) { |
| 156 | const CONFIGURATION_NONE_U16: u16 = CONFIGURATION_NONE as u16; | 156 | const CONFIGURATION_NONE_U16: u16 = CONFIGURATION_NONE as u16; |
| 157 | const CONFIGURATION_VALUE_U16: u16 = CONFIGURATION_VALUE as u16; | 157 | const CONFIGURATION_VALUE_U16: u16 = CONFIGURATION_VALUE as u16; |
| 158 | const DEFAULT_ALTERNATE_SETTING_U16: u16 = DEFAULT_ALTERNATE_SETTING as u16; | 158 | |
| 159 | // If the request has a data state, we must read it. | ||
| 160 | let data = if req.length > 0 { | ||
| 161 | let size = self.control.data_out(self.control_buf).await.unwrap(); | ||
| 162 | &self.control_buf[0..size] | ||
| 163 | } else { | ||
| 164 | &[] | ||
| 165 | }; | ||
| 159 | 166 | ||
| 160 | match (req.request_type, req.recipient) { | 167 | match (req.request_type, req.recipient) { |
| 161 | (RequestType::Standard, Recipient::Device) => match (req.request, req.value) { | 168 | (RequestType::Standard, Recipient::Device) => match (req.request, req.value) { |
| @@ -186,13 +193,6 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 186 | }, | 193 | }, |
| 187 | _ => self.control.reject(), | 194 | _ => self.control.reject(), |
| 188 | }, | 195 | }, |
| 189 | (RequestType::Standard, Recipient::Interface) => match (req.request, req.value) { | ||
| 190 | (Request::SET_INTERFACE, DEFAULT_ALTERNATE_SETTING_U16) => { | ||
| 191 | // TODO: do something when alternate settings are implemented | ||
| 192 | self.control.accept(); | ||
| 193 | } | ||
| 194 | _ => self.control.reject(), | ||
| 195 | }, | ||
| 196 | (RequestType::Standard, Recipient::Endpoint) => match (req.request, req.value) { | 196 | (RequestType::Standard, Recipient::Endpoint) => match (req.request, req.value) { |
| 197 | (Request::SET_FEATURE, Request::FEATURE_ENDPOINT_HALT) => { | 197 | (Request::SET_FEATURE, Request::FEATURE_ENDPOINT_HALT) => { |
| 198 | let ep_addr = ((req.index as u8) & 0x8f).into(); | 198 | let ep_addr = ((req.index as u8) & 0x8f).into(); |
| @@ -206,24 +206,26 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 206 | } | 206 | } |
| 207 | _ => self.control.reject(), | 207 | _ => self.control.reject(), |
| 208 | }, | 208 | }, |
| 209 | (RequestType::Class, Recipient::Interface) => { | 209 | (_, Recipient::Interface) => { |
| 210 | let data = if req.length > 0 { | ||
| 211 | let size = self.control.data_out(self.control_buf).await.unwrap(); | ||
| 212 | &self.control_buf[0..size] | ||
| 213 | } else { | ||
| 214 | &[] | ||
| 215 | }; | ||
| 216 | |||
| 217 | let handler = self | 210 | let handler = self |
| 218 | .interfaces | 211 | .interfaces |
| 219 | .iter_mut() | 212 | .iter_mut() |
| 220 | .find(|(i, _)| req.index == *i as _) | 213 | .find(|(i, _)| req.index == *i as _) |
| 221 | .map(|(_, h)| h); | 214 | .map(|(_, h)| h); |
| 215 | |||
| 222 | match handler { | 216 | match handler { |
| 223 | Some(handler) => match handler.control_out(req, data) { | 217 | Some(handler) => { |
| 224 | OutResponse::Accepted => return self.control.accept(), | 218 | let response = match (req.request_type, req.request) { |
| 225 | OutResponse::Rejected => return self.control.reject(), | 219 | (RequestType::Standard, Request::SET_INTERFACE) => { |
| 226 | }, | 220 | handler.set_interface(req.value) |
| 221 | } | ||
| 222 | _ => handler.control_out(req, data), | ||
| 223 | }; | ||
| 224 | match response { | ||
| 225 | OutResponse::Accepted => self.control.accept(), | ||
| 226 | OutResponse::Rejected => self.control.reject(), | ||
| 227 | } | ||
| 228 | } | ||
| 227 | None => self.control.reject(), | 229 | None => self.control.reject(), |
| 228 | } | 230 | } |
| 229 | } | 231 | } |
| @@ -256,18 +258,6 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 256 | } | 258 | } |
| 257 | _ => self.control.reject(), | 259 | _ => self.control.reject(), |
| 258 | }, | 260 | }, |
| 259 | (RequestType::Standard, Recipient::Interface) => match req.request { | ||
| 260 | Request::GET_STATUS => { | ||
| 261 | let status: u16 = 0x0000; | ||
| 262 | self.control.accept_in(&status.to_le_bytes()).await; | ||
| 263 | } | ||
| 264 | Request::GET_INTERFACE => { | ||
| 265 | // TODO: change when alternate settings are implemented | ||
| 266 | let status = DEFAULT_ALTERNATE_SETTING; | ||
| 267 | self.control.accept_in(&status.to_le_bytes()).await; | ||
| 268 | } | ||
| 269 | _ => self.control.reject(), | ||
| 270 | }, | ||
| 271 | (RequestType::Standard, Recipient::Endpoint) => match req.request { | 261 | (RequestType::Standard, Recipient::Endpoint) => match req.request { |
| 272 | Request::GET_STATUS => { | 262 | Request::GET_STATUS => { |
| 273 | let ep_addr: EndpointAddress = ((req.index as u8) & 0x8f).into(); | 263 | let ep_addr: EndpointAddress = ((req.index as u8) & 0x8f).into(); |
| @@ -279,17 +269,30 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 279 | } | 269 | } |
| 280 | _ => self.control.reject(), | 270 | _ => self.control.reject(), |
| 281 | }, | 271 | }, |
| 282 | (RequestType::Class, Recipient::Interface) => { | 272 | (_, Recipient::Interface) => { |
| 283 | let handler = self | 273 | let handler = self |
| 284 | .interfaces | 274 | .interfaces |
| 285 | .iter_mut() | 275 | .iter_mut() |
| 286 | .find(|(i, _)| req.index == *i as _) | 276 | .find(|(i, _)| req.index == *i as _) |
| 287 | .map(|(_, h)| h); | 277 | .map(|(_, h)| h); |
| 278 | |||
| 288 | match handler { | 279 | match handler { |
| 289 | Some(handler) => match handler.control_in(req, self.control_buf) { | 280 | Some(handler) => { |
| 290 | InResponse::Accepted(data) => self.control.accept_in(data).await, | 281 | let response = match (req.request_type, req.request) { |
| 291 | InResponse::Rejected => self.control.reject(), | 282 | (RequestType::Standard, Request::GET_STATUS) => { |
| 292 | }, | 283 | handler.get_status(self.control_buf) |
| 284 | } | ||
| 285 | (RequestType::Standard, Request::GET_INTERFACE) => { | ||
| 286 | handler.get_interface(self.control_buf) | ||
| 287 | } | ||
| 288 | _ => handler.control_in(req, self.control_buf), | ||
| 289 | }; | ||
| 290 | |||
| 291 | match response { | ||
| 292 | InResponse::Accepted(data) => self.control.accept_in(data).await, | ||
| 293 | InResponse::Rejected => self.control.reject(), | ||
| 294 | } | ||
| 295 | } | ||
| 293 | None => self.control.reject(), | 296 | None => self.control.reject(), |
| 294 | } | 297 | } |
| 295 | } | 298 | } |
