summaryrefslogtreecommitdiff
path: root/shared/tinyusb/mp_usbd.h
diff options
context:
space:
mode:
authorAngus Gratton <angus@redyak.com.au>2023-11-23 09:48:41 +1100
committerDamien George <damien@micropython.org>2024-03-15 14:22:11 +1100
commit9d0d262be069089f01da6b40d2cd78f1da14de0f (patch)
tree197aae85f00879c35945fa32eb0a1552e5e10c1f /shared/tinyusb/mp_usbd.h
parent43904acea8b2087fdf9f283c0f8ce7d92d16e605 (diff)
extmod/machine_usb_device: Add support for Python USB devices.
This new machine-module driver provides a "USBDevice" singleton object and a shim TinyUSB "runtime" driver that delegates the descriptors and all of the TinyUSB callbacks to Python functions. This allows writing arbitrary USB devices in pure Python. It's also possible to have a base built-in USB device implemented in C (eg CDC, or CDC+MSC) and a Python USB device added on top of that. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
Diffstat (limited to 'shared/tinyusb/mp_usbd.h')
-rw-r--r--shared/tinyusb/mp_usbd.h101
1 files changed, 93 insertions, 8 deletions
diff --git a/shared/tinyusb/mp_usbd.h b/shared/tinyusb/mp_usbd.h
index 89f8bf0ee..ef3234845 100644
--- a/shared/tinyusb/mp_usbd.h
+++ b/shared/tinyusb/mp_usbd.h
@@ -27,25 +27,110 @@
#ifndef MICROPY_INCLUDED_SHARED_TINYUSB_MP_USBD_H
#define MICROPY_INCLUDED_SHARED_TINYUSB_MP_USBD_H
+#include "py/mpconfig.h"
+
+#if MICROPY_HW_ENABLE_USBDEV
+
#include "py/obj.h"
-#include "tusb.h"
+#include "py/objarray.h"
+#include "py/runtime.h"
-static inline void mp_usbd_init(void) {
- // Currently this is a thin wrapper around tusb_init(), however
- // runtime USB support will require this to be extended.
- tusb_init();
-}
+#ifndef NO_QSTR
+#include "tusb.h"
+#include "device/dcd.h"
+#endif
-// Call this to explicitly run the TinyUSB device task.
+// Run the TinyUSB device task
void mp_usbd_task(void);
+// Schedule a call to mp_usbd_task(), even if no USB interrupt has occurred
+void mp_usbd_schedule_task(void);
+
// Function to be implemented in port code.
// Can write a string up to MICROPY_HW_USB_DESC_STR_MAX characters long, plus terminating byte.
extern void mp_usbd_port_get_serial_number(char *buf);
-// Most ports need to write a hexadecimal serial number from a byte array, this
+// Most ports need to write a hexadecimal serial number from a byte array. This
// is a helper function for this. out_str must be long enough to hold a string of total
// length (2 * bytes_len + 1) (including NUL terminator).
void mp_usbd_hex_str(char *out_str, const uint8_t *bytes, size_t bytes_len);
+// Length of built-in configuration descriptor
+#define MP_USBD_BUILTIN_DESC_CFG_LEN (TUD_CONFIG_DESC_LEN + \
+ (CFG_TUD_CDC ? (TUD_CDC_DESC_LEN) : 0) + \
+ (CFG_TUD_MSC ? (TUD_MSC_DESC_LEN) : 0) \
+ )
+
+// Built-in USB device and configuration descriptor values
+extern const tusb_desc_device_t mp_usbd_builtin_desc_dev;
+extern const uint8_t mp_usbd_builtin_desc_cfg[MP_USBD_BUILTIN_DESC_CFG_LEN];
+
+void mp_usbd_task_callback(mp_sched_node_t *node);
+
+#if MICROPY_HW_ENABLE_USB_RUNTIME_DEVICE
+void mp_usbd_deinit(void);
+void mp_usbd_init(void);
+
+const char *mp_usbd_runtime_string_cb(uint8_t index);
+
+// Maximum number of pending exceptions per single TinyUSB task execution
+#define MP_USBD_MAX_PEND_EXCS 2
+
+typedef struct {
+ mp_obj_base_t base;
+
+ mp_obj_t desc_dev; // Device descriptor bytes
+ mp_obj_t desc_cfg; // Configuration descriptor bytes
+ mp_obj_t desc_strs; // List/dict/similar to look up string descriptors by index
+
+ // Runtime device driver callback functions
+ mp_obj_t open_itf_cb;
+ mp_obj_t reset_cb;
+ mp_obj_t control_xfer_cb;
+ mp_obj_t xfer_cb;
+
+ mp_obj_t builtin_driver; // Points to one of mp_type_usb_device_builtin_nnn
+
+ bool active; // Has the user set the USB device active?
+ bool trigger; // Has the user requested the active state change (or re-activate)?
+
+ // Temporary pointers for xfer data in progress on each endpoint
+ // Ensuring they aren't garbage collected until the xfer completes
+ mp_obj_t xfer_data[CFG_TUD_ENDPPOINT_MAX][2];
+
+ // Pointer to a memoryview that is reused to refer to various pieces of
+ // control transfer data that are pushed to USB control transfer
+ // callbacks. Python code can't rely on the memoryview contents
+ // to remain valid after the callback returns!
+ mp_obj_array_t *control_data;
+
+ // Pointers to exceptions thrown inside Python callbacks. See
+ // usbd_callback_function_n().
+ mp_uint_t num_pend_excs;
+ mp_obj_t pend_excs[MP_USBD_MAX_PEND_EXCS];
+} mp_obj_usb_device_t;
+
+// Built-in constant objects, possible values of builtin_driver
+//
+// (Currently not possible to change built-in drivers at runtime, just enable/disable.)
+extern const mp_obj_type_t mp_type_usb_device_builtin_default;
+extern const mp_obj_type_t mp_type_usb_device_builtin_none;
+
+// Return true if any built-in driver is enabled
+inline static bool mp_usb_device_builtin_enabled(const mp_obj_usb_device_t *usbd) {
+ return usbd->builtin_driver != MP_OBJ_FROM_PTR(&mp_type_usb_device_builtin_none);
+}
+
+#else // Static USBD drivers only
+
+static inline void mp_usbd_init(void) {
+ // Without runtime USB support, this can be a thin wrapper wrapper around tusb_init()
+ extern bool tusb_init(void);
+ tusb_init();
+}
+
+#endif
+
+#endif // MICROPY_HW_ENABLE_USBDEV
+
#endif // MICROPY_INCLUDED_SHARED_TINYUSB_USBD_H