From 1bb84dfed1342427dd307a47c5914a7053fea8e4 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Thu, 16 Jul 2020 18:05:01 +0200 Subject: [PATCH] add note about bLength and bDescriptorType --- embedded-workshop-book/src/data-stage.md | 4 ++++ .../src/get-descriptor-config-response.md | 10 ++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/embedded-workshop-book/src/data-stage.md b/embedded-workshop-book/src/data-stage.md index 9be3004..9516e6b 100644 --- a/embedded-workshop-book/src/data-stage.md +++ b/embedded-workshop-book/src/data-stage.md @@ -14,6 +14,8 @@ The `Ep0In` API has two methods: `start` and `end` (also see their API documenta 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: +- `bLength = 18`, the size of the descriptor (must always be this value) +- `bDescriptorType = 1`, device descriptor type (must always be this value) - `bDeviceClass = bDeviceSubClass = bDeviceProtocol = 0`, these are unimportant for enumeration - `bMaxPacketSize0 = 64`, this is the most performant option (minimizes exchanges between the device and the host) and it's assumed by the `Ep0In` abstraction - `idVendor = consts::VID`, value expected by the `usb-list` tool (\*) @@ -26,6 +28,8 @@ To implement responding to a GET_DESCRIPTOR Device request, extend `usb-3.rs` so 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. + 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). Don't forget to also handle the `EP0DATADONE` event! diff --git a/embedded-workshop-book/src/get-descriptor-config-response.md b/embedded-workshop-book/src/get-descriptor-config-response.md index 2c0e05e..c496cbf 100644 --- a/embedded-workshop-book/src/get-descriptor-config-response.md +++ b/embedded-workshop-book/src/get-descriptor-config-response.md @@ -13,8 +13,8 @@ The configuration descriptor and one interface descriptor will be concatenated i The configuration descriptor in the response should contain these fields: -- `bLength = 9`, the size of this descriptor (see table 9-10 in the USB spec) -- `bDescriptorType = 2`, configuration descriptor (see table 9-5 in the USB spec) +- `bLength = 9`, the size of this descriptor (must always be this value) +- `bDescriptorType = 2`, configuration descriptor type (must always be this value) - `wTotalLength = 18` = one configuration descriptor (9 bytes) and one interface descriptor (9 bytes) - `bNumInterfaces = 1`, a single interface (the minimum value) - `bConfigurationValue = 42`, any non-zero value will do @@ -24,8 +24,8 @@ The configuration descriptor in the response should contain these fields: The interface descriptor in the response should contain these fields: -- `bLength = 9`, the size of this descriptor (see table 9-11 in the USB spec) -- `bDescriptorType = 4`, interface descriptor (see table 9-5 in the USB spec) +- `bLength = 9`, the size of this descriptor (must always be this value) +- `bDescriptorType = 4`, interface descriptor type (must always be this value) - `bInterfaceNumber = 0`, this is the first, and only, interface - `bAlternateSetting = 0`, alternate settings are not supported - `bNumEndpoints = 0`, no endpoint associated to this interface (other than the control endpoint) @@ -34,4 +34,6 @@ The interface descriptor in the response should contain these fields: Again, we strongly recommend that you use the `usb2::configuration::Descriptor` and `usb2::interface::Descriptor` abstractions here. Each descriptor instance can be transformed into its byte representation using the `bytes` method -- the method returns an array. To concatenate both arrays you can use an stack-allocated [`heapless::Vec`] buffer. If you haven't the `heapless` crate before you can find example usage in the the `src/bin/vec.rs` file. +> NOTE: the `usb2::configuration::Descriptor` and `usb2::interface::Descriptor` structs do 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. + [`heapless::Vec`]: https://docs.rs/heapless/0.5.5/heapless/struct.Vec.html