⦁	Removed `import time` (not used)
⦁	Removed unused/duplicate `_Device.config` argument `config_str`
⦁	Fixed the loop reserving other string indexes used by built-in drivers `while len(strs) < builtin_driver.str_max:` to `while len(strs) < builtin\_driver.str\_max - 1:` (row 169)because str_max equals to one more than the highest string descriptor index value used by any built-in descriptor according to the [docs](https://docs.micropython.org/en/latest/library/machine.USBDevice.html) and added a comment that this loop is probably unnecessary or even wrong
⦁	Added `bAlternateSetting` as argument to `Descriptor.interface`, because it is used for USB MIDI 2.0
⦁	Some code optimisations
pull/1030/head
HLammers 2025-07-05 11:49:36 +02:00
rodzic 913498ef05
commit 942c80cbd0
1 zmienionych plików z 24 dodań i 17 usunięć

Wyświetl plik

@ -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 @@ class _Device:
device_class=0,
device_subclass=0,
device_protocol=0,
config_str=None,
max_power_ma=None,
remote_wakeup=False,
):
@ -166,7 +166,9 @@ class _Device:
# 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 +206,11 @@ class _Device:
)
# 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 +668,7 @@ class Descriptor:
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 +684,7 @@ class Descriptor:
_STD_DESC_INTERFACE_LEN, # bLength
_STD_DESC_INTERFACE_TYPE, # bDescriptorType
bInterfaceNumber,
0, # bAlternateSetting, not currently supported
bAlternateSetting,
bNumEndpoints,
bInterfaceClass,
bInterfaceSubClass,
@ -791,17 +795,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,16 +820,16 @@ class Buffer:
# 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
if self._n == self._w:
assert nbytes <= self._l - (_w := self._w) # can't say we wrote more than was pended
if self._n == _w:
# no data was read while the write was happening, so the buffer is already in place
# (this is the fast path)
self._n += nbytes
@ -834,13 +839,14 @@ class Buffer:
#
# 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 +872,11 @@ class Buffer:
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)
@ -881,4 +888,4 @@ class Buffer:
if to_r:
b[:to_r] = pr[:to_r]
self.finish_read(to_r)
return to_r
return to_r