diff --git a/micropython/usb/usb-device/usb/device/core.py b/micropython/usb/usb-device/usb/device/core.py index 7be09ee46..a3e603d73 100644 --- a/micropython/usb/usb-device/usb/device/core.py +++ b/micropython/usb/usb-device/usb/device/core.py @@ -3,10 +3,11 @@ # These contain the classes and utilities that are needed to # implement a USB device, not any complete USB drivers. # -# MIT license; Copyright (c) 2022-2024 Angus Gratton +# MIT license; Copyright (c) 2022-2024 Angus Gratton, 2025 Harm Lammers from micropython import const import machine import struct +import time try: from _thread import get_ident @@ -108,7 +109,6 @@ def config( # noqa: PLR0913 device_class=0, device_subclass=0, device_protocol=0, - config_str=None, max_power_ma=None, remote_wakeup=False, ): @@ -166,7 +166,11 @@ def maybe_set(value, idx): # Keep track of the interface and endpoint indexes itf_num = builtin_driver.itf_max ep_num = max(builtin_driver.ep_max, 1) # Endpoint 0 always reserved for control - while len(strs) < builtin_driver.str_max: + while ( + len(strs) < builtin_driver.str_max - 1 + ): # This is possibly unnecessary or wrong because + # https://docs.micropython.org/en/latest/library/machine.USBDevice.html + # states all string values except index 0 should be plain ASCII strs.append(None) # Reserve other string indexes used by builtin drivers initial_cfg = builtin_driver.desc_cfg or (b"\x00" * _STD_DESC_CONFIG_LEN) @@ -204,10 +208,11 @@ def maybe_set(value, idx): ) # Configuration string is optional but supported - iConfiguration = 0 if configuration_str: iConfiguration = len(strs) strs.append(configuration_str) + else: + iConfiguration = 0 if max_power_ma is not None: # Convert from mA to the units used in the descriptor @@ -665,6 +670,7 @@ def interface( bInterfaceSubClass=_INTERFACE_SUBCLASS_NONE, bInterfaceProtocol=_PROTOCOL_NONE, iInterface=0, + bAlternateSetting=0, ): # Utility function to append a standard Interface descriptor, with # the properties specified in the parameter list. @@ -680,7 +686,7 @@ def interface( _STD_DESC_INTERFACE_LEN, # bLength _STD_DESC_INTERFACE_TYPE, # bDescriptorType bInterfaceNumber, - 0, # bAlternateSetting, not currently supported + bAlternateSetting, bNumEndpoints, bInterfaceClass, bInterfaceSubClass, @@ -791,17 +797,18 @@ class Buffer: # approximate a Python-based single byte ringbuffer. # def __init__(self, length): + self._l = length self._b = memoryview(bytearray(length)) - # number of bytes in buffer read to read, starting at index 0. Updated + # number of bytes in buffer ready to read, starting at index 0. Updated # by both producer & consumer. self._n = 0 - # start index of a pending write into the buffer, if any. equals + # start index of a pending write into the buffer, if any. Equals # len(self._b) if no write is pending. Updated by producer only. self._w = length def writable(self): # Number of writable bytes in the buffer. Assumes no pending write is outstanding. - return len(self._b) - self._n + return self._l - self._n def readable(self): # Number of readable bytes in the buffer. Assumes no pending read is outstanding. @@ -815,15 +822,15 @@ def pend_write(self, wmax=None): # this many bytes long. # # (No critical section needed as self._w is only updated by the producer.) - self._w = self._n - end = (self._w + wmax) if wmax else len(self._b) - return self._b[self._w : end] + self._w = (_w := self._n) + end = (_w + wmax) if wmax else self._l + return self._b[_w:end] def finish_write(self, nbytes): # Called by the producer to indicate it wrote nbytes into the buffer. ist = machine.disable_irq() try: - assert nbytes <= len(self._b) - self._w # can't say we wrote more than was pended + assert nbytes <= self._l - self._w # can't say we wrote more than was pended if self._n == self._w: # no data was read while the write was happening, so the buffer is already in place # (this is the fast path) @@ -834,13 +841,14 @@ def finish_write(self, nbytes): # # As this updates self._n we have to do it in the critical # section, so do it byte by byte to avoid allocating. + _b = self._b while nbytes > 0: - self._b[self._n] = self._b[self._w] + _b[self._n] = _b[self._w] self._n += 1 self._w += 1 nbytes -= 1 - self._w = len(self._b) + self._w = self._l finally: machine.enable_irq(ist) @@ -866,10 +874,11 @@ def finish_read(self, nbytes): assert nbytes <= self._n # can't say we read more than was available i = 0 self._n -= nbytes + _b = self._b while i < self._n: # consumer only read part of the buffer, so shuffle remaining # read data back towards index 0 to avoid fragmentation - self._b[i] = self._b[i + nbytes] + _b[i] = _b[i + nbytes] i += 1 finally: machine.enable_irq(ist)