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...
This commit is contained in:
parent
9cc4b4cd37
commit
59e6cab252
|
@ -1473,6 +1473,10 @@ msgstr ""
|
|||
msgid "No capture in progress"
|
||||
msgstr ""
|
||||
|
||||
#: shared-module/usb/core/Device.c
|
||||
msgid "No configuration set"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/_bleio/PacketBuffer.c
|
||||
msgid "No connection: length cannot be determined"
|
||||
msgstr ""
|
||||
|
|
|
@ -123,7 +123,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(usb_core_device_get_manufacturer_obj, usb_core_device_
|
|||
MP_PROPERTY_GETTER(usb_core_device_manufacturer_obj,
|
||||
(mp_obj_t)&usb_core_device_get_manufacturer_obj);
|
||||
|
||||
//| def set_configuration(self, configuration=None):
|
||||
//| def set_configuration(self, configuration=1):
|
||||
//| """Set the active configuration.
|
||||
//|
|
||||
//| The configuration parameter is the bConfigurationValue field of the
|
||||
|
@ -136,7 +136,7 @@ MP_PROPERTY_GETTER(usb_core_device_manufacturer_obj,
|
|||
STATIC mp_obj_t usb_core_device_set_configuration(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_configuration };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_configuration, MP_ARG_INT, {.u_int = 0x100} },
|
||||
{ MP_QSTR_configuration, MP_ARG_INT, {.u_int = 1} },
|
||||
};
|
||||
usb_core_device_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
|
|
|
@ -132,13 +132,23 @@ mp_obj_t common_hal_usb_core_device_get_manufacturer(usb_core_device_obj_t *self
|
|||
}
|
||||
|
||||
void common_hal_usb_core_device_set_configuration(usb_core_device_obj_t *self, mp_int_t configuration) {
|
||||
if (configuration == 0x100) {
|
||||
tusb_desc_configuration_t desc;
|
||||
if (!tuh_descriptor_get_configuration(self->device_number, 0, &desc, sizeof(desc), _transfer_done_cb, 0) ||
|
||||
!_wait_for_callback()) {
|
||||
return;
|
||||
}
|
||||
configuration = desc.bConfigurationValue;
|
||||
// We assume that the config index is one less than the value.
|
||||
uint8_t config_index = configuration - 1;
|
||||
// Get the configuration descriptor and cache it. We'll use it later to open
|
||||
// endpoints.
|
||||
|
||||
// Get only the config descriptor first.
|
||||
tusb_desc_configuration_t desc;
|
||||
if (!tuh_descriptor_get_configuration(self->device_number, config_index, &desc, sizeof(desc), _transfer_done_cb, 0) ||
|
||||
!_wait_for_callback()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the config descriptor plus interfaces and endpoints.
|
||||
self->configuration_descriptor = m_realloc(self->configuration_descriptor, desc.wTotalLength);
|
||||
if (!tuh_descriptor_get_configuration(self->device_number, config_index, self->configuration_descriptor, desc.wTotalLength, _transfer_done_cb, 0) ||
|
||||
!_wait_for_callback()) {
|
||||
return;
|
||||
}
|
||||
tuh_configuration_set(self->device_number, configuration, _transfer_done_cb, 0);
|
||||
_wait_for_callback();
|
||||
|
@ -159,6 +169,7 @@ STATIC size_t _xfer(tuh_xfer_t *xfer, mp_int_t timeout) {
|
|||
RUN_BACKGROUND_TASKS;
|
||||
}
|
||||
if (mp_hal_is_interrupted()) {
|
||||
tuh_edpt_abort_xfer(xfer->daddr, xfer->ep_addr);
|
||||
return 0;
|
||||
}
|
||||
xfer_result_t result = _xfer_result;
|
||||
|
@ -167,6 +178,7 @@ STATIC size_t _xfer(tuh_xfer_t *xfer, mp_int_t timeout) {
|
|||
mp_raise_usb_core_USBError(translate("Pipe error"));
|
||||
}
|
||||
if (result == 0xff) {
|
||||
tuh_edpt_abort_xfer(xfer->daddr, xfer->ep_addr);
|
||||
mp_raise_usb_core_USBTimeoutError();
|
||||
}
|
||||
if (result == XFER_RESULT_SUCCESS) {
|
||||
|
@ -191,17 +203,13 @@ STATIC bool _open_endpoint(usb_core_device_obj_t *self, mp_int_t endpoint) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// Fetch the full configuration descriptor and search for the endpoint's descriptor.
|
||||
uint8_t desc_buf[128];
|
||||
if (!tuh_descriptor_get_configuration(self->device_number, self->configuration_index, &desc_buf, sizeof(desc_buf), _transfer_done_cb, 0) ||
|
||||
!_wait_for_callback()) {
|
||||
return false;
|
||||
if (self->configuration_descriptor == NULL) {
|
||||
mp_raise_usb_core_USBError(translate("No configuration set"));
|
||||
}
|
||||
tusb_desc_configuration_t *desc_cfg = (tusb_desc_configuration_t *)desc_buf;
|
||||
|
||||
tusb_desc_configuration_t *desc_cfg = (tusb_desc_configuration_t *)self->configuration_descriptor;
|
||||
|
||||
uint32_t total_length = tu_le16toh(desc_cfg->wTotalLength);
|
||||
// Cap to the buffer size we requested.
|
||||
total_length = MIN(total_length, sizeof(desc_buf));
|
||||
uint8_t const *desc_end = ((uint8_t const *)desc_cfg) + total_length;
|
||||
uint8_t const *p_desc = tu_desc_next(desc_cfg);
|
||||
|
||||
|
@ -287,6 +295,7 @@ mp_int_t common_hal_usb_core_device_ctrl_transfer(usb_core_device_obj_t *self,
|
|||
RUN_BACKGROUND_TASKS;
|
||||
}
|
||||
if (mp_hal_is_interrupted()) {
|
||||
tuh_edpt_abort_xfer(xfer.daddr, xfer.ep_addr);
|
||||
return 0;
|
||||
}
|
||||
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,
|
|||
mp_raise_usb_core_USBError(translate("Pipe error"));
|
||||
}
|
||||
if (result == 0xff) {
|
||||
tuh_edpt_abort_xfer(xfer.daddr, xfer.ep_addr);
|
||||
mp_raise_usb_core_USBTimeoutError();
|
||||
}
|
||||
if (result == XFER_RESULT_SUCCESS) {
|
||||
|
|
|
@ -32,7 +32,8 @@
|
|||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
uint8_t device_number;
|
||||
uint8_t configuration_index; // not number
|
||||
uint8_t configuration_index; // not bConfigurationValue
|
||||
uint8_t *configuration_descriptor; // Contains the length of the all descriptors.
|
||||
uint8_t open_endpoints[8];
|
||||
} usb_core_device_obj_t;
|
||||
|
||||
|
|
Loading…
Reference in New Issue