diff options
Diffstat (limited to 'shared-bindings')
26 files changed, 316 insertions, 45 deletions
diff --git a/shared-bindings/_bleio/Adapter.c b/shared-bindings/_bleio/Adapter.c index a64167e5a..9772fa830 100644 --- a/shared-bindings/_bleio/Adapter.c +++ b/shared-bindings/_bleio/Adapter.c @@ -144,6 +144,9 @@ const mp_obj_property_t bleio_adapter_name_obj = { //| Starts advertising until `stop_advertising` is called or if connectable, another device //| connects to us. //| +//| .. warning: If data is longer than 31 bytes, then this will automatically advertise as an +//| extended advertisement that older BLE 4.x clients won't be able to scan for. +//| //| :param buf data: advertising data packet bytes //| :param buf scan_response: scan response data packet bytes. ``None`` if no scan response is needed. //| :param bool connectable: If `True` then other devices are allowed to connect to this peripheral. @@ -201,7 +204,7 @@ STATIC mp_obj_t bleio_adapter_stop_advertising(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_stop_advertising_obj, bleio_adapter_stop_advertising); -//| .. method:: start_scan(prefixes=b"", \*, buffer_size=512, extended=False, timeout=None, interval=0.1, window=0.1, minimum_rssi=-80) +//| .. method:: start_scan(prefixes=b"", \*, buffer_size=512, extended=False, timeout=None, interval=0.1, window=0.1, minimum_rssi=-80, active=True) //| //| Starts a BLE scan and returns an iterator of results. Advertisements and scan responses are //| filtered and returned separately. @@ -227,7 +230,7 @@ STATIC mp_obj_t bleio_adapter_start_scan(size_t n_args, const mp_obj_t *pos_args { MP_QSTR_prefixes, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_buffer_size, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 512} }, { MP_QSTR_extended, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, - { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_window, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_minimum_rssi, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -80} }, @@ -239,7 +242,7 @@ STATIC mp_obj_t bleio_adapter_start_scan(size_t n_args, const mp_obj_t *pos_args mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); mp_float_t timeout = 0; - if (args[ARG_timeout].u_obj != MP_OBJ_NULL) { + if (args[ARG_timeout].u_obj != mp_const_none) { timeout = mp_obj_get_float(args[ARG_timeout].u_obj); } @@ -306,7 +309,7 @@ const mp_obj_property_t bleio_adapter_connected_obj = { //| .. attribute:: connections //| -//| Tuple of active connections including those initiated through +//| Tuple of active connections including those initiated through //| :py:meth:`_bleio.Adapter.connect`. (read-only) //| STATIC mp_obj_t bleio_adapter_get_connections(mp_obj_t self) { @@ -321,7 +324,7 @@ const mp_obj_property_t bleio_adapter_connections_obj = { (mp_obj_t)&mp_const_none_obj }, }; -//| .. method:: connect(address, *, timeout, pair=False) +//| .. method:: connect(address, *, timeout) //| //| Attempts a connection to the device with the given address. //| @@ -331,24 +334,23 @@ const mp_obj_property_t bleio_adapter_connections_obj = { STATIC mp_obj_t bleio_adapter_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - enum { ARG_address, ARG_timeout, ARG_pair }; + enum { ARG_address, ARG_timeout }; static const mp_arg_t allowed_args[] = { { MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_pair, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = false } }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); if (!MP_OBJ_IS_TYPE(args[ARG_address].u_obj, &bleio_address_type)) { - mp_raise_ValueError(translate("Expected an Address")); + mp_raise_TypeError(translate("Expected an Address")); } bleio_address_obj_t *address = MP_OBJ_TO_PTR(args[ARG_address].u_obj); mp_float_t timeout = mp_obj_get_float(args[ARG_timeout].u_obj); - return common_hal_bleio_adapter_connect(self, address, timeout, args[ARG_pair].u_bool); + return common_hal_bleio_adapter_connect(self, address, timeout); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_adapter_connect_obj, 2, bleio_adapter_connect); diff --git a/shared-bindings/_bleio/Adapter.h b/shared-bindings/_bleio/Adapter.h index 2ff77f755..4340d82c1 100644 --- a/shared-bindings/_bleio/Adapter.h +++ b/shared-bindings/_bleio/Adapter.h @@ -55,6 +55,6 @@ void common_hal_bleio_adapter_stop_scan(bleio_adapter_obj_t *self); bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self); mp_obj_t common_hal_bleio_adapter_get_connections(bleio_adapter_obj_t *self); -mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout, bool pair); +mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H diff --git a/shared-bindings/_bleio/Characteristic.c b/shared-bindings/_bleio/Characteristic.c index d89da2a2f..7fcf274da 100644 --- a/shared-bindings/_bleio/Characteristic.c +++ b/shared-bindings/_bleio/Characteristic.c @@ -94,12 +94,12 @@ STATIC mp_obj_t bleio_characteristic_add_to_service(size_t n_args, const mp_obj_ const mp_obj_t service_obj = args[ARG_service].u_obj; if (!MP_OBJ_IS_TYPE(service_obj, &bleio_service_type)) { - mp_raise_ValueError(translate("Expected a Service")); + mp_raise_TypeError(translate("Expected a Service")); } const mp_obj_t uuid_obj = args[ARG_uuid].u_obj; if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) { - mp_raise_ValueError(translate("Expected a UUID")); + mp_raise_TypeError(translate("Expected a UUID")); } const bleio_characteristic_properties_t properties = args[ARG_properties].u_int; @@ -168,7 +168,7 @@ const mp_obj_property_t bleio_characteristic_properties_obj = { //| .. attribute:: uuid //| //| The UUID of this characteristic. (read-only) -//| +//| //| Will be ``None`` if the 128-bit UUID for this characteristic is not known. //| STATIC mp_obj_t bleio_characteristic_get_uuid(mp_obj_t self_in) { diff --git a/shared-bindings/_bleio/CharacteristicBuffer.c b/shared-bindings/_bleio/CharacteristicBuffer.c index 9cc708eb7..fc95d0d50 100644 --- a/shared-bindings/_bleio/CharacteristicBuffer.c +++ b/shared-bindings/_bleio/CharacteristicBuffer.c @@ -30,13 +30,14 @@ #include "py/runtime.h" #include "py/stream.h" +#include "shared-bindings/_bleio/__init__.h" #include "shared-bindings/_bleio/CharacteristicBuffer.h" #include "shared-bindings/_bleio/UUID.h" #include "shared-bindings/util.h" STATIC void raise_error_if_not_connected(bleio_characteristic_buffer_obj_t *self) { if (!common_hal_bleio_characteristic_buffer_connected(self)) { - mp_raise_ValueError(translate("Not connected")); + mp_raise_bleio_ConnectionError(translate("Not connected")); } } @@ -83,7 +84,7 @@ STATIC mp_obj_t bleio_characteristic_buffer_make_new(const mp_obj_type_t *type, } if (!MP_OBJ_IS_TYPE(characteristic, &bleio_characteristic_type)) { - mp_raise_ValueError(translate("Expected a Characteristic")); + mp_raise_TypeError(translate("Expected a Characteristic")); } bleio_characteristic_buffer_obj_t *self = m_new_obj(bleio_characteristic_buffer_obj_t); @@ -151,9 +152,6 @@ STATIC mp_uint_t bleio_characteristic_buffer_ioctl(mp_obj_t self_in, mp_uint_t r bleio_characteristic_buffer_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); raise_error_if_not_connected(self); - if (!common_hal_bleio_characteristic_buffer_connected(self)) { - mp_raise_ValueError(translate("Not connected")); - } mp_uint_t ret; if (request == MP_IOCTL_POLL) { mp_uint_t flags = arg; @@ -232,6 +230,7 @@ STATIC const mp_rom_map_elem_t bleio_characteristic_buffer_locals_dict_table[] = STATIC MP_DEFINE_CONST_DICT(bleio_characteristic_buffer_locals_dict, bleio_characteristic_buffer_locals_dict_table); STATIC const mp_stream_p_t characteristic_buffer_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = bleio_characteristic_buffer_read, .write = bleio_characteristic_buffer_write, .ioctl = bleio_characteristic_buffer_ioctl, diff --git a/shared-bindings/_bleio/Connection.c b/shared-bindings/_bleio/Connection.c index 1c6931b29..c157af365 100644 --- a/shared-bindings/_bleio/Connection.c +++ b/shared-bindings/_bleio/Connection.c @@ -36,6 +36,7 @@ #include "py/objproperty.h" #include "py/objstr.h" #include "py/runtime.h" +#include "shared-bindings/_bleio/__init__.h" #include "shared-bindings/_bleio/Adapter.h" #include "shared-bindings/_bleio/Address.h" #include "shared-bindings/_bleio/Characteristic.h" @@ -65,9 +66,9 @@ //| connection = _bleio.adapter.connect(my_entry.address, timeout=10) //| -STATIC void ensure_connected(bleio_connection_obj_t *self) { +void bleio_connection_ensure_connected(bleio_connection_obj_t *self) { if (!common_hal_bleio_connection_get_connected(self)) { - mp_raise_ValueError(translate("Connection has been disconnected and can no longer be used. Create a new connection.")); + mp_raise_bleio_ConnectionError(translate("Connection has been disconnected and can no longer be used. Create a new connection.")); } } @@ -79,18 +80,39 @@ STATIC void ensure_connected(bleio_connection_obj_t *self) { //| //| .. method:: disconnect() //| -//| Disconnects from the remote peripheral. +//| Disconnects from the remote peripheral. Does nothing if already disconnected. //| STATIC mp_obj_t bleio_connection_disconnect(mp_obj_t self_in) { bleio_connection_obj_t *self = MP_OBJ_TO_PTR(self_in); - ensure_connected(self); - + // common_hal_bleio_connection_disconnect() does nothing if already disconnected. common_hal_bleio_connection_disconnect(self->connection); - return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_connection_disconnect_obj, bleio_connection_disconnect); + +//| .. method:: pair(*, bond=True) +//| +//| Pair to the peer to improve security. +//| +STATIC mp_obj_t bleio_connection_pair(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + bleio_connection_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + enum { ARG_bond }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_bond, MP_ARG_BOOL, {.u_bool = true} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + bleio_connection_ensure_connected(self); + + common_hal_bleio_connection_pair(self->connection, args[ARG_bond].u_bool); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_connection_pair_obj, 1, bleio_connection_pair); + //| .. method:: discover_remote_services(service_uuids_whitelist=None) //| //| Do BLE discovery for all services or for the given service UUIDS, @@ -98,19 +120,19 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_connection_disconnect_obj, bleio_connecti //| `Connection.connected` must be True. //| //| :param iterable service_uuids_whitelist: -//| +//| //| an iterable of :py:class:~`UUID` objects for the services provided by the peripheral //| that you want to use. //| //| The peripheral may provide more services, but services not listed are ignored //| and will not be returned. //| -//| If service_uuids_whitelist is None, then all services will undergo discovery, which can be +//| If service_uuids_whitelist is None, then all services will undergo discovery, which can be //| slow. //| //| If the service UUID is 128-bit, or its characteristic UUID's are 128-bit, you //| you must have already created a :py:class:~`UUID` object for that UUID in order for the -//| service or characteristic to be discovered. Creating the UUID causes the UUID to be +//| service or characteristic to be discovered. Creating the UUID causes the UUID to be //| registered for use. (This restriction may be lifted in the future.) //| //| :return: A tuple of `_bleio.Service` objects provided by the remote peripheral. @@ -126,7 +148,7 @@ STATIC mp_obj_t bleio_connection_discover_remote_services(mp_uint_t n_args, cons mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - ensure_connected(self); + bleio_connection_ensure_connected(self); return MP_OBJ_FROM_PTR(common_hal_bleio_connection_discover_remote_services( self, @@ -136,7 +158,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_connection_discover_remote_services_obj, //| .. attribute:: connected //| -//| True if connected to a remote peer. +//| True if connected to the remote peer. //| STATIC mp_obj_t bleio_connection_get_connected(mp_obj_t self_in) { bleio_connection_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -152,13 +174,76 @@ const mp_obj_property_t bleio_connection_connected_obj = { (mp_obj_t)&mp_const_none_obj }, }; + +//| .. attribute:: paired +//| +//| True if paired to the remote peer. +//| +STATIC mp_obj_t bleio_connection_get_paired(mp_obj_t self_in) { + bleio_connection_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_bool(common_hal_bleio_connection_get_paired(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_connection_get_paired_obj, bleio_connection_get_paired); + +const mp_obj_property_t bleio_connection_paired_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_connection_get_paired_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + + +//| .. attribute:: connection_interval +//| +//| Time between transmissions in milliseconds. Will be multiple of 1.25ms. Lower numbers +//| increase speed and decrease latency but increase power consumption. +//| +//| When setting connection_interval, the peer may reject the new interval and +//| `connection_interval` will then remain the same. +//| +//| Apple has additional guidelines that dictate should be a multiple of 15ms except if HID is +//| available. When HID is available Apple devices may accept 11.25ms intervals. +//| +//| +STATIC mp_obj_t bleio_connection_get_connection_interval(mp_obj_t self_in) { + bleio_connection_obj_t *self = MP_OBJ_TO_PTR(self_in); + + bleio_connection_ensure_connected(self); + return mp_obj_new_float(common_hal_bleio_connection_get_connection_interval(self->connection)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_connection_get_connection_interval_obj, bleio_connection_get_connection_interval); + +STATIC mp_obj_t bleio_connection_set_connection_interval(mp_obj_t self_in, mp_obj_t interval_in) { + bleio_connection_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_float_t interval = mp_obj_get_float(interval_in); + + bleio_connection_ensure_connected(self); + common_hal_bleio_connection_set_connection_interval(self->connection, interval); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_connection_set_connection_interval_obj, bleio_connection_set_connection_interval); + +const mp_obj_property_t bleio_connection_connection_interval_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_connection_get_connection_interval_obj, + (mp_obj_t)&bleio_connection_set_connection_interval_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + STATIC const mp_rom_map_elem_t bleio_connection_locals_dict_table[] = { // Methods + { MP_ROM_QSTR(MP_QSTR_pair), MP_ROM_PTR(&bleio_connection_pair_obj) }, { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_connection_disconnect_obj) }, { MP_ROM_QSTR(MP_QSTR_discover_remote_services), MP_ROM_PTR(&bleio_connection_discover_remote_services_obj) }, // Properties - { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_connection_connected_obj) }, + { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_connection_connected_obj) }, + { MP_ROM_QSTR(MP_QSTR_paired), MP_ROM_PTR(&bleio_connection_paired_obj) }, + { MP_ROM_QSTR(MP_QSTR_connection_interval), MP_ROM_PTR(&bleio_connection_connection_interval_obj) }, + }; STATIC MP_DEFINE_CONST_DICT(bleio_connection_locals_dict, bleio_connection_locals_dict_table); diff --git a/shared-bindings/_bleio/Connection.h b/shared-bindings/_bleio/Connection.h index 5de6730c9..c6f260160 100644 --- a/shared-bindings/_bleio/Connection.h +++ b/shared-bindings/_bleio/Connection.h @@ -34,8 +34,15 @@ extern const mp_obj_type_t bleio_connection_type; +extern void common_hal_bleio_connection_pair(bleio_connection_internal_t *self, bool bond); extern void common_hal_bleio_connection_disconnect(bleio_connection_internal_t *self); extern bool common_hal_bleio_connection_get_connected(bleio_connection_obj_t *self); +extern bool common_hal_bleio_connection_get_paired(bleio_connection_obj_t *self); extern mp_obj_tuple_t *common_hal_bleio_connection_discover_remote_services(bleio_connection_obj_t *self, mp_obj_t service_uuids_whitelist); +mp_float_t common_hal_bleio_connection_get_connection_interval(bleio_connection_internal_t *self); +void common_hal_bleio_connection_set_connection_interval(bleio_connection_internal_t *self, mp_float_t new_interval); + +void bleio_connection_ensure_connected(bleio_connection_obj_t *self); + #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CONNECTION_H diff --git a/shared-bindings/_bleio/Descriptor.c b/shared-bindings/_bleio/Descriptor.c index 45a95903e..f7b6b5bbf 100644 --- a/shared-bindings/_bleio/Descriptor.c +++ b/shared-bindings/_bleio/Descriptor.c @@ -89,12 +89,12 @@ STATIC mp_obj_t bleio_descriptor_add_to_characteristic(size_t n_args, const mp_o const mp_obj_t characteristic_obj = args[ARG_characteristic].u_obj; if (!MP_OBJ_IS_TYPE(characteristic_obj, &bleio_characteristic_type)) { - mp_raise_ValueError(translate("Expected a Characteristic")); + mp_raise_TypeError(translate("Expected a Characteristic")); } const mp_obj_t uuid_obj = args[ARG_uuid].u_obj; if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) { - mp_raise_ValueError(translate("Expected a UUID")); + mp_raise_TypeError(translate("Expected a UUID")); } const bleio_attribute_security_mode_t read_perm = args[ARG_read_perm].u_int; diff --git a/shared-bindings/_bleio/Service.c b/shared-bindings/_bleio/Service.c index 3e1ad7088..bc242bc36 100644 --- a/shared-bindings/_bleio/Service.c +++ b/shared-bindings/_bleio/Service.c @@ -64,7 +64,7 @@ STATIC mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t uuid_obj = args[ARG_uuid].u_obj; if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) { - mp_raise_ValueError(translate("Expected a UUID")); + mp_raise_TypeError(translate("Expected a UUID")); } const bool is_secondary = args[ARG_secondary].u_bool; @@ -136,7 +136,7 @@ const mp_obj_property_t bleio_service_secondary_obj = { //| .. attribute:: uuid //| //| The UUID of this service. (read-only) -//| +//| //| Will be ``None`` if the 128-bit UUID for this service is not known. //| STATIC mp_obj_t bleio_service_get_uuid(mp_obj_t self_in) { diff --git a/shared-bindings/_bleio/__init__.c b/shared-bindings/_bleio/__init__.c index 0c6ebb973..ba2454da4 100644 --- a/shared-bindings/_bleio/__init__.c +++ b/shared-bindings/_bleio/__init__.c @@ -26,6 +26,8 @@ * THE SOFTWARE. */ +#include "py/objexcept.h" +#include "py/runtime.h" #include "shared-bindings/_bleio/__init__.h" #include "shared-bindings/_bleio/Address.h" #include "shared-bindings/_bleio/Attribute.h" @@ -78,7 +80,58 @@ //| This object is the sole instance of `_bleio.Adapter`. //| +//| .. class:: BluetoothError(Exception) +//| +//| Catch all exception for Bluetooth related errors. +//| +MP_DEFINE_BLEIO_EXCEPTION(BluetoothError, Exception) + +NORETURN void mp_raise_bleio_BluetoothError(const compressed_string_t* fmt, ...) { + va_list argptr; + va_start(argptr,fmt); + mp_obj_t exception = mp_obj_new_exception_msg_vlist(&mp_type_bleio_BluetoothError, fmt, argptr); + va_end(argptr); + nlr_raise(exception); +} + +//| .. class:: ConnectionError(BluetoothError) +//| +//| Raised when a connection is unavailable. +//| +MP_DEFINE_BLEIO_EXCEPTION(ConnectionError, bleio_BluetoothError) +NORETURN void mp_raise_bleio_ConnectionError(const compressed_string_t* fmt, ...) { + va_list argptr; + va_start(argptr,fmt); + mp_obj_t exception = mp_obj_new_exception_msg_vlist(&mp_type_bleio_ConnectionError, fmt, argptr); + va_end(argptr); + nlr_raise(exception); +} + +//| .. class:: RoleError(BluetoothError) +//| +//| Raised when a resource is used as the mismatched role. For example, if a local CCCD is +//| attempted to be set but they can only be set when remote. +//| +MP_DEFINE_BLEIO_EXCEPTION(RoleError, bleio_BluetoothError) +NORETURN void mp_raise_bleio_RoleError(const compressed_string_t* msg) { + mp_raise_msg(&mp_type_bleio_RoleError, msg); +} + +//| .. class:: SecurityError(BluetoothError) +//| +//| Raised when a security related error occurs. +//| +MP_DEFINE_BLEIO_EXCEPTION(SecurityError, bleio_BluetoothError) +NORETURN void mp_raise_bleio_SecurityError(const compressed_string_t* fmt, ...) { + va_list argptr; + va_start(argptr,fmt); + mp_obj_t exception = mp_obj_new_exception_msg_vlist(&mp_type_bleio_SecurityError, fmt, argptr); + va_end(argptr); + nlr_raise(exception); +} + STATIC const mp_rom_map_elem_t bleio_module_globals_table[] = { + // Name must be the first entry so that the exception printing below is correct. { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__bleio) }, { MP_ROM_QSTR(MP_QSTR_Adapter), MP_ROM_PTR(&bleio_adapter_type) }, { MP_ROM_QSTR(MP_QSTR_Address), MP_ROM_PTR(&bleio_address_type) }, @@ -94,10 +147,26 @@ STATIC const mp_rom_map_elem_t bleio_module_globals_table[] = { // Properties { MP_ROM_QSTR(MP_QSTR_adapter), MP_ROM_PTR(&common_hal_bleio_adapter_obj) }, + + // Errors + { MP_ROM_QSTR(MP_QSTR_BluetoothError), MP_ROM_PTR(&mp_type_bleio_BluetoothError) }, + { MP_ROM_QSTR(MP_QSTR_ConnectionError), MP_ROM_PTR(&mp_type_bleio_ConnectionError) }, + { MP_ROM_QSTR(MP_QSTR_RoleError), MP_ROM_PTR(&mp_type_bleio_RoleError) }, + { MP_ROM_QSTR(MP_QSTR_SecurityError), MP_ROM_PTR(&mp_type_bleio_SecurityError) }, }; STATIC MP_DEFINE_CONST_DICT(bleio_module_globals, bleio_module_globals_table); +void bleio_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { + mp_print_kind_t k = kind & ~PRINT_EXC_SUBCLASS; + bool is_subclass = kind & PRINT_EXC_SUBCLASS; + if (!is_subclass && (k == PRINT_EXC)) { + mp_print_str(print, qstr_str(MP_OBJ_QSTR_VALUE(bleio_module_globals_table[0].value))); + mp_print_str(print, "."); + } + mp_obj_exception_print(print, o_in, kind); +} + const mp_obj_module_t bleio_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&bleio_module_globals, diff --git a/shared-bindings/_bleio/__init__.h b/shared-bindings/_bleio/__init__.h index 92c695fa6..5256bdaa0 100644 --- a/shared-bindings/_bleio/__init__.h +++ b/shared-bindings/_bleio/__init__.h @@ -38,6 +38,28 @@ extern bleio_adapter_obj_t common_hal_bleio_adapter_obj; +void bleio_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind); + +#define MP_DEFINE_BLEIO_EXCEPTION(exc_name, base_name) \ +const mp_obj_type_t mp_type_bleio_ ## exc_name = { \ + { &mp_type_type }, \ + .name = MP_QSTR_ ## exc_name, \ + .print = bleio_exception_print, \ + .make_new = mp_obj_exception_make_new, \ + .attr = mp_obj_exception_attr, \ + .parent = &mp_type_ ## base_name, \ +}; + +extern const mp_obj_type_t mp_type_bleio_BluetoothError; +extern const mp_obj_type_t mp_type_bleio_ConnectionError; +extern const mp_obj_type_t mp_type_bleio_RoleError; +extern const mp_obj_type_t mp_type_bleio_SecurityError; + +NORETURN void mp_raise_bleio_BluetoothError(const compressed_string_t* msg, ...); +NORETURN void mp_raise_bleio_ConnectionError(const compressed_string_t* msg, ...); +NORETURN void mp_raise_bleio_RoleError(const compressed_string_t* msg); +NORETURN void mp_raise_bleio_SecurityError(const compressed_string_t* msg, ...); + void common_hal_bleio_check_connected(uint16_t conn_handle); uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device); diff --git a/shared-bindings/audiobusio/I2SOut.c b/shared-bindings/audiobusio/I2SOut.c index 81383c777..8f7382fde 100644 --- a/shared-bindings/audiobusio/I2SOut.c +++ b/shared-bindings/audiobusio/I2SOut.c @@ -117,7 +117,7 @@ STATIC mp_obj_t audiobusio_i2sout_make_new(const mp_obj_type_t *type, size_t n_a assert_pin(data_obj, false); const mcu_pin_obj_t *data = MP_OBJ_TO_PTR(data_obj); - audiobusio_i2sout_obj_t *self = m_new_obj(audiobusio_i2sout_obj_t); + audiobusio_i2sout_obj_t *self = m_new_obj_with_finaliser(audiobusio_i2sout_obj_t); self->base.type = &audiobusio_i2sout_type; common_hal_audiobusio_i2sout_construct(self, bit_clock, word_select, data, args[ARG_left_justified].u_bool); @@ -268,6 +268,7 @@ const mp_obj_property_t audiobusio_i2sout_paused_obj = { STATIC const mp_rom_map_elem_t audiobusio_i2sout_locals_dict_table[] = { // Methods + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&audiobusio_i2sout_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiobusio_i2sout_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audiobusio_i2sout___exit___obj) }, diff --git a/shared-bindings/audiocore/RawSample.c b/shared-bindings/audiocore/RawSample.c index 07f8c683f..87d410ea1 100644 --- a/shared-bindings/audiocore/RawSample.c +++ b/shared-bindings/audiocore/RawSample.c @@ -180,9 +180,20 @@ STATIC const mp_rom_map_elem_t audioio_rawsample_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(audioio_rawsample_locals_dict, audioio_rawsample_locals_dict_table); +STATIC const audiosample_p_t audioio_rawsample_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) + .sample_rate = (audiosample_sample_rate_fun)common_hal_audioio_rawsample_get_sample_rate, + .bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_audioio_rawsample_get_bits_per_sample, + .channel_count = (audiosample_channel_count_fun)common_hal_audioio_rawsample_get_channel_count, + .reset_buffer = (audiosample_reset_buffer_fun)audioio_rawsample_reset_buffer, + .get_buffer = (audiosample_get_buffer_fun)audioio_rawsample_get_buffer, + .get_buffer_structure = (audiosample_get_buffer_structure_fun)audioio_rawsample_get_buffer_structure, +}; + const mp_obj_type_t audioio_rawsample_type = { { &mp_type_type }, .name = MP_QSTR_RawSample, .make_new = audioio_rawsample_make_new, .locals_dict = (mp_obj_dict_t*)&audioio_rawsample_locals_dict, + .protocol = &audioio_rawsample_proto, }; diff --git a/shared-bindings/audiocore/RawSample.h b/shared-bindings/audiocore/RawSample.h index b02778cad..61f61a066 100644 --- a/shared-bindings/audiocore/RawSample.h +++ b/shared-bindings/audiocore/RawSample.h @@ -39,6 +39,8 @@ void common_hal_audioio_rawsample_construct(audioio_rawsample_obj_t* self, void common_hal_audioio_rawsample_deinit(audioio_rawsample_obj_t* self); bool common_hal_audioio_rawsample_deinited(audioio_rawsample_obj_t* self); uint32_t common_hal_audioio_rawsample_get_sample_rate(audioio_rawsample_obj_t* self); +uint8_t common_hal_audioio_rawsample_get_bits_per_sample(audioio_rawsample_obj_t* self); +uint8_t common_hal_audioio_rawsample_get_channel_count(audioio_rawsample_obj_t* self); void common_hal_audioio_rawsample_set_sample_rate(audioio_rawsample_obj_t* self, uint32_t sample_rate); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_RAWSAMPLE_H diff --git a/shared-bindings/audiocore/WaveFile.c b/shared-bindings/audiocore/WaveFile.c index 1b3a94ff3..178d2a139 100644 --- a/shared-bindings/audiocore/WaveFile.c +++ b/shared-bindings/audiocore/WaveFile.c @@ -206,9 +206,21 @@ STATIC const mp_rom_map_elem_t audioio_wavefile_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(audioio_wavefile_locals_dict, audioio_wavefile_locals_dict_table); +STATIC const audiosample_p_t audioio_wavefile_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) + .sample_rate = (audiosample_sample_rate_fun)common_hal_audioio_wavefile_get_sample_rate, + .bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_audioio_wavefile_get_bits_per_sample, + .channel_count = (audiosample_channel_count_fun)common_hal_audioio_wavefile_get_channel_count, + .reset_buffer = (audiosample_reset_buffer_fun)audioio_wavefile_reset_buffer, + .get_buffer = (audiosample_get_buffer_fun)audioio_wavefile_get_buffer, + .get_buffer_structure = (audiosample_get_buffer_structure_fun)audioio_wavefile_get_buffer_structure, +}; + + const mp_obj_type_t audioio_wavefile_type = { { &mp_type_type }, .name = MP_QSTR_WaveFile, .make_new = audioio_wavefile_make_new, .locals_dict = (mp_obj_dict_t*)&audioio_wavefile_locals_dict, + .protocol = &audioio_wavefile_proto, }; diff --git a/shared-bindings/audiomixer/Mixer.c b/shared-bindings/audiomixer/Mixer.c index ed7b95d9e..03ffb9373 100644 --- a/shared-bindings/audiomixer/Mixer.c +++ b/shared-bindings/audiomixer/Mixer.c @@ -291,9 +291,20 @@ STATIC const mp_rom_map_elem_t audiomixer_mixer_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(audiomixer_mixer_locals_dict, audiomixer_mixer_locals_dict_table); +STATIC const audiosample_p_t audiomixer_mixer_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) + .sample_rate = (audiosample_sample_rate_fun)common_hal_audiomixer_mixer_get_sample_rate, + .bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_audiomixer_mixer_get_bits_per_sample, + .channel_count = (audiosample_channel_count_fun)common_hal_audiomixer_mixer_get_channel_count, + .reset_buffer = (audiosample_reset_buffer_fun)audiomixer_mixer_reset_buffer, + .get_buffer = (audiosample_get_buffer_fun)audiomixer_mixer_get_buffer, + .get_buffer_structure = (audiosample_get_buffer_structure_fun)audiomixer_mixer_get_buffer_structure, +}; + const mp_obj_type_t audiomixer_mixer_type = { { &mp_type_type }, .name = MP_QSTR_Mixer, .make_new = audiomixer_mixer_make_new, .locals_dict = (mp_obj_dict_t*)&audiomixer_mixer_locals_dict, + .protocol = &audiomixer_mixer_proto, }; diff --git a/shared-bindings/audiomixer/Mixer.h b/shared-bindings/audiomixer/Mixer.h index 9eabbf61d..a99e1bf62 100644 --- a/shared-bindings/audiomixer/Mixer.h +++ b/shared-bindings/audiomixer/Mixer.h @@ -47,5 +47,7 @@ bool common_hal_audiomixer_mixer_deinited(audiomixer_mixer_obj_t* self); bool common_hal_audiomixer_mixer_get_playing(audiomixer_mixer_obj_t* self); uint32_t common_hal_audiomixer_mixer_get_sample_rate(audiomixer_mixer_obj_t* self); +uint8_t common_hal_audiomixer_mixer_get_channel_count(audiomixer_mixer_obj_t* self); +uint8_t common_hal_audiomixer_mixer_get_bits_per_sample(audiomixer_mixer_obj_t* self); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOMIXER_MIXER_H diff --git a/shared-bindings/board/__init__.c b/shared-bindings/board/__init__.c index 47e2d64bc..3dda59fb8 100644 --- a/shared-bindings/board/__init__.c +++ b/shared-bindings/board/__init__.c @@ -93,6 +93,12 @@ MP_DEFINE_CONST_FUN_OBJ_0(board_spi_obj, board_spi); //| //| Returns the `busio.UART` object for the board designated TX and RX pins. It is a singleton. //| +//| The object created uses the default parameter values for `busio.UART`. If you need to set +//| parameters that are not changeable after creation, such as ``receiver_buffer_size``, +//| do not use `board.UART()`; instead create a `busio.UART` object explicitly with the +//| desired parameters. +//| +//| #if BOARD_UART mp_obj_t board_uart(void) { mp_obj_t singleton = common_hal_board_get_uart(); diff --git a/shared-bindings/busio/UART.c b/shared-bindings/busio/UART.c index c7eef8c43..1fc81e78e 100644 --- a/shared-bindings/busio/UART.c +++ b/shared-bindings/busio/UART.c @@ -57,7 +57,7 @@ //| :param int bits: the number of bits per byte, 7, 8 or 9. //| :param Parity parity: the parity used for error checking. //| :param int stop: the number of stop bits, 1 or 2. -//| :param float timeout: the timeout in seconds to wait for the first character and between subsequent characters. Raises ``ValueError`` if timeout >100 seconds. +//| :param float timeout: the timeout in seconds to wait for the first character and between subsequent characters when reading. Raises ``ValueError`` if timeout >100 seconds. //| :param int receiver_buffer_size: the character length of the read buffer (0 to disable). (When a character is 9 bits the buffer will be 2 * receiver_buffer_size bytes.) //| //| *New in CircuitPython 4.0:* ``timeout`` has incompatibly changed units from milliseconds to seconds. @@ -69,6 +69,12 @@ typedef struct { extern const busio_uart_parity_obj_t busio_uart_parity_even_obj; extern const busio_uart_parity_obj_t busio_uart_parity_odd_obj; +STATIC void validate_timeout(mp_float_t timeout) { + if (timeout < (mp_float_t) 0.0f || timeout > (mp_float_t) 100.0f) { + mp_raise_ValueError(translate("timeout must be 0.0-100.0 seconds")); + } +} + STATIC mp_obj_t busio_uart_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // Always initially allocate the UART object within the long-lived heap. // This is needed to avoid crashes with certain UART implementations which @@ -116,9 +122,7 @@ STATIC mp_obj_t busio_uart_make_new(const mp_obj_type_t *type, size_t n_args, co } mp_float_t timeout = mp_obj_get_float(args[ARG_timeout].u_obj); - if (timeout > (mp_float_t)100.0) { - mp_raise_ValueError(translate("timeout >100 (units are now seconds, not msecs)")); - } + validate_timeout(timeout); common_hal_busio_uart_construct(self, tx, rx, args[ARG_baudrate].u_int, bits, parity, stop, timeout, @@ -286,6 +290,35 @@ const mp_obj_property_t busio_uart_in_waiting_obj = { (mp_obj_t)&mp_const_none_obj}, }; +//| .. attribute:: timeout +//| +//| The current timeout, in seconds (float). +//| +STATIC mp_obj_t busio_uart_obj_get_timeout(mp_obj_t self_in) { + busio_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_float(common_hal_busio_uart_get_timeout(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(busio_uart_get_timeout_obj, busio_uart_obj_get_timeout); + +STATIC mp_obj_t busio_uart_obj_set_timeout(mp_obj_t self_in, mp_obj_t timeout) { + busio_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + mp_float_t timeout_float = mp_obj_get_float(timeout); + validate_timeout(timeout_float); + common_hal_busio_uart_set_timeout(self, timeout_float); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(busio_uart_set_timeout_obj, busio_uart_obj_set_timeout); + + +const mp_obj_property_t busio_uart_timeout_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&busio_uart_get_timeout_obj, + (mp_obj_t)&busio_uart_set_timeout_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + //| .. method:: reset_input_buffer() //| //| Discard any unread characters in the input buffer. @@ -355,8 +388,9 @@ STATIC const mp_rom_map_elem_t busio_uart_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_reset_input_buffer), MP_ROM_PTR(&busio_uart_reset_input_buffer_obj) }, // Properties - { MP_ROM_QSTR(MP_QSTR_baudrate), MP_ROM_PTR(&busio_uart_baudrate_obj) }, - { MP_ROM_QSTR(MP_QSTR_in_waiting), MP_ROM_PTR(&busio_uart_in_waiting_obj) }, + { MP_ROM_QSTR(MP_QSTR_baudrate), MP_ROM_PTR(&busio_uart_baudrate_obj) }, + { MP_ROM_QSTR(MP_QSTR_in_waiting), MP_ROM_PTR(&busio_uart_in_waiting_obj) }, + { MP_ROM_QSTR(MP_QSTR_timeout), MP_ROM_PTR(&busio_uart_timeout_obj) }, // Nested Enum-like Classes. { MP_ROM_QSTR(MP_QSTR_Parity), MP_ROM_PTR(&busio_uart_parity_type) }, @@ -364,6 +398,7 @@ STATIC const mp_rom_map_elem_t busio_uart_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(busio_uart_locals_dict, busio_uart_locals_dict_table); STATIC const mp_stream_p_t uart_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = busio_uart_read, .write = busio_uart_write, .ioctl = busio_uart_ioctl, diff --git a/shared-bindings/busio/UART.h b/shared-bindings/busio/UART.h index 776a996be..cfd2c800c 100644 --- a/shared-bindings/busio/UART.h +++ b/shared-bindings/busio/UART.h @@ -57,7 +57,8 @@ extern size_t common_hal_busio_uart_write(busio_uart_obj_t *self, extern uint32_t common_hal_busio_uart_get_baudrate(busio_uart_obj_t *self); extern void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrate); - +extern mp_float_t common_hal_busio_uart_get_timeout(busio_uart_obj_t *self); +extern void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeout); extern uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self); extern void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self); diff --git a/shared-bindings/displayio/OnDiskBitmap.c b/shared-bindings/displayio/OnDiskBitmap.c index bf00ef855..f7e2bf693 100644 --- a/shared-bindings/displayio/OnDiskBitmap.c +++ b/shared-bindings/displayio/OnDiskBitmap.c @@ -59,7 +59,7 @@ //| //| with open("/sample.bmp", "rb") as f: //| odb = displayio.OnDiskBitmap(f) -//| face = displayio.TileGrid(odb, pixel_shader=displayio.ColorConverter(), position=(0,0)) +//| face = displayio.TileGrid(odb, pixel_shader=displayio.ColorConverter()) //| splash.append(face) //| # Wait for the image to load. //| board.DISPLAY.wait_for_frame() diff --git a/shared-bindings/microcontroller/Pin.h b/shared-bindings/microcontroller/Pin.h index ed831b258..2d15dd5c5 100644 --- a/shared-bindings/microcontroller/Pin.h +++ b/shared-bindings/microcontroller/Pin.h @@ -37,5 +37,7 @@ void assert_pin(mp_obj_t obj, bool none_ok); void assert_pin_free(const mcu_pin_obj_t* pin); bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t* pin); +void common_hal_never_reset_pin(const mcu_pin_obj_t* pin); +void common_hal_reset_pin(const mcu_pin_obj_t* pin); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER_PIN_H diff --git a/shared-bindings/socket/__init__.c b/shared-bindings/socket/__init__.c index 6d04a9893..2d6c16e90 100644 --- a/shared-bindings/socket/__init__.c +++ b/shared-bindings/socket/__init__.c @@ -500,6 +500,7 @@ mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int * } STATIC const mp_stream_p_t socket_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .ioctl = socket_ioctl, .is_text = false, }; diff --git a/shared-bindings/terminalio/Terminal.c b/shared-bindings/terminalio/Terminal.c index cdde672d3..9c01fba20 100644 --- a/shared-bindings/terminalio/Terminal.c +++ b/shared-bindings/terminalio/Terminal.c @@ -112,6 +112,7 @@ STATIC const mp_rom_map_elem_t terminalio_terminal_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(terminalio_terminal_locals_dict, terminalio_terminal_locals_dict_table); STATIC const mp_stream_p_t terminalio_terminal_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = NULL, .write = terminalio_terminal_write, .ioctl = terminalio_terminal_ioctl, diff --git a/shared-bindings/time/__init__.c b/shared-bindings/time/__init__.c index 2654de09a..b3e4604b5 100644 --- a/shared-bindings/time/__init__.c +++ b/shared-bindings/time/__init__.c @@ -85,9 +85,9 @@ MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_obj, time_sleep); #if MICROPY_PY_COLLECTIONS mp_obj_t struct_time_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { if (n_args != 1 || (kw_args != NULL && kw_args->used > 0)) { - mp_raise_TypeError(translate("time.struct_time() takes exactly 1 argument")); + return namedtuple_make_new(type, n_args, args, kw_args); } - if (!MP_OBJ_IS_TYPE(args[0], &mp_type_tuple) || ((mp_obj_tuple_t*) MP_OBJ_TO_PTR(args[0]))->len != 9) { + if (mp_obj_get_type(args[0])->getiter != mp_obj_tuple_getiter || ((mp_obj_tuple_t*) MP_OBJ_TO_PTR(args[0]))->len != 9) { mp_raise_TypeError(translate("time.struct_time() takes a 9-sequence")); } diff --git a/shared-bindings/usb_midi/PortIn.c b/shared-bindings/usb_midi/PortIn.c index 356a81d52..e2df56e95 100644 --- a/shared-bindings/usb_midi/PortIn.c +++ b/shared-bindings/usb_midi/PortIn.c @@ -107,6 +107,7 @@ STATIC const mp_rom_map_elem_t usb_midi_portin_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(usb_midi_portin_locals_dict, usb_midi_portin_locals_dict_table); STATIC const mp_stream_p_t usb_midi_portin_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = usb_midi_portin_read, .write = NULL, .ioctl = usb_midi_portin_ioctl, diff --git a/shared-bindings/usb_midi/PortOut.c b/shared-bindings/usb_midi/PortOut.c index 6f4ce6716..e3eddfaf5 100644 --- a/shared-bindings/usb_midi/PortOut.c +++ b/shared-bindings/usb_midi/PortOut.c @@ -89,6 +89,7 @@ STATIC const mp_rom_map_elem_t usb_midi_portout_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(usb_midi_portout_locals_dict, usb_midi_portout_locals_dict_table); STATIC const mp_stream_p_t usb_midi_portout_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = NULL, .write = usb_midi_portout_write, .ioctl = usb_midi_portout_ioctl, |
