From 429769f1b104a9a78542a08df0e4583069a6e4a9 Mon Sep 17 00:00:00 2001 From: Mirabellensaft Date: Wed, 21 Apr 2021 15:38:22 +0200 Subject: [PATCH] restructure assignment and information --- embedded-workshop-book/src/data-stage.md | 26 ++++++++++++++++-------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/embedded-workshop-book/src/data-stage.md b/embedded-workshop-book/src/data-stage.md index 0277231..1700fe4 100644 --- a/embedded-workshop-book/src/data-stage.md +++ b/embedded-workshop-book/src/data-stage.md @@ -2,17 +2,22 @@ The next step is to respond to the GET_DESCRIPTOR request with a device descriptor. -✅ Open the file `src/bin/usb-3.rs`. Implement the response to the GET_DESCRIPTOR request. Use the following guide for assistance. - ❗️ Keep the cable connected to the J3 port for the rest of the workshop - To do this we'll use the `dk::usb::Ep0In` abstraction -- we'll look into what the abstraction does in a future section; for now we'll just use it. +✅ Open the file `src/bin/usb-3.rs`. -An instance of this abstraction is available in the `board` value (`#[init]` function). The first step is to make this `Ep0In` instance available to the `on_event` function. +Part of this response is already implemented. We'll go through this. -The `Ep0In` API has two methods: `start` and `end` (also see their API documentation). `start` is used to start a DATA stage; this method takes a *slice of bytes* (`[u8]`) as argument; this argument is the response data. The `end` method needs to be called after `start`, when the EP0DATADONE event is raised, to complete the control transfer. `Ep0In` will automatically issue the STATUS stage that must follow the DATA stage. -To implement responding to a GET_DESCRIPTOR Device request, extend `usb-3.rs` so that it uses `Ep0In` to respond to the `GET_DESCRIPTOR Device` request (and only to that request). The response must be a device descriptor with its fields set to these values: +We'll use the `dk::usb::Ep0In` abstraction. An instance of it is available in the `board` value (`#[init]` function). The first step is to make this `Ep0In` instance available to the `on_event` function. + +The `Ep0In` API has two methods: `start` and `end`. `start` is used to start a DATA stage; this method takes a *slice of bytes* (`[u8]`) as argument; this argument is the response data. The `end` method needs to be called after `start`, when the EP0DATADONE event is raised, to complete the control transfer. `Ep0In` will automatically issue the STATUS stage that must follow the DATA stage. + +✅ Implement the EP0DATADONE event by calling the `end` method of the `EP0In` API. + +✅ Implement the response to the GET_DESCRIPTOR request. Extend `usb-3.rs` so that it uses `Ep0In` to respond to the `GET_DESCRIPTOR Device` request (and only to that request). + +**Values of the device descriptor** - `bLength = 18`, the size of the descriptor (must always be this value) - `bDescriptorType = 1`, device descriptor type (must always be this value) @@ -25,14 +30,17 @@ To implement responding to a GET_DESCRIPTOR Device request, extend `usb-3.rs` so - `bNumConfigurations = 1`, must be at least `1` so this is the minimum value >(\*) the `common` crate refers to the crate in the `advanced/common` folder. It is already part of the `firmware` crate dependencies. +**Use the `usb2::device::Descriptor` abstraction** Although you can create the device descriptor by hand as an array filled with magic values we *strongly* recommend you use the `usb2::device::Descriptor` abstraction. The crate is already in the dependency list of the project; you can open its API documentation with the following command: `cargo doc -p usb2 --open`. -> NOTE: the `usb2::device::Descriptor` struct does not have `bLength` and `bDescriptorType` fields. Those fields have fixed values according to the USB spec so you cannot modify or set them. When `bytes()` is called on the `Descriptor` value the returned array, the binary representation of the descriptor, will contain those fields set to their correct value. +**The length of the device descriptor** -Note that the device descriptor is 18 bytes long but the host may ask for fewer bytes (see `wlength` field in the SETUP data). In that case you must respond with the amount of bytes the host asked for. The opposite may also happen: `wlength` may be larger than the size of the device descriptor; in this case your answer must be 18 bytes long (do *not* pad the response with zeroes). +The `usb2::device::Descriptor` struct does not have `bLength` and `bDescriptorType` fields. Those fields have fixed values according to the USB spec so you cannot modify or set them. When `bytes()` is called on the `Descriptor` value the returned array, the binary representation of the descriptor, will contain those fields set to their correct value. -Don't forget to also handle the `EP0DATADONE` event! +The device descriptor is 18 bytes long but the host may ask for fewer bytes (see `wlength` field in the SETUP data). In that case you must respond with the amount of bytes the host asked for. The opposite may also happen: `wlength` may be larger than the size of the device descriptor; in this case your answer must be 18 bytes long (do *not* pad the response with zeroes). + +**Expected log output** Once you have successfully responded to the GET_DESCRIPTOR Device request you should get logs like these (if you are logging like `usb-3` does):