Skip to content

Commit 00dcf6b

Browse files
committed
Tweaks from review
1 parent 45f9522 commit 00dcf6b

File tree

7 files changed

+145
-78
lines changed

7 files changed

+145
-78
lines changed

py/circuitpy_defns.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,7 @@ endif
646646
SRC_SHARED_MODULE_INTERNAL = \
647647
$(filter $(SRC_PATTERNS), \
648648
displayio/display_core.c \
649+
usb/utf16le.c \
649650
)
650651

651652
SRC_COMMON_HAL_INTERNAL = \

shared-bindings/usb/core/Device.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ const mp_obj_property_t usb_core_device_manufacturer_obj = {
163163
STATIC mp_obj_t usb_core_device_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
164164
enum { ARG_endpoint, ARG_data, ARG_timeout };
165165
static const mp_arg_t allowed_args[] = {
166-
{ MP_QSTR_endpoint, MP_ARG_REQUIRED | MP_ARG_OBJ },
166+
{ MP_QSTR_endpoint, MP_ARG_REQUIRED | MP_ARG_INT },
167167
{ MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ },
168168
{ MP_QSTR_timeout, MP_ARG_INT, {.u_int = 0} },
169169
};
@@ -191,7 +191,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(usb_core_device_write_obj, 2, usb_core_device_write);
191191
STATIC mp_obj_t usb_core_device_read(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
192192
enum { ARG_endpoint, ARG_size_or_buffer, ARG_timeout };
193193
static const mp_arg_t allowed_args[] = {
194-
{ MP_QSTR_endpoint, MP_ARG_REQUIRED | MP_ARG_OBJ },
194+
{ MP_QSTR_endpoint, MP_ARG_REQUIRED | MP_ARG_INT },
195195
{ MP_QSTR_size_or_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ },
196196
{ MP_QSTR_timeout, MP_ARG_INT, {.u_int = 0} },
197197
};

shared-bindings/usb/core/__init__.c

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
*/
2626

2727
#include <stdarg.h>
28+
#include <string.h>
2829

2930
#include "py/obj.h"
3031
#include "py/objexcept.h"
@@ -97,8 +98,6 @@ STATIC mp_obj_t _next_device(usb_core_devices_obj_t *iter) {
9798
usb_core_device_obj_t *self = m_new_obj(usb_core_device_obj_t);
9899
self->base.type = &usb_core_device_type;
99100

100-
mp_printf(&mp_plat_print, "USB device %d matches\n", i);
101-
102101
common_hal_usb_core_device_construct(self, i);
103102
iter->next_index = i + 1;
104103
return MP_OBJ_FROM_PTR(self);
@@ -132,29 +131,31 @@ STATIC mp_obj_t usb_core_find(size_t n_args, const mp_obj_t *pos_args, mp_map_t
132131
enum { ARG_find_all, ARG_idVendor, ARG_idProduct };
133132
static const mp_arg_t allowed_args[] = {
134133
{ MP_QSTR_find_all, MP_ARG_BOOL, {.u_bool = false} },
135-
{ MP_QSTR_idVendor, MP_ARG_INT, {.u_int = 0x10000} },
136-
{ MP_QSTR_idProduct, MP_ARG_INT, {.u_int = 0x10000} },
134+
{ MP_QSTR_idVendor, MP_ARG_OBJ, {.u_obj = mp_const_none} },
135+
{ MP_QSTR_idProduct, MP_ARG_OBJ, {.u_obj = mp_const_none} },
137136
};
138137
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
139138
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
140139

141-
bool find_all = args[ARG_find_all].u_bool;
140+
const bool find_all = args[ARG_find_all].u_bool;
142141
usb_core_devices_obj_t temp_iter;
143-
usb_core_devices_obj_t *iter;
144-
if (find_all) {
145-
iter = m_new_obj(usb_core_devices_obj_t);
146-
iter->base.type = &usb_core_devices_type;
147-
} else {
148-
iter = &temp_iter;
142+
temp_iter.base.type = &usb_core_devices_type;
143+
temp_iter.next_index = 1;
144+
if (!mp_obj_get_int_maybe(args[ARG_idVendor].u_obj, &temp_iter.vid)) {
145+
temp_iter.vid = 0x10000;
149146
}
150-
iter->next_index = 1;
151-
iter->vid = args[ARG_idVendor].u_int;
152-
iter->pid = args[ARG_idProduct].u_int;
153-
if (!find_all) {
154-
return _next_device(iter);
147+
if (!mp_obj_get_int_maybe(args[ARG_idProduct].u_obj, &temp_iter.pid)) {
148+
temp_iter.pid = 0x10000;
155149
}
156-
157-
return MP_OBJ_FROM_PTR(iter);
150+
if (find_all) {
151+
// Copy the temp iter contents to a heap object before we return it.
152+
// We could do this up front but GCC falsely detects that we may return
153+
// the stack copy.
154+
usb_core_devices_obj_t *iter = m_new_obj(usb_core_devices_obj_t);
155+
memcpy(iter, &temp_iter, sizeof(usb_core_devices_obj_t));
156+
return MP_OBJ_FROM_PTR(iter);
157+
}
158+
return _next_device(&temp_iter);
158159
}
159160
MP_DEFINE_CONST_FUN_OBJ_KW(usb_core_find_obj, 0, usb_core_find);
160161

shared-module/usb/core/Device.c

Lines changed: 3 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "py/runtime.h"
3333
#include "shared/runtime/interrupt_char.h"
3434
#include "shared-bindings/usb/core/__init__.h"
35+
#include "shared-module/usb/utf16le.h"
3536
#include "supervisor/shared/tick.h"
3637

3738
bool common_hal_usb_core_device_construct(usb_core_device_obj_t *self, uint8_t device_number) {
@@ -49,7 +50,6 @@ uint16_t common_hal_usb_core_device_get_idVendor(usb_core_device_obj_t *self) {
4950
uint16_t vid;
5051
uint16_t pid;
5152
tuh_vid_pid_get(self->device_number, &vid, &pid);
52-
mp_printf(&mp_plat_print, "%d vid %04x pid %04x\n", self->device_number, vid, pid);
5353
return vid;
5454
}
5555

@@ -62,60 +62,13 @@ uint16_t common_hal_usb_core_device_get_idProduct(usb_core_device_obj_t *self) {
6262

6363
STATIC xfer_result_t _get_string_result;
6464
STATIC bool _transfer_done_cb(uint8_t daddr, tusb_control_request_t const *request, xfer_result_t result) {
65+
// Store the result so we stop waiting for the transfer. We don't need the other data for now.
6566
(void)daddr;
6667
(void)request;
6768
_get_string_result = result;
6869
return true;
6970
}
7071

71-
72-
STATIC void _convert_utf16le_to_utf8(const uint16_t *utf16, size_t utf16_len, uint8_t *utf8, size_t utf8_len) {
73-
// TODO: Check for runover.
74-
(void)utf8_len;
75-
76-
for (size_t i = 0; i < utf16_len; i++) {
77-
uint16_t chr = utf16[i];
78-
if (chr < 0x80) {
79-
*utf8++ = chr & 0xff;
80-
} else if (chr < 0x800) {
81-
*utf8++ = (uint8_t)(0xC0 | (chr >> 6 & 0x1F));
82-
*utf8++ = (uint8_t)(0x80 | (chr >> 0 & 0x3F));
83-
} else if (chr < 0x10000) {
84-
// TODO: Verify surrogate.
85-
*utf8++ = (uint8_t)(0xE0 | (chr >> 12 & 0x0F));
86-
*utf8++ = (uint8_t)(0x80 | (chr >> 6 & 0x3F));
87-
*utf8++ = (uint8_t)(0x80 | (chr >> 0 & 0x3F));
88-
} else {
89-
// TODO: Handle UTF-16 code points that take two entries.
90-
uint32_t hc = ((chr & 0xFFFF0000) - 0xD8000000) >> 6; /* Get high 10 bits */
91-
chr = (chr & 0xFFFF) - 0xDC00; /* Get low 10 bits */
92-
chr = (hc | chr) + 0x10000;
93-
*utf8++ = (uint8_t)(0xF0 | (chr >> 18 & 0x07));
94-
*utf8++ = (uint8_t)(0x80 | (chr >> 12 & 0x3F));
95-
*utf8++ = (uint8_t)(0x80 | (chr >> 6 & 0x3F));
96-
*utf8++ = (uint8_t)(0x80 | (chr >> 0 & 0x3F));
97-
}
98-
}
99-
}
100-
101-
// Count how many bytes a utf-16-le encoded string will take in utf-8.
102-
STATIC mp_int_t _count_utf8_bytes(const uint16_t *buf, size_t len) {
103-
size_t total_bytes = 0;
104-
for (size_t i = 0; i < len; i++) {
105-
uint16_t chr = buf[i];
106-
if (chr < 0x80) {
107-
total_bytes += 1;
108-
} else if (chr < 0x800) {
109-
total_bytes += 2;
110-
} else if (chr < 0x10000) {
111-
total_bytes += 3;
112-
} else {
113-
total_bytes += 4;
114-
}
115-
}
116-
return total_bytes;
117-
}
118-
11972
STATIC void _wait_for_callback(void) {
12073
while (!mp_hal_is_interrupted() &&
12174
_get_string_result == 0xff) {
@@ -130,14 +83,7 @@ STATIC mp_obj_t _get_string(const uint16_t *temp_buf) {
13083
if (utf16_len == 0) {
13184
return mp_const_none;
13285
}
133-
size_t size = _count_utf8_bytes(temp_buf + 1, utf16_len);
134-
vstr_t vstr;
135-
vstr_init_len(&vstr, size + 1);
136-
byte *p = (byte *)vstr.buf;
137-
// Null terminate.
138-
p[size] = '\0';
139-
_convert_utf16le_to_utf8(temp_buf + 1, utf16_len, p, size);
140-
return mp_obj_new_str_from_vstr(&mp_type_str, &vstr);
86+
return utf16le_to_string(temp_buf + 1, utf16_len);
14187
}
14288

14389
mp_obj_t common_hal_usb_core_device_get_serial_number(usb_core_device_obj_t *self) {

shared-module/usb/utf16le.c

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2022 Scott Shawcroft for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include "shared-module/usb/utf16le.h"
28+
29+
STATIC void _convert_utf16le_to_utf8(const uint16_t *utf16, size_t utf16_len, uint8_t *utf8, size_t utf8_len) {
30+
// TODO: Check for runover.
31+
(void)utf8_len;
32+
33+
for (size_t i = 0; i < utf16_len; i++) {
34+
uint16_t chr = utf16[i];
35+
if (chr < 0x80) {
36+
*utf8++ = chr & 0xff;
37+
} else if (chr < 0x800) {
38+
*utf8++ = (uint8_t)(0xC0 | (chr >> 6 & 0x1F));
39+
*utf8++ = (uint8_t)(0x80 | (chr >> 0 & 0x3F));
40+
} else if (chr < 0x10000) {
41+
// TODO: Verify surrogate.
42+
*utf8++ = (uint8_t)(0xE0 | (chr >> 12 & 0x0F));
43+
*utf8++ = (uint8_t)(0x80 | (chr >> 6 & 0x3F));
44+
*utf8++ = (uint8_t)(0x80 | (chr >> 0 & 0x3F));
45+
} else {
46+
// TODO: Handle UTF-16 code points that take two entries.
47+
uint32_t hc = ((chr & 0xFFFF0000) - 0xD8000000) >> 6; /* Get high 10 bits */
48+
chr = (chr & 0xFFFF) - 0xDC00; /* Get low 10 bits */
49+
chr = (hc | chr) + 0x10000;
50+
*utf8++ = (uint8_t)(0xF0 | (chr >> 18 & 0x07));
51+
*utf8++ = (uint8_t)(0x80 | (chr >> 12 & 0x3F));
52+
*utf8++ = (uint8_t)(0x80 | (chr >> 6 & 0x3F));
53+
*utf8++ = (uint8_t)(0x80 | (chr >> 0 & 0x3F));
54+
}
55+
}
56+
}
57+
58+
// Count how many bytes a utf-16-le encoded string will take in utf-8.
59+
STATIC mp_int_t _count_utf8_bytes(const uint16_t *buf, size_t len) {
60+
size_t total_bytes = 0;
61+
for (size_t i = 0; i < len; i++) {
62+
uint16_t chr = buf[i];
63+
if (chr < 0x80) {
64+
total_bytes += 1;
65+
} else if (chr < 0x800) {
66+
total_bytes += 2;
67+
} else if (chr < 0x10000) {
68+
total_bytes += 3;
69+
} else {
70+
total_bytes += 4;
71+
}
72+
}
73+
return total_bytes;
74+
}
75+
76+
mp_obj_t utf16le_to_string(const uint16_t *buf, size_t utf16_len) {
77+
size_t size = _count_utf8_bytes(buf, utf16_len);
78+
vstr_t vstr;
79+
vstr_init_len(&vstr, size + 1);
80+
byte *p = (byte *)vstr.buf;
81+
// Null terminate.
82+
p[size] = '\0';
83+
_convert_utf16le_to_utf8(buf, utf16_len, p, size);
84+
return mp_obj_new_str_from_vstr(&mp_type_str, &vstr);
85+
}

shared-module/usb/utf16le.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2022 Scott Shawcroft for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#ifndef MICROPY_INCLUDED_SHARED_MODULE_USB_UTF16LE_H
28+
#define MICROPY_INCLUDED_SHARED_MODULE_USB_UTF16LE_H
29+
30+
#include "py/obj.h"
31+
32+
mp_obj_t utf16le_to_string(const uint16_t *buf, size_t utf16_len);
33+
34+
#endif // MICROPY_INCLUDED_SHARED_MODULE_USB_UTF16LE_H

tests/circuitpython-manual/usb/device_info.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
while True:
1515
for device in usb.core.find(find_all=True):
16-
print(device.idVendor, device.idProduct)
16+
print(f"{device.idVendor:04x}:{device.idProduct:04x}")
1717
print(device.manufacturer, device.product)
1818
print(device.serial_number)
1919
print()

0 commit comments

Comments
 (0)