Skip to content

Commit b1203f9

Browse files
committed
extmod/machine_usb_device: Allow builtin config without dynamic devices.
Signed-off-by: Andrew Leech <[email protected]>
1 parent cd19765 commit b1203f9

File tree

3 files changed

+443
-105
lines changed

3 files changed

+443
-105
lines changed

docs/library/machine.USBDevice.rst

Lines changed: 144 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -188,23 +188,39 @@ Methods
188188
.. attribute:: USBDevice.builtin_driver
189189

190190
This attribute holds the current built-in driver configuration, and must be
191-
set to one of the ``USBDevice.BUILTIN_`` named constants defined on this object.
191+
set to one of the ``USBDevice.BUILTIN_`` constants or a combination of them
192+
using the bitwise OR operator (``|``).
192193

193194
By default it holds the value :data:`USBDevice.BUILTIN_NONE`.
194195

195196
Runtime USB device must be inactive when setting this field. Call the
196197
:func:`USBDevice.active` function to deactivate before setting if necessary
197198
(and again to activate after setting).
198199

200+
**Combining Built-in Drivers:**
201+
202+
Multiple built-in USB classes can be enabled simultaneously by combining
203+
constants with the bitwise OR operator::
204+
205+
usb = machine.USBDevice()
206+
usb.active(False)
207+
# Enable both CDC and MSC
208+
usb.builtin_driver = usb.BUILTIN_CDC | usb.BUILTIN_MSC
209+
usb.active(True)
210+
211+
The combined configuration will dynamically generate appropriate USB
212+
descriptors containing only the selected classes.
213+
199214
If this value is set to any value other than :data:`USBDevice.BUILTIN_NONE` then
200215
the following restrictions apply to the :func:`USBDevice.config` arguments:
201216

202217
- ``desc_cfg`` should begin with the built-in USB interface descriptor data
203218
accessible via :data:`USBDevice.builtin_driver` attribute ``desc_cfg``.
204-
Descriptors appended after the built-in configuration descriptors should use
205-
interface, string and endpoint numbers starting from the max built-in values
206-
defined in :data:`USBDevice.builtin_driver` attributes ``itf_max``, ``str_max`` and
207-
``ep_max``.
219+
The descriptor is dynamically generated based on the combination of classes
220+
enabled. Descriptors appended after the built-in configuration descriptors
221+
should use interface, string and endpoint numbers starting from the max
222+
built-in values defined in :data:`USBDevice.builtin_driver` attributes
223+
``itf_max``, ``str_max`` and ``ep_max``.
208224

209225
- The ``bNumInterfaces`` field in the built-in configuration
210226
descriptor will also need to be updated if any new interfaces
@@ -266,39 +282,133 @@ Constants
266282
---------
267283

268284
.. data:: USBDevice.BUILTIN_NONE
285+
286+
Constant representing no built-in USB drivers enabled. This is the
287+
default value for :data:`USBDevice.builtin_driver`.
288+
269289
.. data:: USBDevice.BUILTIN_DEFAULT
290+
291+
Constant representing the default combination of built-in USB drivers
292+
for this firmware build. The exact combination depends on compile-time
293+
configuration options.
294+
270295
.. data:: USBDevice.BUILTIN_CDC
296+
297+
Constant representing the built-in USB CDC (serial port) driver.
298+
Can be combined with other ``BUILTIN_`` constants using the bitwise
299+
OR operator (``|``).
300+
271301
.. data:: USBDevice.BUILTIN_MSC
302+
303+
Constant representing the built-in USB MSC (mass storage) driver.
304+
Can be combined with other ``BUILTIN_`` constants using the bitwise
305+
OR operator (``|``).
306+
307+
.. data:: USBDevice.BUILTIN_NCM
308+
309+
Constant representing the built-in USB NCM (network) driver.
310+
Only available when ``MICROPY_HW_NETWORK_USBNET`` is enabled in the
311+
firmware build. Can be combined with other ``BUILTIN_`` constants
312+
using the bitwise OR operator (``|``).
313+
314+
.. note:: When NCM is disabled after being active, the network
315+
interface is automatically cleaned up.
316+
272317
.. data:: USBDevice.BUILTIN_CDC_MSC
273318

274-
These constant objects hold the built-in descriptor data which is
275-
compiled into the MicroPython firmware. ``USBDevice.BUILTIN_NONE`` and
276-
``USBDevice.BUILTIN_DEFAULT`` are always present. Additional objects may be present
277-
depending on the firmware build configuration and the actual built-in drivers.
278-
279-
.. note:: Currently at most one of ``USBDevice.BUILTIN_CDC``,
280-
``USBDevice.BUILTIN_MSC`` and ``USBDevice.BUILTIN_CDC_MSC`` is defined
281-
and will be the same object as ``USBDevice.BUILTIN_DEFAULT``.
282-
These constants are defined to allow run-time detection of
283-
the built-in driver (if any). Support for selecting one of
284-
multiple built-in driver configurations may be added in the
285-
future.
286-
287-
These values are assigned to :data:`USBDevice.builtin_driver` to get/set the
288-
built-in configuration.
289-
290-
Each object contains the following read-only fields:
291-
292-
- ``itf_max`` - One more than the highest bInterfaceNumber value used
293-
in the built-in configuration descriptor.
294-
- ``ep_max`` - One more than the highest bEndpointAddress value used
295-
in the built-in configuration descriptor. Does not include any
296-
``IN`` flag bit (0x80).
297-
- ``str_max`` - One more than the highest string descriptor index
298-
value used by any built-in descriptor.
299-
- ``desc_dev`` - ``bytes`` object containing the built-in USB device
300-
descriptor.
301-
- ``desc_cfg`` - ``bytes`` object containing the complete built-in USB
302-
configuration descriptor.
319+
.. deprecated::
320+
Use ``USBDevice.BUILTIN_CDC | USBDevice.BUILTIN_MSC`` instead.
321+
322+
Legacy constant for CDC and MSC combination. Provided for backward
323+
compatibility only.
324+
325+
**Combining Built-in Constants:**
326+
327+
Built-in driver constants can be combined using the bitwise OR operator to
328+
create custom USB device configurations::
329+
330+
# CDC serial port only
331+
usb.builtin_driver = USBDevice.BUILTIN_CDC
332+
333+
# CDC and MSC (serial + mass storage)
334+
usb.builtin_driver = USBDevice.BUILTIN_CDC | USBDevice.BUILTIN_MSC
335+
336+
# All available interfaces
337+
usb.builtin_driver = USBDevice.BUILTIN_CDC | USBDevice.BUILTIN_MSC | USBDevice.BUILTIN_NCM
338+
339+
# No built-in drivers (for fully custom USB devices)
340+
usb.builtin_driver = USBDevice.BUILTIN_NONE
341+
342+
The combined configuration dynamically generates the appropriate USB descriptors
343+
and updates the ``itf_max``, ``ep_max``, and ``str_max`` properties accordingly.
344+
345+
Each constant object contains the following read-only fields:
346+
347+
- ``itf_max`` - One more than the highest bInterfaceNumber value used
348+
in the configuration. Dynamically calculated based on enabled classes.
349+
- ``ep_max`` - One more than the highest bEndpointAddress value used
350+
in the configuration. Does not include any ``IN`` flag bit (0x80).
351+
Dynamically calculated based on enabled classes.
352+
- ``str_max`` - One more than the highest string descriptor index
353+
value used by any descriptor. Dynamically calculated.
354+
- ``desc_dev`` - ``bytes`` object containing the USB device descriptor.
355+
- ``desc_cfg`` - ``bytes`` object containing the complete USB
356+
configuration descriptor for the enabled classes.
357+
358+
Usage Examples
359+
--------------
360+
361+
**Basic CDC Serial Port:**
362+
::
363+
364+
import machine
365+
366+
usb = machine.USBDevice()
367+
usb.active(False)
368+
usb.builtin_driver = usb.BUILTIN_CDC
369+
usb.active(True)
370+
371+
**CDC + Mass Storage:**
372+
::
373+
374+
import machine
375+
376+
usb = machine.USBDevice()
377+
usb.active(False)
378+
usb.builtin_driver = usb.BUILTIN_CDC | usb.BUILTIN_MSC
379+
usb.active(True)
380+
381+
**Network Device with Serial Console:**
382+
::
383+
384+
import machine
385+
386+
usb = machine.USBDevice()
387+
usb.active(False)
388+
# Enable both CDC for console and NCM for networking
389+
usb.builtin_driver = usb.BUILTIN_CDC | usb.BUILTIN_NCM
390+
usb.active(True)
391+
392+
**Switching Configurations at Runtime:**
393+
::
394+
395+
import machine
396+
397+
usb = machine.USBDevice()
398+
399+
# Start with CDC only
400+
usb.active(False)
401+
usb.builtin_driver = usb.BUILTIN_CDC
402+
usb.active(True)
403+
404+
# Later, add mass storage
405+
usb.active(False)
406+
usb.builtin_driver = usb.BUILTIN_CDC | usb.BUILTIN_MSC
407+
usb.active(True)
408+
409+
# Remove MSC, add NCM
410+
usb.active(False)
411+
usb.builtin_driver = usb.BUILTIN_CDC | usb.BUILTIN_NCM
412+
usb.active(True)
303413

304414
.. _usb driver modules in micropython-lib: https://github.com/micropython/micropython-lib/tree/master/micropython/usb#readme

0 commit comments

Comments
 (0)