Skip to content

Commit 59e6cab

Browse files
committed
Cache configuration descriptor
We use it to open endpoints as they are used. Fetching the descriptor as needed can cause issues with devices that we're expecting a control packet while another transaction was ongoing. Specifically, a usb thumb drive didn't expect a control transaction while doing a SCSI transaction. This PR also aborts transactions on timeout or ctrl-c interrupt. It doesn't always recover though...
1 parent 9cc4b4c commit 59e6cab

File tree

4 files changed

+33
-18
lines changed

4 files changed

+33
-18
lines changed

locale/circuitpython.pot

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1473,6 +1473,10 @@ msgstr ""
14731473
msgid "No capture in progress"
14741474
msgstr ""
14751475

1476+
#: shared-module/usb/core/Device.c
1477+
msgid "No configuration set"
1478+
msgstr ""
1479+
14761480
#: shared-bindings/_bleio/PacketBuffer.c
14771481
msgid "No connection: length cannot be determined"
14781482
msgstr ""

shared-bindings/usb/core/Device.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(usb_core_device_get_manufacturer_obj, usb_core_device_
123123
MP_PROPERTY_GETTER(usb_core_device_manufacturer_obj,
124124
(mp_obj_t)&usb_core_device_get_manufacturer_obj);
125125

126-
//| def set_configuration(self, configuration=None):
126+
//| def set_configuration(self, configuration=1):
127127
//| """Set the active configuration.
128128
//|
129129
//| The configuration parameter is the bConfigurationValue field of the
@@ -136,7 +136,7 @@ MP_PROPERTY_GETTER(usb_core_device_manufacturer_obj,
136136
STATIC mp_obj_t usb_core_device_set_configuration(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
137137
enum { ARG_configuration };
138138
static const mp_arg_t allowed_args[] = {
139-
{ MP_QSTR_configuration, MP_ARG_INT, {.u_int = 0x100} },
139+
{ MP_QSTR_configuration, MP_ARG_INT, {.u_int = 1} },
140140
};
141141
usb_core_device_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
142142
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];

shared-module/usb/core/Device.c

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -132,13 +132,23 @@ mp_obj_t common_hal_usb_core_device_get_manufacturer(usb_core_device_obj_t *self
132132
}
133133

134134
void common_hal_usb_core_device_set_configuration(usb_core_device_obj_t *self, mp_int_t configuration) {
135-
if (configuration == 0x100) {
136-
tusb_desc_configuration_t desc;
137-
if (!tuh_descriptor_get_configuration(self->device_number, 0, &desc, sizeof(desc), _transfer_done_cb, 0) ||
138-
!_wait_for_callback()) {
139-
return;
140-
}
141-
configuration = desc.bConfigurationValue;
135+
// We assume that the config index is one less than the value.
136+
uint8_t config_index = configuration - 1;
137+
// Get the configuration descriptor and cache it. We'll use it later to open
138+
// endpoints.
139+
140+
// Get only the config descriptor first.
141+
tusb_desc_configuration_t desc;
142+
if (!tuh_descriptor_get_configuration(self->device_number, config_index, &desc, sizeof(desc), _transfer_done_cb, 0) ||
143+
!_wait_for_callback()) {
144+
return;
145+
}
146+
147+
// Get the config descriptor plus interfaces and endpoints.
148+
self->configuration_descriptor = m_realloc(self->configuration_descriptor, desc.wTotalLength);
149+
if (!tuh_descriptor_get_configuration(self->device_number, config_index, self->configuration_descriptor, desc.wTotalLength, _transfer_done_cb, 0) ||
150+
!_wait_for_callback()) {
151+
return;
142152
}
143153
tuh_configuration_set(self->device_number, configuration, _transfer_done_cb, 0);
144154
_wait_for_callback();
@@ -159,6 +169,7 @@ STATIC size_t _xfer(tuh_xfer_t *xfer, mp_int_t timeout) {
159169
RUN_BACKGROUND_TASKS;
160170
}
161171
if (mp_hal_is_interrupted()) {
172+
tuh_edpt_abort_xfer(xfer->daddr, xfer->ep_addr);
162173
return 0;
163174
}
164175
xfer_result_t result = _xfer_result;
@@ -167,6 +178,7 @@ STATIC size_t _xfer(tuh_xfer_t *xfer, mp_int_t timeout) {
167178
mp_raise_usb_core_USBError(translate("Pipe error"));
168179
}
169180
if (result == 0xff) {
181+
tuh_edpt_abort_xfer(xfer->daddr, xfer->ep_addr);
170182
mp_raise_usb_core_USBTimeoutError();
171183
}
172184
if (result == XFER_RESULT_SUCCESS) {
@@ -191,17 +203,13 @@ STATIC bool _open_endpoint(usb_core_device_obj_t *self, mp_int_t endpoint) {
191203
return true;
192204
}
193205

194-
// Fetch the full configuration descriptor and search for the endpoint's descriptor.
195-
uint8_t desc_buf[128];
196-
if (!tuh_descriptor_get_configuration(self->device_number, self->configuration_index, &desc_buf, sizeof(desc_buf), _transfer_done_cb, 0) ||
197-
!_wait_for_callback()) {
198-
return false;
206+
if (self->configuration_descriptor == NULL) {
207+
mp_raise_usb_core_USBError(translate("No configuration set"));
199208
}
200-
tusb_desc_configuration_t *desc_cfg = (tusb_desc_configuration_t *)desc_buf;
209+
210+
tusb_desc_configuration_t *desc_cfg = (tusb_desc_configuration_t *)self->configuration_descriptor;
201211

202212
uint32_t total_length = tu_le16toh(desc_cfg->wTotalLength);
203-
// Cap to the buffer size we requested.
204-
total_length = MIN(total_length, sizeof(desc_buf));
205213
uint8_t const *desc_end = ((uint8_t const *)desc_cfg) + total_length;
206214
uint8_t const *p_desc = tu_desc_next(desc_cfg);
207215

@@ -287,6 +295,7 @@ mp_int_t common_hal_usb_core_device_ctrl_transfer(usb_core_device_obj_t *self,
287295
RUN_BACKGROUND_TASKS;
288296
}
289297
if (mp_hal_is_interrupted()) {
298+
tuh_edpt_abort_xfer(xfer.daddr, xfer.ep_addr);
290299
return 0;
291300
}
292301
xfer_result_t result = _xfer_result;
@@ -295,6 +304,7 @@ mp_int_t common_hal_usb_core_device_ctrl_transfer(usb_core_device_obj_t *self,
295304
mp_raise_usb_core_USBError(translate("Pipe error"));
296305
}
297306
if (result == 0xff) {
307+
tuh_edpt_abort_xfer(xfer.daddr, xfer.ep_addr);
298308
mp_raise_usb_core_USBTimeoutError();
299309
}
300310
if (result == XFER_RESULT_SUCCESS) {

shared-module/usb/core/Device.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@
3232
typedef struct {
3333
mp_obj_base_t base;
3434
uint8_t device_number;
35-
uint8_t configuration_index; // not number
35+
uint8_t configuration_index; // not bConfigurationValue
36+
uint8_t *configuration_descriptor; // Contains the length of the all descriptors.
3637
uint8_t open_endpoints[8];
3738
} usb_core_device_obj_t;
3839

0 commit comments

Comments
 (0)