mirror of
https://github.com/ferrous-systems/embedded-trainings-2020.git
synced 2024-09-26 13:30:07 +00:00
105 lines
5.7 KiB
Markdown
105 lines
5.7 KiB
Markdown
# Getting it Configured
|
|
|
|
At this stage the device will be in the `Address` stage. It has been identified and enumerated by the host but cannot yet be used by host applications. The device must first move to the `Configured` state before the host can start, for example, HID communication or send non-standard requests over the control endpoint.
|
|
|
|
Windows and macOS will enumerate the device but not automatically configure it after enumeration. Here's what you should do to force the host to configure the device.
|
|
|
|
## Linux and Mac OS
|
|
|
|
Nothing extra needs to be done if you're working on a Linux or Mac OS host. The host will automatically send a `SET_CONFIGURATION` request so proceed to the `SET_CONFIGURATION` section to see how to handle the request.
|
|
|
|
## Windows
|
|
|
|
After getting the device enumerated and into the idle state, open the Zadig tool (covered in the setup instructions; see the top README) and use it to associate the nRF52840 USB device to the WinUSB driver. The nRF52840 will appear as a "unknown device" with a VID and PID that matches the ones defined in the `common` crate
|
|
|
|
Now modify the `print-descs` program to "open" the device -- this operation is commented out in the source code. With this modification `print-descs` will cause Windows to send a `SET_CONFIGURATION` request to configure the device. You'll need to run `print-descs` to test out the correct handling of the `SET_CONFIGURATION` request.
|
|
|
|
## SET_CONFIGURATION
|
|
|
|
The SET_CONFIGURATION request is sent by the host to configure the device. Its configuration according to section 9.4.7. of the [USB specification][usb_spec] is:
|
|
|
|
- `bmrequesttype` is **0b00000000**
|
|
- `brequest` is **9** (i.e. the SET_CONFIGURATION Request Code, see table 9-4 in the USB spec)
|
|
- `wValue` contains the requested configuration value
|
|
- `wIndex` and `wLength` are 0, there is no `wData`
|
|
|
|
[usb_spec]: https://www.usb.org/document-library/usb-20-specification
|
|
|
|
✅ To handle a SET_CONFIGURATION, do the following:
|
|
|
|
- If the device is in the `Default` state, you should stall the endpoint because the operation is not permitted in that state.
|
|
|
|
- If the device is in the `Address` state, then
|
|
- if `wValue` is 0 (`None` in the `usb` API) then stay in the `Address` state
|
|
- if `wValue` is non-zero and valid (was previously reported in a configuration descriptor) then move to the `Configured` state
|
|
- if `wValue` is not valid then stall the endpoint
|
|
|
|
- If the device is in the `Configured` state, then read the requested configuration value from `wValue`
|
|
- if `wValue` is 0 (`None` in the `usb` API) then return to the `Address` state
|
|
- if `wValue` is non-zero and valid (was previously reported in a configuration descriptor) then move to the `Configured` state with the new configuration value
|
|
- if `wValue` is not valid then stall the endpoint
|
|
|
|
In all the cases where you did not stall the endpoint (by returning `Err`) you'll need to acknowledge the request by starting a STATUS stage.
|
|
|
|
✅ This is done by writing 1 to the TASKS_EP0STATUS register.
|
|
|
|
NOTE: On Windows, you may get a `GET_STATUS` request *before* the `SET_CONFIGURATION` request and although you *should* respond to it, stalling the `GET_STATUS` request seems sufficient to get the device to the `Configured` state.
|
|
|
|
## Expected output
|
|
|
|
✅ Run the progam and check the log output.
|
|
|
|
Once you are correctly handling the `SET_CONFIGURATION` request you should get logs like these:
|
|
|
|
``` console
|
|
INFO:usb_5 -- USB: UsbReset @ 397.15576ms
|
|
INFO:usb_5 -- USB reset condition detected
|
|
INFO:usb_5 -- USB: UsbEp0Setup @ 470.00122ms
|
|
INFO:usb_5 -- EP0: GetDescriptor { descriptor: Device, length: 64 }
|
|
INFO:dk::usbd -- EP0IN: start 18B transfer
|
|
INFO:usb_5 -- USB: UsbEp0DataDone @ 470.306395ms
|
|
INFO:usb_5 -- EP0IN: transfer complete
|
|
INFO:dk::usbd -- EP0IN: transfer done
|
|
INFO:usb_5 -- USB: UsbReset @ 520.721433ms
|
|
INFO:usb_5 -- USB reset condition detected
|
|
INFO:usb_5 -- USB: UsbEp0Setup @ 593.292235ms
|
|
INFO:usb_5 -- EP0: SetAddress { address: Some(21) }
|
|
INFO:usb_5 -- USB: UsbEp0Setup @ 609.954832ms
|
|
INFO:usb_5 -- EP0: GetDescriptor { descriptor: Device, length: 18 }
|
|
INFO:dk::usbd -- EP0IN: start 18B transfer
|
|
INFO:usb_5 -- USB: UsbEp0DataDone @ 610.260008ms
|
|
INFO:usb_5 -- EP0IN: transfer complete
|
|
INFO:dk::usbd -- EP0IN: transfer done
|
|
INFO:usb_5 -- USB: UsbEp0Setup @ 610.443113ms
|
|
INFO:usb_5 -- EP0: GetDescriptor { descriptor: DeviceQualifier, length: 10 }
|
|
WARN:usb_5 -- EP0IN: stalled
|
|
INFO:usb_5 -- USB: UsbEp0Setup @ 610.809325ms
|
|
INFO:usb_5 -- EP0: GetDescriptor { descriptor: DeviceQualifier, length: 10 }
|
|
WARN:usb_5 -- EP0IN: stalled
|
|
INFO:usb_5 -- USB: UsbEp0Setup @ 611.175535ms
|
|
INFO:usb_5 -- EP0: GetDescriptor { descriptor: DeviceQualifier, length: 10 }
|
|
WARN:usb_5 -- EP0IN: stalled
|
|
INFO:usb_5 -- USB: UsbEp0Setup @ 611.511228ms
|
|
INFO:usb_5 -- EP0: GetDescriptor { descriptor: Configuration { index: 0 }, length: 9 }
|
|
INFO:dk::usbd -- EP0IN: start 9B transfer
|
|
INFO:usb_5 -- USB: UsbEp0DataDone @ 611.846922ms
|
|
INFO:usb_5 -- EP0IN: transfer complete
|
|
INFO:dk::usbd -- EP0IN: transfer done
|
|
INFO:usb_5 -- USB: UsbEp0Setup @ 612.030027ms
|
|
INFO:usb_5 -- EP0: GetDescriptor { descriptor: Configuration { index: 0 }, length: 18 }
|
|
INFO:dk::usbd -- EP0IN: start 18B transfer
|
|
INFO:usb_5 -- USB: UsbEp0DataDone @ 612.365721ms
|
|
INFO:usb_5 -- EP0IN: transfer complete
|
|
INFO:dk::usbd -- EP0IN: transfer done
|
|
INFO:usb_5 -- USB: UsbEp0Setup @ 612.640378ms
|
|
INFO:usb_5 -- EP0: SetConfiguration { value: Some(42) }
|
|
INFO:usb_5 -- entering the configured state
|
|
```
|
|
|
|
These logs are from a Linux host. You can find traces for other OSes in these files (they are in the `advanced` folder):
|
|
|
|
- `linux-configured.txt` (same logs as the ones shown above)
|
|
- `win-configured.txt`, this file only contains the logs produced by running `print-descs`
|
|
- `macos-configured.txt`
|
|
|
|
You can find a solution to this part of the exercise in `src/bin/usb-5-solution.rs`.
|