Skip to content

Commit 771b4c7

Browse files
committed
Add two space saving knobs
* Reduce the number of supported HID reports of IDs per descriptor. This saves ~200 bytes in the default HID objects. * (Not enabled) Compute QSTR attrs on init. This trades 1k RAM for flash. Flash is the default (1).
1 parent cc0a6c8 commit 771b4c7

File tree

5 files changed

+47
-18
lines changed

5 files changed

+47
-18
lines changed

ports/atmel-samd/mpconfigport.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@
6161

6262
#define MICROPY_FATFS_EXFAT 0
6363

64+
// Only support simpler HID descriptors on SAMD21.
65+
#define CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR (1)
66+
6467
#endif // SAMD21
6568

6669
////////////////////////////////////////////////////////////////////////////////////////////////////

py/circuitpy_mpconfig.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,13 @@ void supervisor_run_background_tasks_if_tick(void);
717717

718718
#define CIRCUITPY_VERBOSE_BLE 0
719719

720+
// This trades ~1k flash space (1) for that much in RAM plus the cost to compute
721+
// the values once on init (0). Only turn it off, when you really need the flash
722+
// space and are willing to trade the RAM.
723+
#ifndef CIRCUITPY_PRECOMPUTE_QSTR_ATTR
724+
#define CIRCUITPY_PRECOMPUTE_QSTR_ATTR (1)
725+
#endif
726+
720727
// USB settings
721728

722729
// If the port requires certain USB endpoint numbers, define these in mpconfigport.h.
@@ -761,6 +768,16 @@ void supervisor_run_background_tasks_if_tick(void);
761768
#define USB_HID_EP_NUM_IN (0)
762769
#endif
763770

771+
// The most complicated device currently known of is the head and eye tracker, which requires 5
772+
// report ids.
773+
// https://usb.org/sites/default/files/hutrr74_-_usage_page_for_head_and_eye_trackers_0.pdf
774+
// The default descriptors only use 1, so that is the minimum.
775+
#ifndef CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR
776+
#define CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR (6)
777+
#elif CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR < 1
778+
#error "CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR must be at least 1"
779+
#endif
780+
764781
#ifndef USB_MIDI_EP_NUM_OUT
765782
#define USB_MIDI_EP_NUM_OUT (0)
766783
#endif

py/qstr.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ mp_uint_t qstr_compute_hash(const byte *data, size_t len) {
7777
return hash;
7878
}
7979

80-
const qstr_attr_t mp_qstr_const_attr[] = {
80+
#if CIRCUITPY_PRECOMPUTE_QSTR_ATTR
81+
const qstr_attr_t mp_qstr_const_attr[MP_QSTRnumber_of] = {
8182
#ifndef NO_QSTR
8283
#define QDEF(id, hash, len, str) { hash, len },
8384
#define TRANSLATION(id, length, compressed ...)
@@ -86,6 +87,9 @@ const qstr_attr_t mp_qstr_const_attr[] = {
8687
#undef QDEF
8788
#endif
8889
};
90+
#else
91+
qstr_attr_t mp_qstr_const_attr[MP_QSTRnumber_of];
92+
#endif
8993

9094
const qstr_pool_t mp_qstr_const_pool = {
9195
NULL, // no previous pool
@@ -115,6 +119,16 @@ void qstr_init(void) {
115119
MP_STATE_VM(last_pool) = (qstr_pool_t *)&CONST_POOL; // we won't modify the const_pool since it has no allocated room left
116120
MP_STATE_VM(qstr_last_chunk) = NULL;
117121

122+
#if CIRCUITPY_PRECOMPUTE_QSTR_ATTR == 0
123+
if (mp_qstr_const_attr[MP_QSTR_circuitpython].len == 0) {
124+
for (size_t i = 0; i < mp_qstr_const_pool.len; i++) {
125+
size_t len = strlen(mp_qstr_const_pool.qstrs[i]);
126+
mp_qstr_const_attr[i].hash = qstr_compute_hash((const byte *)mp_qstr_const_pool.qstrs[i], len);
127+
mp_qstr_const_attr[i].len = len;
128+
}
129+
}
130+
#endif
131+
118132
#if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL
119133
mp_thread_mutex_init(&MP_STATE_VM(qstr_mutex));
120134
#endif

shared-module/usb_hid/Device.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ const usb_hid_device_obj_t usb_hid_device_keyboard_obj = {
8181
.usage = 0x06,
8282
.num_report_ids = 1,
8383
.report_ids = { 0x01, },
84-
.in_report_lengths = { 8, 0, 0, 0, 0, 0, },
84+
.in_report_lengths = { 8, },
8585
.out_report_lengths = { 1, },
8686
};
8787

@@ -131,7 +131,7 @@ const usb_hid_device_obj_t usb_hid_device_mouse_obj = {
131131
.usage = 0x02,
132132
.num_report_ids = 1,
133133
.report_ids = { 0x02, },
134-
.in_report_lengths = { 4, 0, 0, 0, 0, 0, },
134+
.in_report_lengths = { 4, },
135135
.out_report_lengths = { 0, },
136136
};
137137

@@ -160,7 +160,7 @@ const usb_hid_device_obj_t usb_hid_device_consumer_control_obj = {
160160
.usage = 0x01,
161161
.num_report_ids = 1,
162162
.report_ids = { 0x03 },
163-
.in_report_lengths = { 2, 0, 0, 0, 0, 0, },
163+
.in_report_lengths = { 2, },
164164
.out_report_lengths = { 0, },
165165
};
166166

@@ -170,7 +170,7 @@ STATIC size_t get_report_id_idx(usb_hid_device_obj_t *self, size_t report_id) {
170170
return i;
171171
}
172172
}
173-
return MAX_REPORT_IDS_PER_DESCRIPTOR;
173+
return CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR;
174174
}
175175

176176
// See if report_id is used by this device. If it is -1, then return the sole report id used by this device,
@@ -180,16 +180,16 @@ uint8_t common_hal_usb_hid_device_validate_report_id(usb_hid_device_obj_t *self,
180180
return self->report_ids[0];
181181
}
182182
if (!(report_id_arg >= 0 &&
183-
get_report_id_idx(self, (size_t)report_id_arg) < MAX_REPORT_IDS_PER_DESCRIPTOR)) {
183+
get_report_id_idx(self, (size_t)report_id_arg) < CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR)) {
184184
mp_raise_ValueError_varg(translate("Invalid %q"), MP_QSTR_report_id);
185185
}
186186
return (uint8_t)report_id_arg;
187187
}
188188

189189
void common_hal_usb_hid_device_construct(usb_hid_device_obj_t *self, mp_obj_t report_descriptor, uint8_t usage_page, uint8_t usage, size_t num_report_ids, uint8_t *report_ids, uint8_t *in_report_lengths, uint8_t *out_report_lengths) {
190-
if (num_report_ids > MAX_REPORT_IDS_PER_DESCRIPTOR) {
190+
if (num_report_ids > CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR) {
191191
mp_raise_ValueError_varg(translate("More than %d report ids not supported"),
192-
MAX_REPORT_IDS_PER_DESCRIPTOR);
192+
CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR);
193193
}
194194

195195
// report buffer pointers are NULL at start, and are created when USB is initialized.

shared-module/usb_hid/Device.h

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,16 @@
3232

3333
#include "py/obj.h"
3434

35-
// The most complicated device currently known of is the head and eye tracker, which requires 5
36-
// report ids.
37-
// https://usb.org/sites/default/files/hutrr74_-_usage_page_for_head_and_eye_trackers_0.pdf
38-
#define MAX_REPORT_IDS_PER_DESCRIPTOR (6)
39-
4035
typedef struct {
4136
mp_obj_base_t base;
4237
// Python buffer object whose contents are the descriptor.
4338
const uint8_t *report_descriptor;
44-
uint8_t *in_report_buffers[MAX_REPORT_IDS_PER_DESCRIPTOR];
45-
uint8_t *out_report_buffers[MAX_REPORT_IDS_PER_DESCRIPTOR];
39+
uint8_t *in_report_buffers[CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR];
40+
uint8_t *out_report_buffers[CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR];
4641
uint16_t report_descriptor_length;
47-
uint8_t report_ids[MAX_REPORT_IDS_PER_DESCRIPTOR];
48-
uint8_t in_report_lengths[MAX_REPORT_IDS_PER_DESCRIPTOR];
49-
uint8_t out_report_lengths[MAX_REPORT_IDS_PER_DESCRIPTOR];
42+
uint8_t report_ids[CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR];
43+
uint8_t in_report_lengths[CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR];
44+
uint8_t out_report_lengths[CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR];
5045
uint8_t usage_page;
5146
uint8_t usage;
5247
uint8_t num_report_ids;

0 commit comments

Comments
 (0)