mirror of
https://github.com/ferrous-systems/embedded-trainings-2020.git
synced 2024-09-29 06:41:54 +00:00
93 lines
5.3 KiB
Markdown
93 lines
5.3 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
|
||
|
|
||
|
Section 9.4.7, Set Configuration, of the USB spec describes how to handle this request but below you can find a summary:
|
||
|
|
||
|
- 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 the requested configuration value is 0 (`None` in the `usb` API) then stay in the `Address` state
|
||
|
- if the requested configuration value is non-zero and valid (was previously reported in a configuration descriptor) then move to the `Configured` state
|
||
|
- if the requested configuration value is not valid then stall the endpoint
|
||
|
|
||
|
- If the device is in the `Configured` state, then
|
||
|
- if the requested configuration value is 0 (`None` in the `usb` API) then return to the `Address` state
|
||
|
- if the requested configuration value is non-zero and valid (was previously reported in a configuration descriptor) then move to the `Configured` state with the new configuration value
|
||
|
- if the requested configuration value 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
|
||
|
|
||
|
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 next to this README):
|
||
|
|
||
|
- `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`.
|