Skip to content

Commit bee9957

Browse files
committed
supervisor: Add supervisor.set_usb_identification() function
1 parent 7ad35bf commit bee9957

File tree

4 files changed

+105
-15
lines changed

4 files changed

+105
-15
lines changed

shared-bindings/supervisor/__init__.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "supervisor/shared/traceback.h"
3939
#include "supervisor/shared/translate.h"
4040
#include "supervisor/shared/workflow.h"
41+
#include "supervisor/usb.h"
4142

4243
#include "shared-bindings/microcontroller/__init__.h"
4344
#include "shared-bindings/supervisor/__init__.h"
@@ -311,6 +312,62 @@ STATIC mp_obj_t supervisor_reset_terminal(mp_obj_t x_pixels, mp_obj_t y_pixels)
311312
}
312313
MP_DEFINE_CONST_FUN_OBJ_2(supervisor_reset_terminal_obj, supervisor_reset_terminal);
313314

315+
//| def set_usb_identification(manufacturer: Optional[str] = None, product: Optional[str] = None, vid: int = -1, pid: int = -1) -> None:
316+
//| """Override identification constants in the USB Device Descriptor.
317+
//|
318+
//| If passed, `manufacturer` and `product` must be ASCII strings (or buffers) of at most 127
319+
//| characters. Any omitted arguments will be left at their default values.
320+
//|
321+
//| This method must be called in boot.py to have any effect."""
322+
//| ...
323+
//|
324+
STATIC mp_obj_t supervisor_set_usb_identification(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
325+
static const mp_arg_t allowed_args[] = {
326+
{ MP_QSTR_manufacturer, MP_ARG_OBJ, {.u_rom_obj = mp_const_none} },
327+
{ MP_QSTR_product, MP_ARG_OBJ, {.u_rom_obj = mp_const_none} },
328+
{ MP_QSTR_vid, MP_ARG_INT, {.u_int = -1} },
329+
{ MP_QSTR_pid, MP_ARG_INT, {.u_int = -1} },
330+
};
331+
struct {
332+
mp_arg_val_t manufacturer;
333+
mp_arg_val_t product;
334+
mp_arg_val_t vid;
335+
mp_arg_val_t pid;
336+
} args;
337+
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t *)&args);
338+
339+
if (!usb_identification_allocation) {
340+
usb_identification_allocation = allocate_memory(sizeof(usb_identification_t), false, true);
341+
}
342+
usb_identification_t *identification = (usb_identification_t *)usb_identification_allocation->ptr;
343+
344+
mp_arg_validate_int_range(args.vid.u_int, -1, (1 << 16) - 1, MP_QSTR_vid);
345+
mp_arg_validate_int_range(args.pid.u_int, -1, (1 << 16) - 1, MP_QSTR_pid);
346+
347+
identification->vid = args.vid.u_int > -1 ? args.vid.u_int : USB_VID;
348+
identification->pid = args.pid.u_int > -1 ? args.pid.u_int : USB_PID;
349+
350+
mp_buffer_info_t info;
351+
if (args.manufacturer.u_obj != mp_const_none) {
352+
mp_get_buffer_raise(args.manufacturer.u_obj, &info, MP_BUFFER_READ);
353+
mp_arg_validate_length_range(info.len, 0, 127, MP_QSTR_manufacturer);
354+
memcpy(identification->manufacturer_name, info.buf, info.len);
355+
} else {
356+
memcpy(identification->manufacturer_name, USB_MANUFACTURER, sizeof(USB_MANUFACTURER));
357+
}
358+
359+
if (args.product.u_obj != mp_const_none) {
360+
mp_get_buffer_raise(args.product.u_obj, &info, MP_BUFFER_READ);
361+
mp_arg_validate_length_range(info.len, 0, 127, MP_QSTR_product);
362+
memcpy(identification->product_name, info.buf, info.len);
363+
} else {
364+
memcpy(identification->product_name, USB_MANUFACTURER, sizeof(USB_MANUFACTURER));
365+
}
366+
367+
return mp_const_none;
368+
}
369+
MP_DEFINE_CONST_FUN_OBJ_KW(supervisor_set_usb_identification_obj, 0, supervisor_set_usb_identification);
370+
314371
STATIC const mp_rom_map_elem_t supervisor_module_globals_table[] = {
315372
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_supervisor) },
316373
{ MP_ROM_QSTR(MP_QSTR_enable_autoreload), MP_ROM_PTR(&supervisor_enable_autoreload_obj) },
@@ -325,6 +382,7 @@ STATIC const mp_rom_map_elem_t supervisor_module_globals_table[] = {
325382
{ MP_ROM_QSTR(MP_QSTR_get_previous_traceback), MP_ROM_PTR(&supervisor_get_previous_traceback_obj) },
326383
{ MP_ROM_QSTR(MP_QSTR_disable_ble_workflow), MP_ROM_PTR(&supervisor_disable_ble_workflow_obj) },
327384
{ MP_ROM_QSTR(MP_QSTR_reset_terminal), MP_ROM_PTR(&supervisor_reset_terminal_obj) },
385+
{ MP_ROM_QSTR(MP_QSTR_set_usb_identification), MP_ROM_PTR(&supervisor_set_usb_identification_obj) },
328386
};
329387

330388
STATIC MP_DEFINE_CONST_DICT(supervisor_module_globals, supervisor_module_globals_table);

supervisor/shared/usb/usb.c

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,11 @@ void usb_set_defaults(void) {
118118
#endif
119119
};
120120

121+
supervisor_allocation *usb_identification_allocation;
122+
121123
// Some dynamic USB data must be saved after boot.py. How much is needed?
122124
size_t usb_boot_py_data_size(void) {
123-
size_t size = 0;
125+
size_t size = sizeof(usb_identification_t);
124126

125127
#if CIRCUITPY_USB_HID
126128
size += usb_hid_report_descriptor_length();
@@ -131,19 +133,41 @@ size_t usb_boot_py_data_size(void) {
131133

132134
// Fill in the data to save.
133135
void usb_get_boot_py_data(uint8_t *temp_storage, size_t temp_storage_size) {
136+
if (usb_identification_allocation) {
137+
memcpy(temp_storage, usb_identification_allocation->ptr, sizeof(usb_identification_t));
138+
free_memory(usb_identification_allocation);
139+
} else {
140+
usb_identification_t defaults = {
141+
.vid = USB_VID,
142+
.pid = USB_PID,
143+
.manufacturer_name = USB_MANUFACTURER,
144+
.product_name = USB_PRODUCT,
145+
};
146+
memcpy(temp_storage, &defaults, sizeof(defaults));
147+
}
148+
149+
temp_storage += sizeof(usb_identification_t);
150+
temp_storage_size -= sizeof(usb_identification_t);
151+
134152
#if CIRCUITPY_USB_HID
135153
usb_hid_build_report_descriptor(temp_storage, temp_storage_size);
136154
#endif
137155
}
138156

139157
// After VM is gone, save data into non-heap storage (storage_allocations).
140158
void usb_return_boot_py_data(uint8_t *temp_storage, size_t temp_storage_size) {
159+
usb_identification_t identification;
160+
memcpy(&identification, temp_storage, sizeof(usb_identification_t));
161+
162+
temp_storage += sizeof(usb_identification_t);
163+
temp_storage_size -= sizeof(usb_identification_t);
164+
141165
#if CIRCUITPY_USB_HID
142166
usb_hid_save_report_descriptor(temp_storage, temp_storage_size);
143167
#endif
144168

145169
// Now we can also build the rest of the descriptors and place them in storage_allocations.
146-
usb_build_descriptors();
170+
usb_build_descriptors(&identification);
147171
}
148172

149173
// Call this when ready to run code.py or a REPL, and a VM has been started.

supervisor/shared/usb/usb_desc.c

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,6 @@ static supervisor_allocation *device_descriptor_allocation;
6868
static supervisor_allocation *configuration_descriptor_allocation;
6969
static supervisor_allocation *string_descriptors_allocation;
7070

71-
static const char manufacturer_name[] = USB_MANUFACTURER;
72-
static const char product_name[] = USB_PRODUCT;
73-
7471
// Serial number string is UID length * 2 (2 nibbles per byte) + 1 byte for null termination.
7572
static char serial_number_hex_string[COMMON_HAL_MCU_PROCESSOR_UID_LENGTH * 2 + 1];
7673

@@ -113,23 +110,23 @@ static const uint8_t configuration_descriptor_template[] = {
113110
0x32, // 8 bMaxPower 100mA
114111
};
115112

116-
static void usb_build_device_descriptor(uint16_t vid, uint16_t pid) {
113+
static void usb_build_device_descriptor(const usb_identification_t *identification) {
117114
device_descriptor_allocation =
118115
allocate_memory(align32_size(sizeof(device_descriptor_template)),
119116
/*high_address*/ false, /*movable*/ false);
120117
uint8_t *device_descriptor = (uint8_t *)device_descriptor_allocation->ptr;
121118
memcpy(device_descriptor, device_descriptor_template, sizeof(device_descriptor_template));
122119

123-
device_descriptor[DEVICE_VID_LO_INDEX] = vid & 0xFF;
124-
device_descriptor[DEVICE_VID_HI_INDEX] = vid >> 8;
125-
device_descriptor[DEVICE_PID_LO_INDEX] = pid & 0xFF;
126-
device_descriptor[DEVICE_PID_HI_INDEX] = pid >> 8;
120+
device_descriptor[DEVICE_VID_LO_INDEX] = identification->vid & 0xFF;
121+
device_descriptor[DEVICE_VID_HI_INDEX] = identification->vid >> 8;
122+
device_descriptor[DEVICE_PID_LO_INDEX] = identification->pid & 0xFF;
123+
device_descriptor[DEVICE_PID_HI_INDEX] = identification->pid >> 8;
127124

128-
usb_add_interface_string(current_interface_string, manufacturer_name);
125+
usb_add_interface_string(current_interface_string, identification->manufacturer_name);
129126
device_descriptor[DEVICE_MANUFACTURER_STRING_INDEX] = current_interface_string;
130127
current_interface_string++;
131128

132-
usb_add_interface_string(current_interface_string, product_name);
129+
usb_add_interface_string(current_interface_string, identification->product_name);
133130
device_descriptor[DEVICE_PRODUCT_STRING_INDEX] = current_interface_string;
134131
current_interface_string++;
135132

@@ -319,7 +316,7 @@ static void usb_build_interface_string_table(void) {
319316

320317
// After boot.py runs, the USB devices to be used have been chosen, and the descriptors can be set up.
321318
// This is called after the VM is finished, because it uses storage_allocations.
322-
void usb_build_descriptors(void) {
319+
void usb_build_descriptors(const usb_identification_t *identification) {
323320
uint8_t raw_id[COMMON_HAL_MCU_PROCESSOR_UID_LENGTH];
324321
common_hal_mcu_processor_get_uid(raw_id);
325322

@@ -336,7 +333,7 @@ void usb_build_descriptors(void) {
336333
current_interface_string = 1;
337334
collected_interface_strings_length = 0;
338335

339-
usb_build_device_descriptor(USB_VID, USB_PID);
336+
usb_build_device_descriptor(identification);
340337
usb_build_configuration_descriptor();
341338
usb_build_interface_string_table();
342339
}

supervisor/usb.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
#include <stddef.h>
3232
#include <stdint.h>
3333

34+
#include "supervisor/memory.h"
35+
3436
// Ports must call this as frequently as they can in order to keep the USB
3537
// connection alive and responsive. Normally this is called from background
3638
// tasks after the USB IRQ handler is executed, but in specific circumstances
@@ -58,10 +60,19 @@ typedef struct {
5860
size_t num_out_endpoints;
5961
} descriptor_counts_t;
6062

63+
typedef struct {
64+
uint16_t vid;
65+
uint16_t pid;
66+
char manufacturer_name[128];
67+
char product_name[128];
68+
} usb_identification_t;
69+
70+
extern supervisor_allocation *usb_identification_allocation;
71+
6172
// Shared implementation.
6273
bool usb_enabled(void);
6374
void usb_add_interface_string(uint8_t interface_string_index, const char str[]);
64-
void usb_build_descriptors(void);
75+
void usb_build_descriptors(const usb_identification_t *identification);
6576
void usb_disconnect(void);
6677
void usb_init(void);
6778
void usb_set_defaults(void);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy