Skip to content

Commit 77f36df

Browse files
committed
usbd: Don't reset the transfer state when reading config descriptor.
It seems Windows may read the configuration descriptor more than once after a bus reset, so it's necessary not to clear the transfer state when this happens. The other changes are assumed to be idempotent (endpoint numbers will be re-assigned again, but they should come back the same as the last time this function was called.) Signed-off-by: Angus Gratton <angus@redyak.com.au>
1 parent f1a1101 commit 77f36df

File tree

1 file changed

+7
-6
lines changed

1 file changed

+7
-6
lines changed

micropython/usbd/device.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,9 @@ def _descriptor_config_cb(self):
172172
#
173173
# This normally only happens during enumeration, but may happen more than
174174
# once (the host will first ask for a minimum length descriptor, and then
175-
# use the length field request to request the whole thing).
175+
# use the length field request to request the whole thing). Therefore, the
176+
# behaviour must be idempotent (the same descriptor returned, and the state
177+
# unchanged by calling it.)
176178
#
177179
# Note: Currently only one configuration per device is supported.
178180

@@ -189,7 +191,6 @@ def _descriptor_config_cb(self):
189191
self._l = _STD_DESC_CONFIG_LEN
190192

191193
self._eps = {} # rebuild endpoint mapping as we enumerate each interface
192-
self._ep_cbs = {}
193194
itf_num = static.itf_max
194195
ep_num = max(static.ep_max, 1) # Endpoint 0 always reserved for control
195196

@@ -206,8 +207,9 @@ def _descriptor_config_cb(self):
206207
if dt == _STD_DESC_ENDPOINT_TYPE:
207208
ep_addr = d.b[offs + 2]
208209
self._eps[ep_addr] = itf
209-
self._ep_cbs[ep_addr] = None # no pending callback
210-
210+
if ep_addr not in self._ep_cbs:
211+
# add a callback placeholder if one doesn't already exist
212+
self._ep_cbs[ep_addr] = None
211213
# Find the next ep_num that can be used for next interface
212214
# (Note this does skip some potential EPs, as each ep_num can be both IN and OUT)
213215
ep_num = max((ep_addr & ~EP_IN_FLAG) + 1, ep_num)
@@ -336,8 +338,7 @@ def _reset_cb(self):
336338
# Callback when the USB device is reset by the host
337339

338340
# Cancel outstanding transfer callbacks
339-
for k in self._ep_cbs.keys():
340-
self._ep_cbs[k] = None
341+
self._ep_cbs = {}
341342

342343
# Allow interfaces to respond to the reset
343344
for itf in self._itfs:

0 commit comments

Comments
 (0)