diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ceb691a15b..6bb9612f81 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -234,6 +234,7 @@ jobs: - "makerdiary_nrf52840_m2_devkit" - "makerdiary_nrf52840_mdk" - "makerdiary_nrf52840_mdk_usb_dongle" + - "matrixportal_m4" - "meowbit_v121" - "meowmeow" - "metro_m0_express" @@ -408,8 +409,11 @@ jobs: fail-fast: false matrix: board: + - "electroniccats_bastwifi" + - "espressif_kaluga_1" - "espressif_saola_1_wroom" - "espressif_saola_1_wrover" + - "microdev_micro_s2" - "unexpectedmaker_feathers2" steps: @@ -430,6 +434,11 @@ jobs: with: path: ${{ github.workspace }}/.idf_tools key: ${{ runner.os }}-idf-tools-${{ hashFiles('.git/modules/ports/esp32s2/esp-idf/HEAD') }}-20200801 + - name: Clone IDF submodules + run: | + (cd $IDF_PATH && git submodule update --init) + env: + IDF_PATH: ${{ github.workspace }}/ports/esp32s2/esp-idf - name: Install IDF tools run: | $IDF_PATH/tools/idf_tools.py --non-interactive install required diff --git a/conf.py b/conf.py index 4a8b72584e..256ca922c7 100644 --- a/conf.py +++ b/conf.py @@ -42,6 +42,9 @@ master_doc = 'docs/index' # Grab the JSON values to use while building the module support matrix # in 'shared-bindings/index.rst' +# The stubs must be built before we calculate the shared bindings matrix +subprocess.check_output(["make", "stubs"]) + #modules_support_matrix = shared_bindings_matrix.support_matrix_excluded_boards() modules_support_matrix = shared_bindings_matrix.support_matrix_by_board() @@ -77,7 +80,6 @@ source_suffix = { '.md': 'markdown', } -subprocess.check_output(["make", "stubs"]) extensions.append('autoapi.extension') autoapi_type = 'python' diff --git a/devices/ble_hci/common-hal/_bleio/Adapter.c b/devices/ble_hci/common-hal/_bleio/Adapter.c new file mode 100644 index 0000000000..559b586de3 --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/Adapter.c @@ -0,0 +1,958 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Dan Halbert for Adafruit Industries + * Copyright (c) 2016 Glenn Ruben Bakke + * Copyright (c) 2018 Artur Pacholec + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include + +#include "hci.h" + +#include "py/gc.h" +#include "py/mphal.h" +#include "py/objstr.h" +#include "py/runtime.h" +#include "supervisor/shared/safe_mode.h" +#include "supervisor/shared/tick.h" +#include "supervisor/usb.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" +#include "shared-bindings/_bleio/Service.h" +#include "shared-bindings/nvm/ByteArray.h" +#include "shared-bindings/_bleio/Connection.h" +#include "shared-bindings/_bleio/ScanEntry.h" +#include "shared-bindings/time/__init__.h" + +#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION)) +#define SEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000000) / (RESOLUTION)) +#define UNITS_TO_SEC(TIME, RESOLUTION) (((TIME) * (RESOLUTION)) / 1000000) +// 0.625 msecs (625 usecs) +#define ADV_INTERVAL_UNIT_FLOAT_SECS (0.000625) +// Microseconds is the base unit. The macros above know that. +#define UNIT_0_625_MS (625) +#define UNIT_1_25_MS (1250) +#define UNIT_10_MS (10000) + +#define MAX_ADVERTISEMENT_SIZE (31) + +// TODO make this settable from Python. +#define DEFAULT_TX_POWER 0 // 0 dBm +#define MAX_ANONYMOUS_ADV_TIMEOUT_SECS (60*15) +#define MAX_LIMITED_DISCOVERABLE_ADV_TIMEOUT_SECS (180) + +#define BLE_MIN_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_0_625_MS) +#define BLE_MAX_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_0_625_MS) +#define BLE_SLAVE_LATENCY 0 +#define BLE_CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) + +bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT]; + +STATIC void add_generic_services(bleio_adapter_obj_t *adapter) { + // Create Generic Access UUID, Service, and Characteristics. + + // Generic Access Service setup. + + bleio_uuid_obj_t *generic_access_service_uuid = m_new_obj(bleio_uuid_obj_t); + generic_access_service_uuid->base.type = &bleio_uuid_type; + common_hal_bleio_uuid_construct(generic_access_service_uuid, 0x1800, NULL); + + bleio_uuid_obj_t *device_name_characteristic_uuid = m_new_obj(bleio_uuid_obj_t); + device_name_characteristic_uuid->base.type = &bleio_uuid_type; + common_hal_bleio_uuid_construct(device_name_characteristic_uuid, 0x2A00, NULL); + + bleio_uuid_obj_t *appearance_characteristic_uuid = m_new_obj(bleio_uuid_obj_t); + appearance_characteristic_uuid->base.type = &bleio_uuid_type; + common_hal_bleio_uuid_construct(appearance_characteristic_uuid, 0x2A01, NULL); + + // Not implemented: + // Peripheral Preferred Connection Parameters + // Central Address Resolution + + bleio_service_obj_t *generic_access_service = m_new_obj(bleio_service_obj_t); + generic_access_service->base.type = &bleio_service_type; + common_hal_bleio_service_construct(generic_access_service, generic_access_service_uuid, false); + + adapter->device_name_characteristic = m_new_obj(bleio_characteristic_obj_t); + adapter->device_name_characteristic->base.type = &bleio_characteristic_type; + + char generic_name[] = { 'C', 'I', 'R', 'C', 'U', 'I', 'T', 'P', 'Y', 'n', 'n', 'n', 'n' }; + mp_buffer_info_t generic_name_bufinfo = { + .buf = generic_name, + .len = sizeof(generic_name), + }; + + // Will be added to service by constructor. + common_hal_bleio_characteristic_construct( + adapter->device_name_characteristic, + generic_access_service, + BLE_GATT_HANDLE_INVALID, + device_name_characteristic_uuid, + CHAR_PROP_READ, + SECURITY_MODE_OPEN, + SECURITY_MODE_NO_ACCESS, + 248, // max length, from Bluetooth spec + false, // not fixed length + &generic_name_bufinfo + ); + + uint16_t zero_16 = 0; + mp_buffer_info_t zero_16_value = { + .buf = &zero_16, + .len = sizeof(zero_16), + }; + + adapter->appearance_characteristic = m_new_obj(bleio_characteristic_obj_t); + adapter->appearance_characteristic->base.type = &bleio_characteristic_type; + + common_hal_bleio_characteristic_construct( + adapter->appearance_characteristic, + generic_access_service, + BLE_GATT_HANDLE_INVALID, + appearance_characteristic_uuid, + CHAR_PROP_READ, + SECURITY_MODE_OPEN, + SECURITY_MODE_NO_ACCESS, + 2, // max length, from Bluetooth spec + true, // fixed length + &zero_16_value + ); + + // Generic Attribute Service setup. + + bleio_uuid_obj_t *generic_attribute_service_uuid = m_new_obj(bleio_uuid_obj_t); + generic_attribute_service_uuid->base.type = &bleio_uuid_type; + common_hal_bleio_uuid_construct(generic_attribute_service_uuid, 0x1801, NULL); + + bleio_uuid_obj_t *service_changed_characteristic_uuid = m_new_obj(bleio_uuid_obj_t); + service_changed_characteristic_uuid->base.type = &bleio_uuid_type; + common_hal_bleio_uuid_construct(service_changed_characteristic_uuid, 0x2A05, NULL); + + bleio_service_obj_t *generic_attribute_service = m_new_obj(bleio_service_obj_t); + generic_attribute_service->base.type = &bleio_service_type; + common_hal_bleio_service_construct(generic_attribute_service, generic_attribute_service_uuid, false); + + adapter->service_changed_characteristic = m_new_obj(bleio_characteristic_obj_t); + adapter->service_changed_characteristic->base.type = &bleio_characteristic_type; + + uint32_t zero_32 = 0; + mp_buffer_info_t zero_32_value = { + .buf = &zero_32, + .len = sizeof(zero_32), + }; + + common_hal_bleio_characteristic_construct( + adapter->service_changed_characteristic, + generic_attribute_service, + BLE_GATT_HANDLE_INVALID, + service_changed_characteristic_uuid, + CHAR_PROP_INDICATE, + SECURITY_MODE_OPEN, + SECURITY_MODE_NO_ACCESS, + 4, // max length, from Bluetooth spec + true, // fixed length + &zero_32_value + ); +} + + +STATIC void check_enabled(bleio_adapter_obj_t *adapter) { + if (!common_hal_bleio_adapter_get_enabled(adapter)) { + mp_raise_bleio_BluetoothError(translate("Adapter not enabled")); + } +} + +// STATIC bool adapter_on_ble_evt(ble_evt_t *ble_evt, void *self_in) { +// bleio_adapter_obj_t *self = (bleio_adapter_obj_t*)self_in; + +// // For debugging. +// // mp_printf(&mp_plat_print, "Adapter event: 0x%04x\n", ble_evt->header.evt_id); + +// switch (ble_evt->header.evt_id) { +// case BLE_GAP_EVT_CONNECTED: { +// // Find an empty connection. One must always be available because the SD has the same +// // total connection limit. +// bleio_connection_internal_t *connection; +// for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { +// connection = &bleio_connections[i]; +// if (connection->conn_handle == BLE_CONN_HANDLE_INVALID) { +// break; +// } +// } + +// // Central has connected. +// ble_gap_evt_connected_t* connected = &ble_evt->evt.gap_evt.params.connected; + +// connection->conn_handle = ble_evt->evt.gap_evt.conn_handle; +// connection->connection_obj = mp_const_none; +// connection->pair_status = PAIR_NOT_PAIRED; +// connection->mtu = 0; + +// ble_drv_add_event_handler_entry(&connection->handler_entry, connection_on_ble_evt, connection); +// self->connection_objs = NULL; + +// // Save the current connection parameters. +// memcpy(&connection->conn_params, &connected->conn_params, sizeof(ble_gap_conn_params_t)); + +// #if CIRCUITPY_VERBOSE_BLE +// ble_gap_conn_params_t *cp = &connected->conn_params; +// mp_printf(&mp_plat_print, "conn params: min_ci %d max_ci %d s_l %d sup_timeout %d\n", cp->min_conn_interval, cp->max_conn_interval, cp->slave_latency, cp->conn_sup_timeout); +// #endif + +// // See if connection interval set by Central is out of range. +// // If so, negotiate our preferred range. +// ble_gap_conn_params_t conn_params; +// sd_ble_gap_ppcp_get(&conn_params); +// if (conn_params.min_conn_interval < connected->conn_params.min_conn_interval || +// conn_params.min_conn_interval > connected->conn_params.max_conn_interval) { +// sd_ble_gap_conn_param_update(ble_evt->evt.gap_evt.conn_handle, &conn_params); +// } +// self->current_advertising_data = NULL; +// break; +// } +// case BLE_GAP_EVT_DISCONNECTED: { +// // Find the connection that was disconnected. +// bleio_connection_internal_t *connection; +// for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { +// connection = &bleio_connections[i]; +// if (connection->conn_handle == ble_evt->evt.gap_evt.conn_handle) { +// break; +// } +// } +// ble_drv_remove_event_handler(connection_on_ble_evt, connection); +// connection->conn_handle = BLE_CONN_HANDLE_INVALID; +// connection->pair_status = PAIR_NOT_PAIRED; +// if (connection->connection_obj != mp_const_none) { +// bleio_connection_obj_t* obj = connection->connection_obj; +// obj->connection = NULL; +// obj->disconnect_reason = ble_evt->evt.gap_evt.params.disconnected.reason; +// } +// self->connection_objs = NULL; + +// break; +// } + +// case BLE_GAP_EVT_ADV_SET_TERMINATED: +// self->current_advertising_data = NULL; +// break; + +// default: +// // For debugging. +// // mp_printf(&mp_plat_print, "Unhandled adapter event: 0x%04x\n", ble_evt->header.evt_id); +// return false; +// break; +// } +// return true; +// } + +char default_ble_name[] = { 'C', 'I', 'R', 'C', 'U', 'I', 'T', 'P', 'Y', 0, 0, 0, 0}; + +// Get various values and limits set by the adapter. +// Set event mask. +STATIC void bleio_adapter_hci_init(bleio_adapter_obj_t *self) { + + const size_t len = sizeof(default_ble_name); + + bt_addr_t addr; + hci_check_error(hci_read_bd_addr(&addr)); + + default_ble_name[len - 4] = nibble_to_hex_lower[addr.val[1] >> 4 & 0xf]; + default_ble_name[len - 3] = nibble_to_hex_lower[addr.val[1] & 0xf]; + default_ble_name[len - 2] = nibble_to_hex_lower[addr.val[0] >> 4 & 0xf]; + default_ble_name[len - 1] = nibble_to_hex_lower[addr.val[0] & 0xf]; + self->name = mp_obj_new_str(default_ble_name, len); + + // Get version information. + if (hci_read_local_version(&self->hci_version, &self->hci_revision, &self->lmp_version, + &self->manufacturer, &self->lmp_subversion) != HCI_OK) { + mp_raise_bleio_BluetoothError(translate("Could not read HCI version")); + } + // Get supported features. + if (hci_le_read_local_supported_features(self->features) != HCI_OK) { + mp_raise_bleio_BluetoothError(translate("Could not read BLE features")); + } + + // Enabled desired events. + // Most importantly, includes: + // BT_EVT_MASK_LE_META_EVENT BT_EVT_BIT(61) + if (hci_set_event_mask(0x3FFFFFFFFFFFFFFF) != HCI_OK) { + mp_raise_bleio_BluetoothError(translate("Could not set event mask")); + } + // The default events for LE are: + // BT_EVT_MASK_LE_CONN_COMPLETE, BT_EVT_MASK_LE_ADVERTISING_REPORT, + // BT_EVT_MASK_LE_CONN_UPDATE_COMPLETE, BT_EVT_MASK_LE_REMOTE_FEAT_COMPLETE + // BT_EVT_MASK_LE_LTK_REQUEST. + // That's all we need right now, so we don't bother to set the LE event mask. + + // Get ACL buffer info. + uint16_t le_max_len; + uint8_t le_max_num; + if (hci_le_read_buffer_size(&le_max_len, &le_max_num) == HCI_OK) { + self->max_acl_buffer_len = le_max_len; + self->max_acl_num_buffers = le_max_num; + } else { + // LE Read Buffer Size not available; use the general Read Buffer Size. + uint16_t acl_max_len; + uint8_t sco_max_len; + uint16_t acl_max_num; + uint16_t sco_max_num; + if (hci_read_buffer_size(&acl_max_len, &sco_max_len, &acl_max_num, &sco_max_num) != HCI_OK) { + mp_raise_bleio_BluetoothError(translate("Could not read BLE buffer info")); + } + self->max_acl_buffer_len = acl_max_len; + self->max_acl_num_buffers = acl_max_num; + } + + // Get max advertising length if extended advertising is supported. + if (BT_FEAT_LE_EXT_ADV(self->features)) { + uint16_t max_adv_data_len; + if (hci_le_read_maximum_advertising_data_length(&max_adv_data_len) != HCI_OK) { + mp_raise_bleio_BluetoothError(translate("Could not get max advertising length")); + } + self->max_adv_data_len = max_adv_data_len; + } else { + self->max_adv_data_len = MAX_ADVERTISEMENT_SIZE; + } +} + +void common_hal_bleio_adapter_construct_hci_uart(bleio_adapter_obj_t *self, busio_uart_obj_t *uart, digitalio_digitalinout_obj_t *rts, digitalio_digitalinout_obj_t *cts) { + self->allocated = true; + self->hci_uart = uart; + self->rts_digitalinout = rts; + self->cts_digitalinout = cts; + + // Advertising-related fields are initialized by common_hal_bleio_adapter_set_enabled(). + self->enabled = false; + + common_hal_bleio_adapter_set_enabled(self, true); + bleio_adapter_hci_init(self); + common_hal_bleio_adapter_set_name(self, default_ble_name); +} + +void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enabled) { + const bool is_enabled = common_hal_bleio_adapter_get_enabled(self); + + // Don't enable or disable twice + if (is_enabled == enabled) { + return; + } + + self->enabled = enabled; + + // We must poll for input from the HCI adapter. + // TODO Can we instead trigger an interrupt on UART input traffic? + if (enabled) { + supervisor_enable_tick(); + } else { + supervisor_disable_tick(); + } + + // Enabling or disabling: stop any current activity; reset to known state. + hci_reset(); + self->now_advertising = false; + self->extended_advertising = false; + self->circuitpython_advertising = false; + self->advertising_timeout_msecs = 0; + + if (enabled) { + // Reset list of known attributes. + // Indices into the list are handles. Handle 0x0000 designates an invalid handle, + // so store None there to skip it. + self->attributes = mp_obj_new_list(0, NULL); + bleio_adapter_add_attribute(self, mp_const_none); + add_generic_services(self); + } +} + +bool common_hal_bleio_adapter_get_enabled(bleio_adapter_obj_t *self) { + return self->enabled; +} + +bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_obj_t *self) { + check_enabled(self); + + bt_addr_t addr; + hci_check_error(hci_read_bd_addr(&addr)); + + bleio_address_obj_t *address = m_new_obj(bleio_address_obj_t); + address->base.type = &bleio_address_type; + + common_hal_bleio_address_construct(address, addr.val, BT_ADDR_LE_PUBLIC); + return address; +} + +bool common_hal_bleio_adapter_set_address(bleio_adapter_obj_t *self, bleio_address_obj_t *address) { + mp_buffer_info_t bufinfo; + if (!mp_get_buffer(address->bytes, &bufinfo, MP_BUFFER_READ)) { + return false; + } + return hci_le_set_random_address(bufinfo.buf) == HCI_OK; +} + +mp_obj_str_t* common_hal_bleio_adapter_get_name(bleio_adapter_obj_t *self) { + return self->name; +} + +void common_hal_bleio_adapter_set_name(bleio_adapter_obj_t *self, const char* name) { + self->name = mp_obj_new_str(name, strlen(name)); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(self->name, &bufinfo, MP_BUFFER_READ); + bleio_characteristic_set_local_value(self->device_name_characteristic, &bufinfo); +} + + +// STATIC bool scan_on_ble_evt(ble_evt_t *ble_evt, void *scan_results_in) { +// bleio_scanresults_obj_t *scan_results = (bleio_scanresults_obj_t*)scan_results_in; + +// if (ble_evt->header.evt_id == BLE_GAP_EVT_TIMEOUT && +// ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_SCAN) { +// shared_module_bleio_scanresults_set_done(scan_results, true); +// ble_drv_remove_event_handler(scan_on_ble_evt, scan_results); +// return true; +// } + +// if (ble_evt->header.evt_id != BLE_GAP_EVT_ADV_REPORT) { +// return false; +// } +// ble_gap_evt_adv_report_t *report = &ble_evt->evt.gap_evt.params.adv_report; + +// shared_module_bleio_scanresults_append(scan_results, +// supervisor_ticks_ms64(), +// report->type.connectable, +// report->type.scan_response, +// report->rssi, +// report->peer_addr.addr, +// report->peer_addr.addr_type, +// report->data.p_data, +// report->data.len); + +// const uint32_t err_code = sd_ble_gap_scan_start(NULL, scan_results->common_hal_data); +// if (err_code != NRF_SUCCESS) { +// // TODO: Pass the error into the scan results so it can throw an exception. +// scan_results->done = true; +// } +// return true; +// } + +mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t* prefixes, size_t prefix_length, bool extended, mp_int_t buffer_size, mp_float_t timeout, mp_float_t interval, mp_float_t window, mp_int_t minimum_rssi, bool active) { + // TODO + mp_raise_NotImplementedError(NULL); + check_enabled(self); + + if (self->scan_results != NULL) { + if (!shared_module_bleio_scanresults_get_done(self->scan_results)) { + mp_raise_bleio_BluetoothError(translate("Scan already in progess. Stop with stop_scan.")); + } + self->scan_results = NULL; + } + self->scan_results = shared_module_bleio_new_scanresults(buffer_size, prefixes, prefix_length, minimum_rssi); + + // size_t max_packet_size = extended ? BLE_GAP_SCAN_BUFFER_EXTENDED_MAX_SUPPORTED : BLE_GAP_SCAN_BUFFER_MAX; + // uint8_t *raw_data = m_malloc(sizeof(ble_data_t) + max_packet_size, false); + // ble_data_t * sd_data = (ble_data_t *) raw_data; + // self->scan_results->common_hal_data = sd_data; + // sd_data->len = max_packet_size; + // sd_data->p_data = raw_data + sizeof(ble_data_t); + + // ble_drv_add_event_handler(scan_on_ble_evt, self->scan_results); + + // uint32_t nrf_timeout = SEC_TO_UNITS(timeout, UNIT_10_MS); + // if (timeout <= 0.0001) { + // nrf_timeout = BLE_GAP_SCAN_TIMEOUT_UNLIMITED; + // } + + // ble_gap_scan_params_t scan_params = { + // .extended = extended, + // .interval = SEC_TO_UNITS(interval, UNIT_0_625_MS), + // .timeout = nrf_timeout, + // .window = SEC_TO_UNITS(window, UNIT_0_625_MS), + // .scan_phys = BLE_GAP_PHY_1MBPS, + // .active = active + // }; + // uint32_t err_code; + // vm_used_ble = true; + // err_code = sd_ble_gap_scan_start(&scan_params, sd_data); + + // if (err_code != NRF_SUCCESS) { + // self->scan_results = NULL; + // ble_drv_remove_event_handler(scan_on_ble_evt, self->scan_results); + // check_nrf_error(err_code); + // } + + return MP_OBJ_FROM_PTR(self->scan_results); +} + +void common_hal_bleio_adapter_stop_scan(bleio_adapter_obj_t *self) { + // TODO + mp_raise_NotImplementedError(NULL); + check_enabled(self); + + // If not already scanning, no problem. + if (hci_le_set_scan_enable(BT_HCI_LE_SCAN_DISABLE, BT_HCI_LE_SCAN_FILTER_DUP_DISABLE) == HCI_OK) { + shared_module_bleio_scanresults_set_done(self->scan_results, true); + self->scan_results = NULL; + } +} + +// typedef struct { +// uint16_t conn_handle; +// volatile bool done; +// } connect_info_t; + +// STATIC bool connect_on_ble_evt(ble_evt_t *ble_evt, void *info_in) { +// connect_info_t *info = (connect_info_t*)info_in; + +// switch (ble_evt->header.evt_id) { +// case BLE_GAP_EVT_CONNECTED: +// info->conn_handle = ble_evt->evt.gap_evt.conn_handle; +// info->done = true; + +// break; + +// case BLE_GAP_EVT_TIMEOUT: +// // Handle will be invalid. +// info->done = true; +// break; +// default: +// // For debugging. +// // mp_printf(&mp_plat_print, "Unhandled central event: 0x%04x\n", ble_evt->header.evt_id); +// return false; +// break; +// } +// return true; +// } + +mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout) { + // TODO + mp_raise_NotImplementedError(NULL); + + check_enabled(self); + + // ble_gap_addr_t addr; + + // addr.addr_type = address->type; + // mp_buffer_info_t address_buf_info; + // mp_get_buffer_raise(address->bytes, &address_buf_info, MP_BUFFER_READ); + // memcpy(addr.addr, (uint8_t *) address_buf_info.buf, NUM_BLEIO_ADDRESS_BYTES); + + // ble_gap_scan_params_t scan_params = { + // .interval = MSEC_TO_UNITS(100, UNIT_0_625_MS), + // .window = MSEC_TO_UNITS(100, UNIT_0_625_MS), + // .scan_phys = BLE_GAP_PHY_1MBPS, + // // timeout of 0 means no timeout + // .timeout = SEC_TO_UNITS(timeout, UNIT_10_MS), + // }; + + // ble_gap_conn_params_t conn_params = { + // .conn_sup_timeout = MSEC_TO_UNITS(4000, UNIT_10_MS), + // .min_conn_interval = MSEC_TO_UNITS(15, UNIT_1_25_MS), + // .max_conn_interval = MSEC_TO_UNITS(300, UNIT_1_25_MS), + // .slave_latency = 0, // number of conn events + // }; + + // connect_info_t event_info; + // ble_drv_add_event_handler(connect_on_ble_evt, &event_info); + // event_info.done = false; + + vm_used_ble = true; + // uint32_t err_code = sd_ble_gap_connect(&addr, &scan_params, &conn_params, BLE_CONN_CFG_TAG_CUSTOM); + + // if (err_code != NRF_SUCCESS) { + // ble_drv_remove_event_handler(connect_on_ble_evt, &event_info); + // check_nrf_error(err_code); + // } + + // while (!event_info.done) { + // RUN_BACKGROUND_TASKS; + // } + + // ble_drv_remove_event_handler(connect_on_ble_evt, &event_info); + + // uint16_t conn_handle = event_info.conn_handle; + // if (conn_handle == BLE_CONN_HANDLE_INVALID) { + // mp_raise_bleio_BluetoothError(translate("Failed to connect: timeout")); + // } + + // // Negotiate for better PHY, larger MTU and data lengths since we are the central. These are + // // nice-to-haves so ignore any errors. + // ble_gap_phys_t const phys = { + // .rx_phys = BLE_GAP_PHY_AUTO, + // .tx_phys = BLE_GAP_PHY_AUTO, + // }; + // sd_ble_gap_phy_update(conn_handle, &phys); + // sd_ble_gattc_exchange_mtu_request(conn_handle, BLE_GATTS_VAR_ATTR_LEN_MAX); + // sd_ble_gap_data_length_update(conn_handle, NULL, NULL); + + // Make the connection object and return it. + // for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + // bleio_connection_internal_t *connection = &bleio_connections[i]; + // if (connection->conn_handle == conn_handle) { + // return bleio_connection_new_from_internal(connection); + // } + // } + + mp_raise_bleio_BluetoothError(translate("Failed to connect: internal error")); + + return mp_const_none; +} + +STATIC void check_data_fit(size_t data_len, bool connectable) { + if (data_len > MAX_ADVERTISEMENT_SIZE) { + mp_raise_ValueError(translate("Data too large for advertisement packet")); + } +} + +// STATIC bool advertising_on_ble_evt(ble_evt_t *ble_evt, void *self_in) { +// bleio_adapter_obj_t *self = (bleio_adapter_obj_t*)self_in; + +// switch (ble_evt->header.evt_id) { +// case BLE_GAP_EVT_ADV_SET_TERMINATED: +// common_hal_bleio_adapter_stop_advertising(self); +// ble_drv_remove_event_handler(advertising_on_ble_evt, self_in); +// break; + +// default: +// // For debugging. +// // mp_printf(&mp_plat_print, "Unhandled advertising event: 0x%04x\n", ble_evt->header.evt_id); +// return false; +// break; +// } +// return true; +// } + +uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, bool anonymous, uint32_t timeout, float interval, uint8_t *advertising_data, uint16_t advertising_data_len, uint8_t *scan_response_data, uint16_t scan_response_data_len) { + check_enabled(self); + + if (self->now_advertising) { + if (self->circuitpython_advertising) { + common_hal_bleio_adapter_stop_advertising(self); + } else { + // User-requested advertising. + // TODO allow multiple advertisements. + // Already advertising. Can't advertise twice. + return 1; + } + } + + // Peer address, which we don't use (no directed advertising). + bt_addr_le_t empty_addr = { 0 }; + + bool extended = + advertising_data_len > self->max_adv_data_len || scan_response_data_len > self->max_adv_data_len; + + if (extended) { + if (!BT_FEAT_LE_EXT_ADV(self->features)) { + mp_raise_bleio_BluetoothError(translate("Data length needs extended advertising, but this adapter does not support it")); + } + + uint16_t props = 0; + if (connectable) { + props |= BT_HCI_LE_ADV_PROP_CONN; + } + if (scan_response_data_len > 0) { + props |= BT_HCI_LE_ADV_PROP_SCAN; + } + + // Advertising interval. + uint32_t interval_units = SEC_TO_UNITS(interval, UNIT_0_625_MS); + + hci_check_error( + hci_le_set_extended_advertising_parameters( + 0, // handle + props, // adv properties + interval_units, // min interval + interval_units, // max interval + 0b111, // channel map: channels 37, 38, 39 + anonymous ? BT_ADDR_LE_RANDOM : BT_ADDR_LE_PUBLIC, + &empty_addr, // peer_addr, + 0x00, // filter policy: no filter + DEFAULT_TX_POWER, + BT_HCI_LE_EXT_SCAN_PHY_1M, // Secondary PHY to use + 0x00, // AUX_ADV_IND shall be sent prior to next adv event + BT_HCI_LE_EXT_SCAN_PHY_1M, // Secondary PHY to use + 0x00, // Advertising SID + 0x00 // Scan req notify disable + )); + + // We can use the duration mechanism provided, instead of our own. + self->advertising_timeout_msecs = 0; + + uint8_t handle[1] = { 0 }; + uint16_t duration_10msec[1] = { timeout * 100 }; + uint8_t max_ext_adv_evts[1] = { 0 }; + hci_check_error( + hci_le_set_extended_advertising_enable( + BT_HCI_LE_ADV_ENABLE, + 1, // one advertising set. + handle, + duration_10msec, + max_ext_adv_evts + )); + + self->extended_advertising = true; + } else { + // Legacy advertising (not extended). + + uint8_t adv_type; + if (connectable) { + // Connectable, scannable, undirected. + adv_type = BT_HCI_ADV_IND; + } else if (scan_response_data_len > 0) { + // Unconnectable, scannable, undirected. + adv_type = BT_HCI_ADV_SCAN_IND; + } else { + // Unconnectable, unscannable, undirected. + adv_type = BT_HCI_ADV_NONCONN_IND; + } + + // Advertising interval. + uint16_t interval_units = SEC_TO_UNITS(interval, UNIT_0_625_MS); + + hci_check_error( + hci_le_set_advertising_parameters( + interval_units, // min interval + interval_units, // max interval + adv_type, + anonymous ? BT_ADDR_LE_RANDOM : BT_ADDR_LE_PUBLIC, + &empty_addr, + 0b111, // channel map: channels 37, 38, 39 + 0x00 // filter policy: no filter + )); + + // The HCI commands expect MAX_ADVERTISEMENT_SIZE (31)octets, + // even though the actual data length may be shorter. + uint8_t full_data[MAX_ADVERTISEMENT_SIZE] = { 0 }; + memcpy(full_data, advertising_data, MIN(sizeof(full_data), advertising_data_len)); + hci_check_error(hci_le_set_advertising_data(advertising_data_len, full_data)); + memset(full_data, 0, sizeof(full_data)); + if (scan_response_data_len > 0) { + memcpy(full_data, scan_response_data, MIN(sizeof(full_data), scan_response_data_len)); + hci_check_error(hci_le_set_scan_response_data(scan_response_data_len, full_data)); + } + + // No duration mechanism is provided for legacy advertising, so we need to do our own. + self->advertising_timeout_msecs = timeout * 1000; + self->advertising_start_ticks = supervisor_ticks_ms64(); + + // Start advertising. + hci_check_error(hci_le_set_advertising_enable(BT_HCI_LE_ADV_ENABLE)); + self->extended_advertising = false; + } // end legacy advertising setup + + vm_used_ble = true; + self->now_advertising = true; + return 0; +} + +void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable, bool anonymous, uint32_t timeout, mp_float_t interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo) { + check_enabled(self); + + // interval value has already been validated. + + check_data_fit(advertising_data_bufinfo->len, connectable); + check_data_fit(scan_response_data_bufinfo->len, connectable); + + if (advertising_data_bufinfo->len > MAX_ADVERTISEMENT_SIZE && scan_response_data_bufinfo->len > 0) { + mp_raise_bleio_BluetoothError(translate("Extended advertisements with scan response not supported.")); + } + + // Anonymous mode requires a timeout so that we don't continue to broadcast + // the same data while cycling the MAC address -- otherwise, what's the + // point of randomizing the MAC address? + if (timeout == 0 && anonymous) { + timeout = MAX_ANONYMOUS_ADV_TIMEOUT_SECS; + } else { + if (timeout > MAX_LIMITED_DISCOVERABLE_ADV_TIMEOUT_SECS) { + mp_raise_bleio_BluetoothError(translate("Timeout is too long: Maximum timeout length is %d seconds"), + MAX_LIMITED_DISCOVERABLE_ADV_TIMEOUT_SECS); + } + } + + const uint32_t result =_common_hal_bleio_adapter_start_advertising( + self, connectable, anonymous, timeout, interval, + advertising_data_bufinfo->buf, + advertising_data_bufinfo->len, + scan_response_data_bufinfo->buf, + scan_response_data_bufinfo->len); + + if (result) { + mp_raise_bleio_BluetoothError(translate("Already advertising")); + } + self->circuitpython_advertising = false; +} + +void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self) { + check_enabled(self); + + self->now_advertising = false; + self->extended_advertising = false; + self->circuitpython_advertising = false; + + int result = hci_le_set_advertising_enable(BT_HCI_LE_ADV_DISABLE); + // OK if we're already stopped. There seems to be an ESP32 HCI bug: + // If advertising is already off, then LE_SET_ADV_ENABLE does not return a response. + if (result != HCI_RESPONSE_TIMEOUT) { + hci_check_error(result); + } + + //TODO startup CircuitPython advertising again. +} + +// Note that something stopped advertising, such as a connection happening. +//Don't ask the adapter to stop. +void bleio_adapter_advertising_was_stopped(bleio_adapter_obj_t *self) { + self->now_advertising = false; + self->extended_advertising = false; + self->circuitpython_advertising = false; +} + +bool common_hal_bleio_adapter_get_advertising(bleio_adapter_obj_t *self) { + check_enabled(self); + + return self->now_advertising; +} + +bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self) { + check_enabled(self); + + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &bleio_connections[i]; + if (connection->conn_handle != BLE_CONN_HANDLE_INVALID) { + return true; + } + } + return false; +} + +mp_obj_t common_hal_bleio_adapter_get_connections(bleio_adapter_obj_t *self) { + check_enabled(self); + + if (self->connection_objs != NULL) { + return self->connection_objs; + } + size_t total_connected = 0; + mp_obj_t items[BLEIO_TOTAL_CONNECTION_COUNT]; + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &bleio_connections[i]; + if (connection->conn_handle != BLE_CONN_HANDLE_INVALID) { + if (connection->connection_obj == mp_const_none) { + connection->connection_obj = bleio_connection_new_from_internal(connection); + } + items[total_connected] = connection->connection_obj; + total_connected++; + } + } + self->connection_objs = mp_obj_new_tuple(total_connected, items); + return self->connection_objs; +} + +void common_hal_bleio_adapter_erase_bonding(bleio_adapter_obj_t *self) { + // TODO + mp_raise_NotImplementedError(NULL); + check_enabled(self); + + //FIX bonding_erase_storage(); +} + +uint16_t bleio_adapter_add_attribute(bleio_adapter_obj_t *adapter, mp_obj_t *attribute) { + check_enabled(adapter); + + // The handle is the index of this attribute in the attributes list. + uint16_t handle = (uint16_t) adapter->attributes->len; + mp_obj_list_append(adapter->attributes, attribute); + + if (MP_OBJ_IS_TYPE(attribute, &bleio_service_type)) { + adapter->last_added_service_handle = handle; + } + if (MP_OBJ_IS_TYPE(attribute, &bleio_characteristic_type)) { + adapter->last_added_characteristic_handle = handle; + } + + return handle; +} + +mp_obj_t* bleio_adapter_get_attribute(bleio_adapter_obj_t *adapter, uint16_t handle) { + check_enabled(adapter); + + if (handle == 0 || handle >= adapter->attributes->len) { + return mp_const_none; + } + return adapter->attributes->items[handle]; +} + +uint16_t bleio_adapter_max_attribute_handle(bleio_adapter_obj_t *adapter) { + check_enabled(adapter); + + return adapter->attributes->len - 1; +} + + +void bleio_adapter_gc_collect(bleio_adapter_obj_t* adapter) { + gc_collect_root((void**)adapter, sizeof(bleio_adapter_obj_t) / sizeof(size_t)); + gc_collect_root((void**)bleio_connections, sizeof(bleio_connections) / sizeof(size_t)); +} + +void bleio_adapter_reset(bleio_adapter_obj_t* adapter) { + + if (!common_hal_bleio_adapter_get_enabled(adapter)) { + return; + } + + // Adapter will be reset. + common_hal_bleio_adapter_set_enabled(adapter, false); + + adapter->connection_objs = NULL; + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &bleio_connections[i]; + // Disconnect all connections with Python state cleanly. Keep any supervisor-only connections. + if (connection->connection_obj != mp_const_none && + connection->conn_handle != BLE_CONN_HANDLE_INVALID) { + common_hal_bleio_connection_disconnect(connection); + } + connection->connection_obj = mp_const_none; + } + +} + +void bleio_adapter_background(bleio_adapter_obj_t* adapter) { + if (!common_hal_bleio_adapter_get_enabled(adapter)) { + return; + } + + if (adapter->advertising_timeout_msecs > 0 && + supervisor_ticks_ms64() - adapter->advertising_start_ticks > adapter->advertising_timeout_msecs) { + adapter->advertising_timeout_msecs = 0; + common_hal_bleio_adapter_stop_advertising(adapter); + } + + hci_result_t result = hci_poll_for_incoming_pkt(); + if (result != HCI_OK) { + mp_printf(&mp_plat_print, "bad hci_poll_for_incoming_pkt() result in background: %d\n", result); + } +} diff --git a/devices/ble_hci/common-hal/_bleio/Adapter.h b/devices/ble_hci/common-hal/_bleio/Adapter.h new file mode 100644 index 0000000000..bec1329f28 --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/Adapter.h @@ -0,0 +1,99 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * Copyright (c) 2016 Glenn Ruben Bakke + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_ADAPTER_H +#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_ADAPTER_H + +#include "py/obj.h" +#include "py/objtuple.h" + +#include "shared-bindings/_bleio/Characteristic.h" +#include "shared-bindings/_bleio/Connection.h" +#include "shared-bindings/_bleio/ScanResults.h" +#include "shared-bindings/busio/UART.h" +#include "shared-bindings/digitalio/DigitalInOut.h" + +#ifndef BLEIO_TOTAL_CONNECTION_COUNT +#define BLEIO_TOTAL_CONNECTION_COUNT 5 +#endif + +extern bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT]; + +typedef struct _bleio_adapter_obj_t { + mp_obj_base_t base; + bleio_scanresults_obj_t *scan_results; + mp_obj_t name; + mp_obj_tuple_t *connection_objs; + busio_uart_obj_t* hci_uart; + digitalio_digitalinout_obj_t *rts_digitalinout; + digitalio_digitalinout_obj_t *cts_digitalinout; + bool allocated; // True when in use. + bool now_advertising; + bool extended_advertising; + bool circuitpython_advertising; + bool enabled; + + // HCI adapter version info. + uint8_t hci_version; + uint8_t lmp_version; + uint16_t hci_revision; + uint16_t manufacturer; + uint16_t lmp_subversion; + + // Used to monitor advertising timeout for legacy avertising. + uint64_t advertising_start_ticks; + uint64_t advertising_timeout_msecs; // If zero, do not check. + + // Generic services characteristics. + bleio_characteristic_obj_t *device_name_characteristic; + bleio_characteristic_obj_t *appearance_characteristic; + bleio_characteristic_obj_t * service_changed_characteristic; + + uint16_t max_acl_buffer_len; + uint16_t max_acl_num_buffers; + uint16_t max_adv_data_len; + uint8_t features[8]; // Supported BLE features. + + // All the local attributes for this device. The index into the list + // corresponds to the handle. + mp_obj_list_t *attributes; + // Handle for last added service. Characteristics can only be added immediately after + // the service they belong to. This vets that. + uint16_t last_added_service_handle; + uint16_t last_added_characteristic_handle; +} bleio_adapter_obj_t; + +uint16_t bleio_adapter_add_attribute(bleio_adapter_obj_t *adapter, mp_obj_t *attribute); +void bleio_adapter_advertising_was_stopped(bleio_adapter_obj_t *self); +mp_obj_t* bleio_adapter_get_attribute(bleio_adapter_obj_t *adapter, uint16_t handle); +uint16_t bleio_adapter_max_attribute_handle(bleio_adapter_obj_t *adapter); +void bleio_adapter_background(bleio_adapter_obj_t* adapter); +void bleio_adapter_gc_collect(bleio_adapter_obj_t* adapter); +void bleio_adapter_reset(bleio_adapter_obj_t* adapter); + +#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_ADAPTER_H diff --git a/devices/ble_hci/common-hal/_bleio/Attribute.c b/devices/ble_hci/common-hal/_bleio/Attribute.c new file mode 100644 index 0000000000..26fabed098 --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/Attribute.c @@ -0,0 +1,49 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" + +#include "shared-bindings/_bleio/Attribute.h" +#include "shared-bindings/_bleio/Characteristic.h" +#include "shared-bindings/_bleio/Descriptor.h" +#include "shared-bindings/_bleio/Service.h" + + +bleio_uuid_obj_t *bleio_attribute_get_uuid(mp_obj_t *attribute) { + if (MP_OBJ_IS_TYPE(attribute, &bleio_characteristic_type)) { + bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(attribute); + return characteristic->uuid; + } + if (MP_OBJ_IS_TYPE(attribute, &bleio_descriptor_type)) { + bleio_descriptor_obj_t *descriptor = MP_OBJ_TO_PTR(attribute); + return descriptor->uuid; + } + if (MP_OBJ_IS_TYPE(attribute, &bleio_service_type)) { + bleio_service_obj_t *service = MP_OBJ_TO_PTR(attribute); + return service->uuid; + } + mp_raise_RuntimeError(translate("Invalid BLE attribute")); +} diff --git a/devices/ble_hci/common-hal/_bleio/Attribute.h b/devices/ble_hci/common-hal/_bleio/Attribute.h new file mode 100644 index 0000000000..b8702cae45 --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/Attribute.h @@ -0,0 +1,35 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Dan Halbert for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_ATTRIBUTE_H +#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_ATTRIBUTE_H + +#include "shared-module/_bleio/Attribute.h" +#include "shared-bindings/_bleio/UUID.h" + +bleio_uuid_obj_t *bleio_attribute_get_uuid(mp_obj_t *attribute); + +#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_ATTRIBUTE_H diff --git a/devices/ble_hci/common-hal/_bleio/Characteristic.c b/devices/ble_hci/common-hal/_bleio/Characteristic.c new file mode 100644 index 0000000000..393b80459a --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/Characteristic.c @@ -0,0 +1,228 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" + +#include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Characteristic.h" +#include "shared-bindings/_bleio/CharacteristicBuffer.h" +#include "shared-bindings/_bleio/Descriptor.h" +#include "shared-bindings/_bleio/PacketBuffer.h" +#include "shared-bindings/_bleio/Service.h" + +#include "common-hal/_bleio/Adapter.h" +#include "common-hal/_bleio/att.h" + +#define CCCD_NOTIFY 0x1 +#define CCCD_INDICATE 0x2 + + +void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) { + self->service = service; + self->uuid = uuid; + self->decl_handle = BLE_GATT_HANDLE_INVALID; + self->handle = BLE_GATT_HANDLE_INVALID; + self->props = props; + self->read_perm = read_perm; + self->write_perm = write_perm; + self->descriptor_list = mp_obj_new_list(0, NULL); + self->observer = mp_const_none; + self->user_desc = NULL; + self->cccd = NULL; + self->sccd = NULL; + self->value = mp_obj_new_bytes(initial_value_bufinfo->buf, initial_value_bufinfo->len); + + const mp_int_t max_length_max = 512; + if (max_length < 0 || max_length > max_length_max) { + mp_raise_ValueError(translate("max_length must be <= 512")); + } + self->max_length = max_length; + self->fixed_length = fixed_length; + + if (service->is_remote) { + self->handle = handle; + } else { + common_hal_bleio_service_add_characteristic(self->service, self, initial_value_bufinfo); + } +} + +mp_obj_tuple_t *common_hal_bleio_characteristic_get_descriptors(bleio_characteristic_obj_t *self) { + return mp_obj_new_tuple(self->descriptor_list->len, self->descriptor_list->items); +} + +bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_characteristic_obj_t *self) { + return self->service; +} + +size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self, uint8_t* buf, size_t len) { + // Do GATT operations only if this characteristic has been added to a registered service. + if (self->handle != BLE_GATT_HANDLE_INVALID) { + //FIX uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); + if (common_hal_bleio_service_get_is_remote(self->service)) { + //FIX read remote chars + //uint8_t rsp[MAX(len, 512)]; + //FIX improve att_read_req to write into our requested buffer. + // return att_read_req(conn_handle, self->handle, rsp); + return 0; //FIX + } else { + mp_buffer_info_t bufinfo; + if (!mp_get_buffer(self->value, &bufinfo, MP_BUFFER_READ)) { + return 0; + } + const size_t actual_length = MIN(len, bufinfo.len); + memcpy(buf, bufinfo.buf, actual_length); + return actual_length; + } + } + + return 0; +} + +void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) { + if (self->fixed_length && bufinfo->len != self->max_length) { + mp_raise_ValueError(translate("Value length != required fixed length")); + } + if (bufinfo->len > self->max_length) { + mp_raise_ValueError(translate("Value length > max_length")); + } + + // Do GATT operations only if this characteristic has been added to a registered service. + if (self->handle != BLE_GATT_HANDLE_INVALID) { + if (common_hal_bleio_service_get_is_remote(self->service)) { + //FIX uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); + if (self->props & CHAR_PROP_WRITE) { + //FIX writing remote chars + //uint8_t rsp[sizeof(bt_att_error_rsp)]; + //att_write_req(conn_handle, self->handle, bufinfo->buf, bufinfo->len, rsp); + } else if (self->props & CHAR_PROP_WRITE_NO_RESPONSE) { + //att_write_cmd(conn_handle, self->handle, bufinfo->buff, bufinfo->len); + } else { + mp_raise_bleio_BluetoothError(translate("Characteristic not writable")); + } + } else { + // Always write the value locally even if no connections are active. + bleio_characteristic_set_local_value(self, bufinfo); + // Notify or indicate all active connections. + + uint16_t cccd_value = 0; + mp_buffer_info_t cccd_bufinfo = { + .buf = &cccd_value, + .len = sizeof(cccd_value), + }; + + const bool notify = self->props & CHAR_PROP_NOTIFY; + const bool indicate = self->props & CHAR_PROP_INDICATE; + // Read the CCCD value, if there is one. + if ((notify | indicate) && self->cccd != NULL) { + common_hal_bleio_descriptor_get_value(self->cccd, cccd_bufinfo.buf, cccd_bufinfo.len); + } + + // It's possible that both notify and indicate are set. + if (notify && (cccd_value & CCCD_NOTIFY)) { + att_notify(self->handle, bufinfo->buf, MIN(bufinfo->len, self->max_length)); + } + if (indicate && (cccd_value & CCCD_INDICATE)) { + att_indicate(self->handle, bufinfo->buf, MIN(bufinfo->len, self->max_length)); + + } + } + } +} + +bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characteristic_obj_t *self) { + return self->uuid; +} + +bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties(bleio_characteristic_obj_t *self) { + return self->props; +} + +void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *self, bleio_descriptor_obj_t *descriptor) { + if (self->handle != common_hal_bleio_adapter_obj.last_added_characteristic_handle) { + mp_raise_bleio_BluetoothError( + translate("Descriptor can only be added to most recently added characteristic")); + } + + descriptor->handle = bleio_adapter_add_attribute(&common_hal_bleio_adapter_obj, MP_OBJ_TO_PTR(descriptor)); + // Include this descriptor in the service handle's range. + self->service->end_handle = descriptor->handle; + + mp_obj_list_append(MP_OBJ_FROM_PTR(self->descriptor_list), + MP_OBJ_FROM_PTR(descriptor)); +} + +void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate) { + if (self->cccd == NULL) { + mp_raise_bleio_BluetoothError(translate("No CCCD for this Characteristic")); + } + + if (!common_hal_bleio_service_get_is_remote(self->service)) { + mp_raise_bleio_RoleError(translate("Can't set CCCD on local Characteristic")); + } + + const uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); + common_hal_bleio_check_connected(conn_handle); + + uint16_t cccd_value = + (notify ? CCCD_NOTIFY : 0) | + (indicate ? CCCD_INDICATE : 0); + + //FIX do remote + (void) cccd_value; + // uint8_t rsp[sizeof(bt_att_error_rsp)]; + // if (att_write_req(conn_handle, self->cccd->handle, &cccd_value, sizeof(cccd_value)) == 0) { + // mp_raise_bleio_BluetoothError(translate("Could not write CCCD")); + // } +} + +bool bleio_characteristic_set_local_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) { + if (self->fixed_length && bufinfo->len != self->max_length) { + return false; + } + if (bufinfo->len > self->max_length) { + return false; + } + + self->value = mp_obj_new_bytes(bufinfo->buf, bufinfo->len); + + if (MP_OBJ_IS_TYPE(self->observer, &bleio_characteristic_buffer_type)) { + bleio_characteristic_buffer_update(MP_OBJ_FROM_PTR(self->observer), bufinfo); + } else if (MP_OBJ_IS_TYPE(self->observer, &bleio_packet_buffer_type)) { + bleio_packet_buffer_update(MP_OBJ_FROM_PTR(self->observer), bufinfo); + } else { + return false; + } + return true; +} + +void bleio_characteristic_set_observer(bleio_characteristic_obj_t *self, mp_obj_t observer) { + self->observer = observer; +} + +void bleio_characteristic_clear_observer(bleio_characteristic_obj_t *self) { + self->observer = mp_const_none; +} diff --git a/devices/ble_hci/common-hal/_bleio/Characteristic.h b/devices/ble_hci/common-hal/_bleio/Characteristic.h new file mode 100644 index 0000000000..6d5a12509c --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/Characteristic.h @@ -0,0 +1,63 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CHARACTERISTIC_H +#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CHARACTERISTIC_H + +#include "shared-bindings/_bleio/Attribute.h" +#include "common-hal/_bleio/Descriptor.h" +#include "shared-module/_bleio/Characteristic.h" +#include "common-hal/_bleio/Service.h" +#include "common-hal/_bleio/UUID.h" + +typedef struct _bleio_characteristic_obj { + mp_obj_base_t base; + // Will be MP_OBJ_NULL before being assigned to a Service. + bleio_service_obj_t *service; + bleio_uuid_obj_t *uuid; + mp_obj_t value; + mp_obj_t observer; + mp_obj_list_t *descriptor_list; + uint16_t max_length; + bool fixed_length; + uint16_t decl_handle; + uint16_t handle; // Should be decl_handle+1. + bleio_characteristic_properties_t props; + bleio_attribute_security_mode_t read_perm; + bleio_attribute_security_mode_t write_perm; + bleio_descriptor_obj_t *descriptor_linked_list; + bleio_descriptor_obj_t *user_desc; + bleio_descriptor_obj_t *cccd; + bleio_descriptor_obj_t *sccd; +} bleio_characteristic_obj_t; + +bool bleio_characteristic_set_local_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo); + +void bleio_characteristic_set_observer(bleio_characteristic_obj_t *self, mp_obj_t observer); +void bleio_characteristic_clear_observer(bleio_characteristic_obj_t *self); + +#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CHARACTERISTIC_H diff --git a/devices/ble_hci/common-hal/_bleio/CharacteristicBuffer.c b/devices/ble_hci/common-hal/_bleio/CharacteristicBuffer.c new file mode 100644 index 0000000000..e8cd518808 --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/CharacteristicBuffer.c @@ -0,0 +1,104 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "lib/utils/interrupt_char.h" +#include "py/runtime.h" +#include "py/stream.h" + +#include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Connection.h" +#include "supervisor/shared/tick.h" +#include "common-hal/_bleio/CharacteristicBuffer.h" + +// Push all the data onto the ring buffer. When the buffer is full, new bytes will be dropped. +STATIC void write_to_ringbuf(bleio_characteristic_buffer_obj_t *self, uint8_t *data, uint16_t len) { + ringbuf_put_n(&self->ringbuf, data, len); +} + +void bleio_characteristic_buffer_update(bleio_characteristic_buffer_obj_t *self, mp_buffer_info_t *bufinfo) { + write_to_ringbuf(self, bufinfo->buf, bufinfo->len); +} + +// Assumes that timeout and buffer_size have been validated before call. +void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffer_obj_t *self, + bleio_characteristic_obj_t *characteristic, + mp_float_t timeout, + size_t buffer_size) { + + self->characteristic = characteristic; + self->timeout_ms = timeout * 1000; + // This is a macro. + // true means long-lived, so it won't be moved. + ringbuf_alloc(&self->ringbuf, buffer_size, true); + + bleio_characteristic_set_observer(characteristic, self); +} + +uint32_t common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_t *self, uint8_t *data, size_t len, int *errcode) { + uint64_t start_ticks = supervisor_ticks_ms64(); + + // Wait for all bytes received or timeout + while ( (ringbuf_num_filled(&self->ringbuf) < len) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) { + RUN_BACKGROUND_TASKS; + // Allow user to break out of a timeout with a KeyboardInterrupt. + if ( mp_hal_is_interrupted() ) { + return 0; + } + } + + uint32_t num_bytes_read = ringbuf_get_n(&self->ringbuf, data, len); + return num_bytes_read; +} + +uint32_t common_hal_bleio_characteristic_buffer_rx_characters_available(bleio_characteristic_buffer_obj_t *self) { + uint16_t count = ringbuf_num_filled(&self->ringbuf); + return count; +} + +void common_hal_bleio_characteristic_buffer_clear_rx_buffer(bleio_characteristic_buffer_obj_t *self) { + ringbuf_clear(&self->ringbuf); +} + +bool common_hal_bleio_characteristic_buffer_deinited(bleio_characteristic_buffer_obj_t *self) { + return self->characteristic == NULL; +} + +void common_hal_bleio_characteristic_buffer_deinit(bleio_characteristic_buffer_obj_t *self) { + if (!common_hal_bleio_characteristic_buffer_deinited(self)) { + bleio_characteristic_clear_observer(self->characteristic); + } +} + +bool common_hal_bleio_characteristic_buffer_connected(bleio_characteristic_buffer_obj_t *self) { + return self->characteristic != NULL && + self->characteristic->service != NULL && + (!self->characteristic->service->is_remote || + (self->characteristic->service->connection != MP_OBJ_NULL && + common_hal_bleio_connection_get_connected(self->characteristic->service->connection))); +} diff --git a/devices/ble_hci/common-hal/_bleio/CharacteristicBuffer.h b/devices/ble_hci/common-hal/_bleio/CharacteristicBuffer.h new file mode 100644 index 0000000000..107e5801f8 --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/CharacteristicBuffer.h @@ -0,0 +1,43 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CHARACTERISTICBUFFER_H +#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CHARACTERISTICBUFFER_H + +#include "py/ringbuf.h" +#include "shared-bindings/_bleio/Characteristic.h" + +typedef struct { + mp_obj_base_t base; + bleio_characteristic_obj_t *characteristic; + uint32_t timeout_ms; + // Ring buffer storing consecutive incoming values. + ringbuf_t ringbuf; +} bleio_characteristic_buffer_obj_t; + +void bleio_characteristic_buffer_update(bleio_characteristic_buffer_obj_t *self, mp_buffer_info_t *bufinfo); + +#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CHARACTERISTICBUFFER_H diff --git a/devices/ble_hci/common-hal/_bleio/Connection.c b/devices/ble_hci/common-hal/_bleio/Connection.c new file mode 100644 index 0000000000..ba4eb477d9 --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/Connection.c @@ -0,0 +1,772 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shared-bindings/_bleio/Connection.h" + +#include "att.h" + +#include +#include + +#include "lib/utils/interrupt_char.h" +#include "py/gc.h" +#include "py/objlist.h" +#include "py/objstr.h" +#include "py/qstr.h" +#include "py/runtime.h" +#include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Adapter.h" +#include "shared-bindings/_bleio/Attribute.h" +#include "shared-bindings/_bleio/Characteristic.h" +#include "shared-bindings/_bleio/Service.h" +#include "shared-bindings/_bleio/UUID.h" +#include "supervisor/shared/tick.h" + +#define BLE_ADV_LENGTH_FIELD_SIZE 1 +#define BLE_ADV_AD_TYPE_FIELD_SIZE 1 +#define BLE_AD_TYPE_FLAGS_DATA_SIZE 1 + +// static const ble_gap_sec_params_t pairing_sec_params = { +// .bond = 1, +// .mitm = 0, +// .lesc = 0, +// .keypress = 0, +// .oob = 0, +// .io_caps = BLE_GAP_IO_CAPS_NONE, +// .min_key_size = 7, +// .max_key_size = 16, +// .kdist_own = { .enc = 1, .id = 1}, +// .kdist_peer = { .enc = 1, .id = 1}, +// }; + +#define CONNECTION_DEBUG (1) +#if CONNECTION_DEBUG + #define CONNECTION_DEBUG_PRINTF(...) printf(__VA_ARGS__) +#else + #define CONNECTION_DEBUG_PRINTF(...) +#endif + +static volatile bool m_discovery_in_process; +static volatile bool m_discovery_successful; + +//FIX static bleio_service_obj_t *m_char_discovery_service; +//FIX static bleio_characteristic_obj_t *m_desc_discovery_characteristic; + +// bool connection_on_ble_evt(ble_evt_t *ble_evt, void *self_in) { +// bleio_connection_internal_t *self = (bleio_connection_internal_t*)self_in; + +// if (BLE_GAP_EVT_BASE <= ble_evt->header.evt_id && ble_evt->header.evt_id <= BLE_GAP_EVT_LAST && +// ble_evt->evt.gap_evt.conn_handle != self->conn_handle) { +// return false; +// } +// if (BLE_GATTS_EVT_BASE <= ble_evt->header.evt_id && ble_evt->header.evt_id <= BLE_GATTS_EVT_LAST && +// ble_evt->evt.gatts_evt.conn_handle != self->conn_handle) { +// return false; +// } + +// switch (ble_evt->header.evt_id) { +// case BLE_GAP_EVT_DISCONNECTED: +// // Adapter.c does the work for this event. +// break; + +// case BLE_GAP_EVT_PHY_UPDATE_REQUEST: { +// ble_gap_phys_t const phys = { +// .rx_phys = BLE_GAP_PHY_AUTO, +// .tx_phys = BLE_GAP_PHY_AUTO, +// }; +// sd_ble_gap_phy_update(ble_evt->evt.gap_evt.conn_handle, &phys); +// break; +// } + +// case BLE_GAP_EVT_PHY_UPDATE: { // 0x22 +// break; +// } + +// case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST: +// // SoftDevice will respond to a length update request. +// sd_ble_gap_data_length_update(self->conn_handle, NULL, NULL); +// break; + +// case BLE_GAP_EVT_DATA_LENGTH_UPDATE: { // 0x24 +// break; +// } + +// case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: { +// ble_gatts_evt_exchange_mtu_request_t *request = +// &ble_evt->evt.gatts_evt.params.exchange_mtu_request; + +// uint16_t new_mtu = BLE_GATTS_VAR_ATTR_LEN_MAX; +// if (request->client_rx_mtu < new_mtu) { +// new_mtu = request->client_rx_mtu; +// } +// if (new_mtu < BLE_GATT_ATT_MTU_DEFAULT) { +// new_mtu = BLE_GATT_ATT_MTU_DEFAULT; +// } +// if (self->mtu > 0) { +// new_mtu = self->mtu; +// } + +// self->mtu = new_mtu; +// sd_ble_gatts_exchange_mtu_reply(self->conn_handle, new_mtu); +// break; +// } + + +// case BLE_GATTC_EVT_EXCHANGE_MTU_RSP: { +// ble_gattc_evt_exchange_mtu_rsp_t *response = +// &ble_evt->evt.gattc_evt.params.exchange_mtu_rsp; + +// self->mtu = response->server_rx_mtu; +// break; +// } + +// case BLE_GATTS_EVT_WRITE: +// // A client wrote a value. +// // If we are bonded and it's a CCCD (UUID 0x2902), store the CCCD value. +// if (self->conn_handle != BLE_CONN_HANDLE_INVALID && +// self->pair_status == PAIR_PAIRED && +// ble_evt->evt.gatts_evt.params.write.uuid.type == BLE_UUID_TYPE_BLE && +// ble_evt->evt.gatts_evt.params.write.uuid.uuid == 0x2902) { +// // +// // Save sys_attr data (CCCD state) in bonding area at +// // next opportunity, but also remember time of this +// // request, so we can consolidate closely-spaced requests. +// self->do_bond_cccds = true; +// self->do_bond_cccds_request_time = supervisor_ticks_ms64(); +// } +// // Return false so other handlers get this event as well. +// return false; + +// case BLE_GATTS_EVT_SYS_ATTR_MISSING: +// sd_ble_gatts_sys_attr_set(self->conn_handle, NULL, 0, 0); +// break; + +// #if CIRCUITPY_VERBOSE_BLE +// // Use read authorization to snoop on all reads when doing verbose debugging. +// case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: { + +// ble_gatts_evt_rw_authorize_request_t *request = +// &ble_evt->evt.gatts_evt.params.authorize_request; + +// mp_printf(&mp_plat_print, "Read %x offset %d ", request->request.read.handle, request->request.read.offset); +// uint8_t value_bytes[22]; +// ble_gatts_value_t value; +// value.offset = request->request.read.offset; +// value.len = 22; +// value.p_value = value_bytes; + +// sd_ble_gatts_value_get(self->conn_handle, request->request.read.handle, &value); +// size_t len = value.len; +// if (len > 22) { +// len = 22; +// } +// for (uint8_t i = 0; i < len; i++) { +// mp_printf(&mp_plat_print, " %02x", value_bytes[i]); +// } +// mp_printf(&mp_plat_print, "\n"); +// ble_gatts_rw_authorize_reply_params_t reply; +// reply.type = request->type; +// reply.params.read.gatt_status = BLE_GATT_STATUS_SUCCESS; +// reply.params.read.update = false; +// reply.params.read.offset = request->request.read.offset; +// sd_ble_gatts_rw_authorize_reply(self->conn_handle, &reply); +// break; +// } +// #endif + +// case BLE_GATTS_EVT_HVN_TX_COMPLETE: // Capture this for now. 0x55 +// break; +// case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: { +// self->conn_params_updating = true; +// ble_gap_evt_conn_param_update_request_t *request = +// &ble_evt->evt.gap_evt.params.conn_param_update_request; +// sd_ble_gap_conn_param_update(self->conn_handle, &request->conn_params); +// break; +// } +// case BLE_GAP_EVT_CONN_PARAM_UPDATE: { // 0x12 +// ble_gap_evt_conn_param_update_t *result = +// &ble_evt->evt.gap_evt.params.conn_param_update; + +// #if CIRCUITPY_VERBOSE_BLE +// ble_gap_conn_params_t *cp = &ble_evt->evt.gap_evt.params.conn_param_update.conn_params; +// mp_printf(&mp_plat_print, "conn params updated: min_ci %d max_ci %d s_l %d sup_timeout %d\n", cp->min_conn_interval, cp->max_conn_interval, cp->slave_latency, cp->conn_sup_timeout); +// #endif + +// memcpy(&self->conn_params, &result->conn_params, sizeof(ble_gap_conn_params_t)); +// self->conn_params_updating = false; +// break; +// } +// case BLE_GAP_EVT_SEC_PARAMS_REQUEST: { +// // First time pairing. +// // 1. Either we or peer initiate the process +// // 2. Peer asks for security parameters using BLE_GAP_EVT_SEC_PARAMS_REQUEST. +// // 3. Pair Key exchange ("just works" implemented now; TODO: out-of-band key pairing) +// // 4. Connection is secured: BLE_GAP_EVT_CONN_SEC_UPDATE +// // 5. Long-term Keys exchanged: BLE_GAP_EVT_AUTH_STATUS + +// bonding_clear_keys(&self->bonding_keys); +// self->ediv = EDIV_INVALID; +// ble_gap_sec_keyset_t keyset = { +// .keys_own = { +// .p_enc_key = &self->bonding_keys.own_enc, +// .p_id_key = NULL, +// .p_sign_key = NULL, +// .p_pk = NULL +// }, + +// .keys_peer = { +// .p_enc_key = &self->bonding_keys.peer_enc, +// .p_id_key = &self->bonding_keys.peer_id, +// .p_sign_key = NULL, +// .p_pk = NULL +// } +// }; + +// sd_ble_gap_sec_params_reply(self->conn_handle, BLE_GAP_SEC_STATUS_SUCCESS, +// self->is_central ? NULL : &pairing_sec_params, +// &keyset); +// break; +// } + +// case BLE_GAP_EVT_LESC_DHKEY_REQUEST: +// // TODO for LESC pairing: +// // sd_ble_gap_lesc_dhkey_reply(...); +// break; + +// case BLE_GAP_EVT_AUTH_STATUS: { // 0x19 +// // Key exchange completed. +// ble_gap_evt_auth_status_t* status = &ble_evt->evt.gap_evt.params.auth_status; +// self->sec_status = status->auth_status; +// if (status->auth_status == BLE_GAP_SEC_STATUS_SUCCESS) { +// self->ediv = self->bonding_keys.own_enc.master_id.ediv; +// self->pair_status = PAIR_PAIRED; +// // Save keys in bonding area at next opportunity. +// self->do_bond_keys = true; +// } else { +// // Inform busy-waiter pairing has failed. +// self->pair_status = PAIR_NOT_PAIRED; +// } +// break; +// } + +// case BLE_GAP_EVT_SEC_INFO_REQUEST: { // 0x14 +// // Peer asks for the stored keys. +// // - load key and return if bonded previously. +// // - Else return NULL --> Initiate key exchange +// ble_gap_evt_sec_info_request_t* sec_info_request = &ble_evt->evt.gap_evt.params.sec_info_request; +// (void) sec_info_request; +// if ( bonding_load_keys(self->is_central, sec_info_request->master_id.ediv, &self->bonding_keys) ) { +// sd_ble_gap_sec_info_reply( +// self->conn_handle, +// &self->bonding_keys.own_enc.enc_info, +// &self->bonding_keys.peer_id.id_info, +// NULL); +// self->ediv = self->bonding_keys.own_enc.master_id.ediv; +// } else { +// // We don't have stored keys. Ask for keys. +// sd_ble_gap_sec_info_reply(self->conn_handle, NULL, NULL, NULL); +// } +// break; +// } + +// case BLE_GAP_EVT_CONN_SEC_UPDATE: { // 0x1a +// // We get this both on first-time pairing and on subsequent pairings using stored keys. +// ble_gap_conn_sec_t* conn_sec = &ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec; +// if (conn_sec->sec_mode.sm <= 1 && conn_sec->sec_mode.lv <= 1) { +// // Security setup did not succeed: +// // mode 0, level 0 means no access +// // mode 1, level 1 means open link +// // mode >=1 and/or level >=1 means encryption is set up +// self->pair_status = PAIR_NOT_PAIRED; +// } else { +// if (bonding_load_cccd_info(self->is_central, self->conn_handle, self->ediv)) { +// // Did an sd_ble_gatts_sys_attr_set() with the stored sys_attr values. +// } else { +// // No matching bonding found, so use fresh system attributes. +// sd_ble_gatts_sys_attr_set(self->conn_handle, NULL, 0, 0); +// } +// self->pair_status = PAIR_PAIRED; +// } +// break; +// } + +// default: +// return false; +// } +// return true; +// } + +void bleio_connection_clear(bleio_connection_internal_t *self) { + mp_obj_list_clear(MP_OBJ_FROM_PTR(self->remote_service_list)); + + self->conn_handle = BLE_CONN_HANDLE_INVALID; + self->pair_status = PAIR_NOT_PAIRED; + self->is_central = false; + //FIX bonding_clear_keys(&self->bonding_keys); +} + +bool common_hal_bleio_connection_get_paired(bleio_connection_obj_t *self) { + if (self->connection == NULL) { + return false; + } + return self->connection->pair_status == PAIR_PAIRED; +} + +bool common_hal_bleio_connection_get_connected(bleio_connection_obj_t *self) { + if (self->connection == NULL) { + return false; + } + return self->connection->conn_handle != BLE_CONN_HANDLE_INVALID; +} + +void common_hal_bleio_connection_disconnect(bleio_connection_internal_t *self) { + hci_disconnect(self->conn_handle); +} + +void common_hal_bleio_connection_pair(bleio_connection_internal_t *self, bool bond) { + self->pair_status = PAIR_WAITING; + + //FIX check_nrf_error(sd_ble_gap_authenticate(self->conn_handle, &pairing_sec_params)); + + while (self->pair_status == PAIR_WAITING && !mp_hal_is_interrupted()) { + RUN_BACKGROUND_TASKS; + } + if (mp_hal_is_interrupted()) { + return; + } + //FIX check_sec_status(self->sec_status); +} + +mp_float_t common_hal_bleio_connection_get_connection_interval(bleio_connection_internal_t *self) { + while (self->conn_params_updating && !mp_hal_is_interrupted()) { + RUN_BACKGROUND_TASKS; + } + //FIX return 1.25f * self->conn_params.min_conn_interval; + return 0.0f; +} + +// Return the current negotiated MTU length, minus overhead. +mp_int_t common_hal_bleio_connection_get_max_packet_length(bleio_connection_internal_t *self) { + return (self->mtu == 0 ? BT_ATT_DEFAULT_LE_MTU : self->mtu) - 3; +} + +void common_hal_bleio_connection_set_connection_interval(bleio_connection_internal_t *self, mp_float_t new_interval) { + // self->conn_params_updating = true; + // uint16_t interval = new_interval / 1.25f; + // self->conn_params.min_conn_interval = interval; + // self->conn_params.max_conn_interval = interval; + // uint32_t status = NRF_ERROR_BUSY; + // while (status == NRF_ERROR_BUSY) { + // status = sd_ble_gap_conn_param_update(self->conn_handle, &self->conn_params); + // RUN_BACKGROUND_TASKS; + // } + // check_nrf_error(status); +} + +// service_uuid may be NULL, to discover all services. +// STATIC bool discover_next_services(bleio_connection_internal_t* connection, uint16_t start_handle, ble_uuid_t *service_uuid) { +// m_discovery_successful = false; +// m_discovery_in_process = true; + +// uint32_t nrf_err = NRF_ERROR_BUSY; +// while (nrf_err == NRF_ERROR_BUSY) { +// nrf_err = sd_ble_gattc_primary_services_discover(connection->conn_handle, start_handle, service_uuid); +// } +// check_nrf_error(nrf_err); + +// // Wait for a discovery event. +// while (m_discovery_in_process) { +// MICROPY_VM_HOOK_LOOP; +// } +// return m_discovery_successful; +// } + +// STATIC bool discover_next_characteristics(bleio_connection_internal_t* connection, bleio_service_obj_t *service, uint16_t start_handle) { +// m_char_discovery_service = service; + +// ble_gattc_handle_range_t handle_range; +// handle_range.start_handle = start_handle; +// handle_range.end_handle = service->end_handle; + +// m_discovery_successful = false; +// m_discovery_in_process = true; + +// uint32_t err_code = sd_ble_gattc_characteristics_discover(connection->conn_handle, &handle_range); +// if (err_code != NRF_SUCCESS) { +// return false; +// } + +// // Wait for a discovery event. +// while (m_discovery_in_process) { +// MICROPY_VM_HOOK_LOOP; +// } +// return m_discovery_successful; +// } + +// STATIC bool discover_next_descriptors(bleio_connection_internal_t* connection, bleio_characteristic_obj_t *characteristic, uint16_t start_handle, uint16_t end_handle) { +// m_desc_discovery_characteristic = characteristic; + +// ble_gattc_handle_range_t handle_range; +// handle_range.start_handle = start_handle; +// handle_range.end_handle = end_handle; + +// m_discovery_successful = false; +// m_discovery_in_process = true; + +// uint32_t err_code = sd_ble_gattc_descriptors_discover(connection->conn_handle, &handle_range); +// if (err_code != NRF_SUCCESS) { +// return false; +// } + +// // Wait for a discovery event. +// while (m_discovery_in_process) { +// MICROPY_VM_HOOK_LOOP; +// } +// return m_discovery_successful; +// } + +// STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *response, bleio_connection_internal_t* connection) { +// for (size_t i = 0; i < response->count; ++i) { +// ble_gattc_service_t *gattc_service = &response->services[i]; + +// bleio_service_obj_t *service = m_new_obj(bleio_service_obj_t); +// service->base.type = &bleio_service_type; + +// // Initialize several fields at once. +// bleio_service_from_connection(service, bleio_connection_new_from_internal(connection)); + +// service->is_remote = true; +// service->start_handle = gattc_service->handle_range.start_handle; +// service->end_handle = gattc_service->handle_range.end_handle; +// service->handle = gattc_service->handle_range.start_handle; + +// if (gattc_service->uuid.type != BLE_UUID_TYPE_UNKNOWN) { +// // Known service UUID. +// bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t); +// uuid->base.type = &bleio_uuid_type; +// bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_service->uuid); +// service->uuid = uuid; +// } else { +// // The discovery response contained a 128-bit UUID that has not yet been registered with the +// // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it. +// // For now, just set the UUID to NULL. +// service->uuid = NULL; +// } +// +// mp_obj_list_append(MP_OBJ_FROM_PTR(connection->remote_service_list), +// MP_OBJ_FROM_PTR(service)); +// } +// +// if (response->count > 0) { +// m_discovery_successful = true; +// } +// m_discovery_in_process = false; +// } + +// STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio_connection_internal_t* connection) { +// for (size_t i = 0; i < response->count; ++i) { +// ble_gattc_char_t *gattc_char = &response->chars[i]; + +// bleio_characteristic_obj_t *characteristic = m_new_obj(bleio_characteristic_obj_t); +// characteristic->base.type = &bleio_characteristic_type; + +// bleio_uuid_obj_t *uuid = NULL; + +// if (gattc_char->uuid.type != BLE_UUID_TYPE_UNKNOWN) { +// // Known characteristic UUID. +// uuid = m_new_obj(bleio_uuid_obj_t); +// uuid->base.type = &bleio_uuid_type; +// bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_char->uuid); +// } else { +// // The discovery response contained a 128-bit UUID that has not yet been registered with the +// // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it. +// // For now, just leave the UUID as NULL. +// } + +// bleio_characteristic_properties_t props = +// (gattc_char->char_props.broadcast ? CHAR_PROP_BROADCAST : 0) | +// (gattc_char->char_props.indicate ? CHAR_PROP_INDICATE : 0) | +// (gattc_char->char_props.notify ? CHAR_PROP_NOTIFY : 0) | +// (gattc_char->char_props.read ? CHAR_PROP_READ : 0) | +// (gattc_char->char_props.write ? CHAR_PROP_WRITE : 0) | +// (gattc_char->char_props.write_wo_resp ? CHAR_PROP_WRITE_NO_RESPONSE : 0); + +// // Call common_hal_bleio_characteristic_construct() to initalize some fields and set up evt handler. +// common_hal_bleio_characteristic_construct( +// characteristic, m_char_discovery_service, gattc_char->handle_value, uuid, +// props, SECURITY_MODE_OPEN, SECURITY_MODE_OPEN, +// GATT_MAX_DATA_LENGTH, false, // max_length, fixed_length: values may not matter for gattc +// NULL); + +// mp_obj_list_append(MP_OBJ_FROM_PTR(m_char_discovery_service->characteristic_list), +// MP_OBJ_FROM_PTR(characteristic)); +// } + +// if (response->count > 0) { +// m_discovery_successful = true; +// } +// m_discovery_in_process = false; +// } + +// STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, bleio_connection_internal_t* connection) { +// for (size_t i = 0; i < response->count; ++i) { +// ble_gattc_desc_t *gattc_desc = &response->descs[i]; + +// // Remember handles for certain well-known descriptors. +// switch (gattc_desc->uuid.uuid) { +// case BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG: +// m_desc_discovery_characteristic->cccd_handle = gattc_desc->handle; +// break; + +// case BLE_UUID_DESCRIPTOR_SERVER_CHAR_CONFIG: +// m_desc_discovery_characteristic->sccd_handle = gattc_desc->handle; +// break; + +// case BLE_UUID_DESCRIPTOR_CHAR_USER_DESC: +// m_desc_discovery_characteristic->user_desc_handle = gattc_desc->handle; +// break; + +// default: +// // TODO: sd_ble_gattc_descriptors_discover() can return things that are not descriptors, +// // so ignore those. +// // https://devzone.nordicsemi.com/f/nordic-q-a/49500/sd_ble_gattc_descriptors_discover-is-returning-attributes-that-are-not-descriptors +// break; +// } + +// bleio_descriptor_obj_t *descriptor = m_new_obj(bleio_descriptor_obj_t); +// descriptor->base.type = &bleio_descriptor_type; + +// bleio_uuid_obj_t *uuid = NULL; + +// if (gattc_desc->uuid.type != BLE_UUID_TYPE_UNKNOWN) { +// // Known descriptor UUID. +// uuid = m_new_obj(bleio_uuid_obj_t); +// uuid->base.type = &bleio_uuid_type; +// bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_desc->uuid); +// } else { +// // The discovery response contained a 128-bit UUID that has not yet been registered with the +// // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it. +// // For now, just leave the UUID as NULL. +// } + +// common_hal_bleio_descriptor_construct( +// descriptor, m_desc_discovery_characteristic, uuid, +// SECURITY_MODE_OPEN, SECURITY_MODE_OPEN, +// GATT_MAX_DATA_LENGTH, false, mp_const_empty_bytes); +// descriptor->handle = gattc_desc->handle; + +// mp_obj_list_append(MP_OBJ_FROM_PTR(m_desc_discovery_characteristic->descriptor_list), +// MP_OBJ_FROM_PTR(descriptor)); +// } + +// if (response->count > 0) { +// m_discovery_successful = true; +// } +// m_discovery_in_process = false; +// } + +// STATIC bool discovery_on_ble_evt(ble_evt_t *ble_evt, mp_obj_t payload) { +// bleio_connection_internal_t* connection = MP_OBJ_TO_PTR(payload); +// switch (ble_evt->header.evt_id) { +// case BLE_GAP_EVT_DISCONNECTED: +// m_discovery_successful = false; +// m_discovery_in_process = false; +// break; + +// case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: +// on_primary_srv_discovery_rsp(&ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp, connection); +// break; + +// case BLE_GATTC_EVT_CHAR_DISC_RSP: +// on_char_discovery_rsp(&ble_evt->evt.gattc_evt.params.char_disc_rsp, connection); +// break; + +// case BLE_GATTC_EVT_DESC_DISC_RSP: +// on_desc_discovery_rsp(&ble_evt->evt.gattc_evt.params.desc_disc_rsp, connection); +// break; + +// default: +// // CONNECTION_DEBUG_PRINTF(&mp_plat_print, "Unhandled discovery event: 0x%04x\n", ble_evt->header.evt_id); +// return false; +// break; +// } +// return true; +// } + +// STATIC void discover_remote_services(bleio_connection_internal_t *self, mp_obj_t service_uuids_whitelist) { +// ble_drv_add_event_handler(discovery_on_ble_evt, self); + +// // Start over with an empty list. +// self->remote_service_list = mp_obj_new_list(0, NULL); + + +// if (service_uuids_whitelist == mp_const_none) { +// // List of service UUID's not given, so discover all available services. + +// uint16_t next_service_start_handle = BLE_GATT_HANDLE_START; + +// while (discover_next_services(self, next_service_start_handle, MP_OBJ_NULL)) { +// // discover_next_services() appends to remote_services_list. + +// // Get the most recently discovered service, and then ask for services +// // whose handles start after the last attribute handle inside that service. +// // There must be at least one if discover_next_services() returned true. +// const bleio_service_obj_t *service = +// self->remote_service_list->items[self->remote_service_list->len - 1]; +// next_service_start_handle = service->end_handle + 1; +// } +// } else { +// mp_obj_iter_buf_t iter_buf; +// mp_obj_t iterable = mp_getiter(service_uuids_whitelist, &iter_buf); +// mp_obj_t uuid_obj; +// while ((uuid_obj = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { +// if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) { +// mp_raise_TypeError(translate("non-UUID found in service_uuids_whitelist")); +// } +// bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_obj); + +// ble_uuid_t nrf_uuid; +// bleio_uuid_convert_to_nrf_ble_uuid(uuid, &nrf_uuid); + +// // Service might or might not be discovered; that's ok. Caller has to check +// // Central.remote_services to find out. +// // We only need to call this once for each service to discover. +// discover_next_services(self, BLE_GATT_HANDLE_START, &nrf_uuid); +// } +// } + + +// for (size_t i = 0; i < self->remote_service_list->len; i++) { +// bleio_service_obj_t *service = MP_OBJ_TO_PTR(self->remote_service_list->items[i]); +// // Skip the service if it had an unknown (unregistered) UUID. +// if (service->uuid == NULL) { +// continue; +// } + +// uint16_t next_char_start_handle = service->start_handle; + +// // Stop when we go past the end of the range of handles for this service or +// // discovery call returns nothing. +// // discover_next_characteristics() appends to the characteristic_list. +// while (next_char_start_handle <= service->end_handle && +// discover_next_characteristics(self, service, next_char_start_handle)) { + + +// // Get the most recently discovered characteristic, and then ask for characteristics +// // whose handles start after the last attribute handle inside that characteristic. +// const bleio_characteristic_obj_t *characteristic = +// MP_OBJ_TO_PTR(service->characteristic_list->items[service->characteristic_list->len - 1]); + +// next_char_start_handle = characteristic->handle + 1; +// } + +// // Got characteristics for this service. Now discover descriptors for each characteristic. +// size_t char_list_len = service->characteristic_list->len; +// for (size_t char_idx = 0; char_idx < char_list_len; ++char_idx) { +// bleio_characteristic_obj_t *characteristic = +// MP_OBJ_TO_PTR(service->characteristic_list->items[char_idx]); +// const bool last_characteristic = char_idx == char_list_len - 1; +// bleio_characteristic_obj_t *next_characteristic = last_characteristic +// ? NULL +// : MP_OBJ_TO_PTR(service->characteristic_list->items[char_idx + 1]); + +// // Skip the characteristic if it had an unknown (unregistered) UUID. +// if (characteristic->uuid == NULL) { +// continue; +// } + +// uint16_t next_desc_start_handle = characteristic->handle + 1; + +// // Don't run past the end of this service or the beginning of the next characteristic. +// uint16_t next_desc_end_handle = next_characteristic == NULL +// ? service->end_handle +// : next_characteristic->handle - 1; + +// // Stop when we go past the end of the range of handles for this service or +// // discovery call returns nothing. +// // discover_next_descriptors() appends to the descriptor_linked_list. +// while (next_desc_start_handle <= service->end_handle && +// next_desc_start_handle <= next_desc_end_handle && +// discover_next_descriptors(self, characteristic, +// next_desc_start_handle, next_desc_end_handle)) { +// // Get the most recently discovered descriptor, and then ask for descriptors +// // whose handles start after that descriptor's handle. +// // There must be at least one if discover_next_descriptors() returned true. +// const bleio_descriptor_obj_t *descriptor = +// characteristic->descriptor_list->items[characteristic->descriptor_list->len - 1]; +// next_desc_start_handle = descriptor->handle + 1; +// } +// } +// } + +// // This event handler is no longer needed. +// ble_drv_remove_event_handler(discovery_on_ble_evt, self); + +// } + +mp_obj_tuple_t *common_hal_bleio_connection_discover_remote_services(bleio_connection_obj_t *self, mp_obj_t service_uuids_whitelist) { + //FIX discover_remote_services(self->connection, service_uuids_whitelist); + bleio_connection_ensure_connected(self); + // Convert to a tuple and then clear the list so the callee will take ownership. + mp_obj_tuple_t *services_tuple = + mp_obj_new_tuple(self->connection->remote_service_list->len, + self->connection->remote_service_list->items); + mp_obj_list_clear(MP_OBJ_FROM_PTR(self->connection->remote_service_list)); + return services_tuple; +} + +uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self) { + if (self == NULL || self->connection == NULL) { + return BLE_CONN_HANDLE_INVALID; + } + return self->connection->conn_handle; +} + +mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t* internal) { + if (internal->connection_obj != mp_const_none) { + return internal->connection_obj; + } + bleio_connection_obj_t *connection = m_new_obj(bleio_connection_obj_t); + connection->base.type = &bleio_connection_type; + connection->connection = internal; + internal->connection_obj = connection; + + return MP_OBJ_FROM_PTR(connection); +} + +// Find the connection that uses the given conn_handle. Return NULL if not found. +bleio_connection_internal_t *bleio_conn_handle_to_connection(uint16_t conn_handle) { + bleio_connection_internal_t *connection; + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + connection = &bleio_connections[i]; + if (connection->conn_handle == conn_handle) { + return connection; + } + } + + return NULL; +} diff --git a/devices/ble_hci/common-hal/_bleio/Connection.h b/devices/ble_hci/common-hal/_bleio/Connection.h new file mode 100644 index 0000000000..0b1f26a213 --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/Connection.h @@ -0,0 +1,89 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CONNECTION_H +#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CONNECTION_H + +#include + +#include "py/obj.h" +#include "py/objlist.h" + +#include "common-hal/_bleio/__init__.h" +#include "shared-module/_bleio/Address.h" +#include "common-hal/_bleio/Service.h" + +typedef enum { + PAIR_NOT_PAIRED, + PAIR_WAITING, + PAIR_PAIRED, +} pair_status_t; + +// We split the Connection object into two so that the internal mechanics can live outside of the +// VM. If it were one object, then we'd risk user code seeing a connection object of theirs be +// reused. +typedef struct { + uint16_t conn_handle; + bool is_central; + // Remote services discovered when this peripheral is acting as a client. + mp_obj_list_t *remote_service_list; + // The advertising data and scan response buffers are held by us, not by the SD, so we must + // maintain them and not change it. If we need to change the contents during advertising, + // there are tricks to get the SD to notice (see DevZone - TBS). + bonding_keys_t bonding_keys; + // EDIV: Encrypted Diversifier: Identifies LTK during legacy pairing. + uint16_t ediv; + volatile pair_status_t pair_status; + uint8_t sec_status; // Internal security status. + mp_obj_t connection_obj; + //REMOVE ble_gap_conn_params_t conn_params; + volatile bool conn_params_updating; + uint16_t mtu; + // Request that CCCD values for this connection be saved, using sys_attr values. + volatile bool do_bond_cccds; + // Request that security key info for this connection be saved. + volatile bool do_bond_keys; + // Time of setting do_bond_ccds: we delay a bit to consolidate multiple CCCD changes + // into one write. Time is currently in ticks_ms. + uint64_t do_bond_cccds_request_time; + //FIX from att.c + uint8_t role; + bt_addr_le_t addr; +} bleio_connection_internal_t; + +typedef struct { + mp_obj_base_t base; + bleio_connection_internal_t* connection; + // The HCI disconnect reason. + uint8_t disconnect_reason; +} bleio_connection_obj_t; + +uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self); +mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t* connection); +bleio_connection_internal_t *bleio_conn_handle_to_connection(uint16_t conn_handle); + +#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CONNECTION_H diff --git a/devices/ble_hci/common-hal/_bleio/Descriptor.c b/devices/ble_hci/common-hal/_bleio/Descriptor.c new file mode 100644 index 0000000000..645273e285 --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/Descriptor.c @@ -0,0 +1,114 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * Copyright (c) 2016 Glenn Ruben Bakke + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" + +#include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Descriptor.h" +#include "shared-bindings/_bleio/Service.h" +#include "shared-bindings/_bleio/UUID.h" + +void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_characteristic_obj_t *characteristic, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) { + self->characteristic = characteristic; + self->uuid = uuid; + self->handle = BLE_GATT_HANDLE_INVALID; + self->read_perm = read_perm; + self->write_perm = write_perm; + self->value = mp_obj_new_bytes(initial_value_bufinfo->buf, initial_value_bufinfo->len); + + const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_MAX; + if (max_length < 0 || max_length > max_length_max) { + mp_raise_ValueError_varg(translate("max_length must be 0-%d when fixed_length is %s"), + max_length_max, fixed_length ? "True" : "False"); + } + self->max_length = max_length; + self->fixed_length = fixed_length; + + common_hal_bleio_descriptor_set_value(self, initial_value_bufinfo); +} + +bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self) { + return self->uuid; +} + +bleio_characteristic_obj_t *common_hal_bleio_descriptor_get_characteristic(bleio_descriptor_obj_t *self) { + return self->characteristic; +} + +size_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self, uint8_t* buf, size_t len) { + // Do GATT operations only if this descriptor has been registered + if (self->handle != BLE_GATT_HANDLE_INVALID) { + if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) { + //uint16_t conn_handle = bleio_connection_get_conn_handle(self->characteristic->service->connection); + //FIX have att_read_req fill in a buffer + //uint8_t rsp[MAX(len, 512)]; + //return att_read_req(conn_handle, self->handle, rsp, len); + return 0; + } else { + mp_buffer_info_t bufinfo; + if (!mp_get_buffer(self->value, &bufinfo, MP_BUFFER_READ)) { + return 0; + } + const size_t actual_length = MIN(len, bufinfo.len); + memcpy(buf, bufinfo.buf, actual_length); + return actual_length; + } + } + + return 0; +} + +void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buffer_info_t *bufinfo) { + if (self->fixed_length && bufinfo->len != self->max_length) { + mp_raise_ValueError(translate("Value length != required fixed length")); + } + if (bufinfo->len > self->max_length) { + mp_raise_ValueError(translate("Value length > max_length")); + } + + self->value = mp_obj_new_bytes(bufinfo->buf, bufinfo->len); + + // Do GATT operations only if this descriptor has been registered. + if (self->handle != BLE_GATT_HANDLE_INVALID) { + if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) { + //FIX + // uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); + // att_write_req(conn_handle, self->handle, bufinfo->buf, bufinfo->len, rsp); + } else { + // Always write the value locally even if no connections are active. + if (self->fixed_length && bufinfo->len != self->max_length) { + return; + } + if (bufinfo->len > self->max_length) { + return; + } + + self->value = mp_obj_new_bytes(bufinfo->buf, bufinfo->len); + } + } +} diff --git a/devices/ble_hci/common-hal/_bleio/Descriptor.h b/devices/ble_hci/common-hal/_bleio/Descriptor.h new file mode 100644 index 0000000000..097a49f8ec --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/Descriptor.h @@ -0,0 +1,53 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * Copyright (c) 2016 Glenn Ruben Bakke + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_DESCRIPTOR_H +#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_DESCRIPTOR_H + +#include "py/obj.h" + +#include "common-hal/_bleio/UUID.h" + +// Forward declare characteristic because it includes a Descriptor. +struct _bleio_characteristic_obj; + +typedef struct _bleio_descriptor_obj { + mp_obj_base_t base; + // Will be MP_OBJ_NULL before being assigned to a Characteristic. + struct _bleio_characteristic_obj *characteristic; + bleio_uuid_obj_t *uuid; + mp_obj_t value; + uint16_t max_length; + bool fixed_length; + uint16_t handle; + bleio_attribute_security_mode_t read_perm; + bleio_attribute_security_mode_t write_perm; + struct _bleio_descriptor_obj* next; +} bleio_descriptor_obj_t; + +#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_DESCRIPTOR_H diff --git a/devices/ble_hci/common-hal/_bleio/PacketBuffer.c b/devices/ble_hci/common-hal/_bleio/PacketBuffer.c new file mode 100644 index 0000000000..98912ba902 --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/PacketBuffer.c @@ -0,0 +1,265 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019-2020 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "lib/utils/interrupt_char.h" +#include "py/runtime.h" +#include "py/stream.h" + +#include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Connection.h" +#include "shared-bindings/_bleio/PacketBuffer.h" +#include "supervisor/shared/tick.h" + +STATIC void write_to_ringbuf(bleio_packet_buffer_obj_t *self, uint8_t *data, uint16_t len) { + if (len + sizeof(uint16_t) > ringbuf_capacity(&self->ringbuf)) { + // This shouldn't happen. + return; + } + // Push all the data onto the ring buffer. + // Make room for the new value by dropping the oldest packets first. + while (ringbuf_capacity(&self->ringbuf) - ringbuf_num_filled(&self->ringbuf) < len + sizeof(uint16_t)) { + uint16_t packet_length; + ringbuf_get_n(&self->ringbuf, (uint8_t*) &packet_length, sizeof(uint16_t)); + for (uint16_t i = 0; i < packet_length; i++) { + ringbuf_get(&self->ringbuf); + } + // set an overflow flag? + } + ringbuf_put_n(&self->ringbuf, (uint8_t*) &len, sizeof(uint16_t)); + ringbuf_put_n(&self->ringbuf, data, len); +} + +STATIC uint32_t queue_next_write(bleio_packet_buffer_obj_t *self) { + // Queue up the next outgoing buffer. We use two, one that has been passed to the SD for + // transmission (when packet_queued is true) and the other is `pending` and can still be + // modified. By primarily appending to the `pending` buffer we can reduce the protocol overhead + // of the lower level link and ATT layers. + self->packet_queued = false; + if (self->pending_size > 0) { + mp_buffer_info_t bufinfo = { + .buf = self->outgoing[self->pending_index], + .len = self->pending_size, + }; + common_hal_bleio_characteristic_set_value(self->characteristic, &bufinfo); + + self->pending_size = 0; + self->pending_index = (self->pending_index + 1) % 2; + self->packet_queued = true; + } + return 0; +} + +void bleio_packet_buffer_update(bleio_packet_buffer_obj_t *self, mp_buffer_info_t *bufinfo) { + write_to_ringbuf(self, bufinfo->buf, bufinfo->len); +} + +void common_hal_bleio_packet_buffer_construct( + bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic, + size_t buffer_size) { + + self->characteristic = characteristic; + self->client = self->characteristic->service->is_remote; + bleio_characteristic_properties_t incoming = + self->characteristic->props & (CHAR_PROP_WRITE_NO_RESPONSE | CHAR_PROP_WRITE); + bleio_characteristic_properties_t outgoing = + self->characteristic->props & (CHAR_PROP_NOTIFY | CHAR_PROP_INDICATE); + + if (self->client) { + // Swap if we're the client. + bleio_characteristic_properties_t temp = incoming; + incoming = outgoing; + outgoing = temp; + self->conn_handle = bleio_connection_get_conn_handle(MP_OBJ_TO_PTR(self->characteristic->service->connection)); + } else { + self->conn_handle = BLE_CONN_HANDLE_INVALID; + } + + if (incoming) { + if (!ringbuf_alloc(&self->ringbuf, buffer_size * (sizeof(uint16_t) + characteristic->max_length), false)) { + mp_raise_ValueError(translate("Buffer too large and unable to allocate")); + } + } + + if (outgoing) { + self->packet_queued = false; + self->pending_index = 0; + self->pending_size = 0; + self->outgoing[0] = m_malloc(characteristic->max_length, false); + self->outgoing[1] = m_malloc(characteristic->max_length, false); + } else { + self->outgoing[0] = NULL; + self->outgoing[1] = NULL; + } + + bleio_characteristic_set_observer(self->characteristic, self); +} + +mp_int_t common_hal_bleio_packet_buffer_readinto(bleio_packet_buffer_obj_t *self, uint8_t *data, size_t len) { + if (ringbuf_num_filled(&self->ringbuf) < 2) { + return 0; + } + + // Copy received data. + // Get packet length, which is in first two bytes of packet. + uint16_t packet_length; + ringbuf_get_n(&self->ringbuf, (uint8_t*) &packet_length, sizeof(uint16_t)); + + mp_int_t ret; + if (packet_length > len) { + // Packet is longer than requested. Return negative of overrun value. + ret = len - packet_length; + // Discard the packet if it's too large. Don't fill data. + while (packet_length--) { + (void) ringbuf_get(&self->ringbuf); + } + } else { + // Read as much as possible, but might be shorter than len. + ringbuf_get_n(&self->ringbuf, data, packet_length); + ret = packet_length; + } + + return ret; +} + +mp_int_t common_hal_bleio_packet_buffer_write(bleio_packet_buffer_obj_t *self, uint8_t *data, size_t len, uint8_t* header, size_t header_len) { + if (self->outgoing[0] == NULL) { + mp_raise_bleio_BluetoothError(translate("Writes not supported on Characteristic")); + } + if (self->conn_handle == BLE_CONN_HANDLE_INVALID) { + return -1; + } + uint16_t outgoing_packet_length = common_hal_bleio_packet_buffer_get_outgoing_packet_length(self); + + if (len + header_len > outgoing_packet_length) { + // Supplied data will not fit in a single BLE packet. + mp_raise_ValueError(translate("Total data to write is larger than outgoing_packet_length")); + } + + if (len + self->pending_size > outgoing_packet_length) { + // No room to append len bytes to packet. Wait until we get a free buffer, + // and keep checking that we haven't been disconnected. + while (self->pending_size != 0 && self->conn_handle != BLE_CONN_HANDLE_INVALID) { + RUN_BACKGROUND_TASKS; + } + } + if (self->conn_handle == BLE_CONN_HANDLE_INVALID) { + return -1; + } + + size_t num_bytes_written = 0; + + uint8_t* pending = self->outgoing[self->pending_index]; + + if (self->pending_size == 0) { + memcpy(pending, header, header_len); + self->pending_size += header_len; + num_bytes_written += header_len; + } + memcpy(pending + self->pending_size, data, len); + self->pending_size += len; + num_bytes_written += len; + + // If no writes are queued then sneak in this data. + if (!self->packet_queued) { + queue_next_write(self); + } + return num_bytes_written; +} + +mp_int_t common_hal_bleio_packet_buffer_get_incoming_packet_length(bleio_packet_buffer_obj_t *self) { + // If this PacketBuffer is coming from a remote service via NOTIFY or INDICATE + // the maximum size is what can be sent in one + // BLE packet. But we must be connected to know that value. + // + // Otherwise it can be as long as the characteristic + // will permit, whether or not we're connected. + + if (self->characteristic == NULL) { + return -1; + } + + if (self->characteristic->service != NULL && + self->characteristic->service->is_remote && + (common_hal_bleio_characteristic_get_properties(self->characteristic) & + (CHAR_PROP_INDICATE | CHAR_PROP_NOTIFY))) { + // We are talking to a remote service, and data is arriving via NOTIFY or INDICATE. + if (self->conn_handle != BLE_CONN_HANDLE_INVALID) { + bleio_connection_internal_t *connection = bleio_conn_handle_to_connection(self->conn_handle); + if (connection) { + return MIN(common_hal_bleio_connection_get_max_packet_length(connection), + self->characteristic->max_length); + } + } + // There's no current connection, so we don't know the MTU, and + // we can't tell what the largest incoming packet length would be. + return -1; + } + return self->characteristic->max_length; +} + +mp_int_t common_hal_bleio_packet_buffer_get_outgoing_packet_length(bleio_packet_buffer_obj_t *self) { + // If we are sending data via NOTIFY or INDICATE, the maximum size + // is what can be sent in one BLE packet. But we must be connected + // to know that value. + // + // Otherwise it can be as long as the characteristic + // will permit, whether or not we're connected. + + if (self->characteristic == NULL) { + return -1; + } + + if (self->characteristic->service != NULL && + !self->characteristic->service->is_remote && + (common_hal_bleio_characteristic_get_properties(self->characteristic) & + (CHAR_PROP_INDICATE | CHAR_PROP_NOTIFY))) { + // We are sending to a client, via NOTIFY or INDICATE. + if (self->conn_handle != BLE_CONN_HANDLE_INVALID) { + bleio_connection_internal_t *connection = bleio_conn_handle_to_connection(self->conn_handle); + if (connection) { + return MIN(common_hal_bleio_connection_get_max_packet_length(connection), + self->characteristic->max_length); + } + } + // There's no current connection, so we don't know the MTU, and + // we can't tell what the largest outgoing packet length would be. + return -1; + } + return self->characteristic->max_length; +} + +bool common_hal_bleio_packet_buffer_deinited(bleio_packet_buffer_obj_t *self) { + return self->characteristic == NULL; +} + +void common_hal_bleio_packet_buffer_deinit(bleio_packet_buffer_obj_t *self) { + if (!common_hal_bleio_packet_buffer_deinited(self)) { + bleio_characteristic_clear_observer(self->characteristic); + } +} diff --git a/devices/ble_hci/common-hal/_bleio/PacketBuffer.h b/devices/ble_hci/common-hal/_bleio/PacketBuffer.h new file mode 100644 index 0000000000..074c03dc69 --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/PacketBuffer.h @@ -0,0 +1,53 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019-2020 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_PACKETBUFFER_H +#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_PACKETBUFFER_H + +#include "py/ringbuf.h" +#include "shared-bindings/_bleio/Characteristic.h" + +typedef struct { + mp_obj_base_t base; + bleio_characteristic_obj_t *characteristic; + // Ring buffer storing consecutive incoming values. + ringbuf_t ringbuf; + // Two outgoing buffers to alternate between. One will be queued for transmission by the SD and + // the other is waiting to be queued and can be extended. + uint8_t* outgoing[2]; + volatile uint16_t pending_size; + // We remember the conn_handle so we can do a NOTIFY/INDICATE to a client. + // We can find out the conn_handle on a Characteristic write or a CCCD write (but not a read). + volatile uint16_t conn_handle; + uint8_t pending_index; + uint8_t write_type; + bool client; + bool packet_queued; +} bleio_packet_buffer_obj_t; + +void bleio_packet_buffer_update(bleio_packet_buffer_obj_t *self, mp_buffer_info_t *bufinfo); + +#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_PACKETBUFFER_H diff --git a/devices/ble_hci/common-hal/_bleio/Service.c b/devices/ble_hci/common-hal/_bleio/Service.c new file mode 100644 index 0000000000..5803f5309d --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/Service.c @@ -0,0 +1,129 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Characteristic.h" +#include "shared-bindings/_bleio/Descriptor.h" +#include "shared-bindings/_bleio/Service.h" +#include "shared-bindings/_bleio/Adapter.h" + +uint32_t _common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary, mp_obj_list_t * characteristic_list) { + self->uuid = uuid; + self->characteristic_list = characteristic_list; + self->is_remote = false; + self->connection = NULL; + self->is_secondary = is_secondary; + + vm_used_ble = true; + + self->handle = bleio_adapter_add_attribute(&common_hal_bleio_adapter_obj, MP_OBJ_TO_PTR(self)); + self->start_handle = self->handle; + self->end_handle = self->handle; + if (self->handle == BLE_GATT_HANDLE_INVALID) { + return 1; + } + return 0; +} + +void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary) { + if (_common_hal_bleio_service_construct(self, uuid, is_secondary, + mp_obj_new_list(0, NULL)) != 0) { + mp_raise_RuntimeError(translate("Failed to add service")); + } +} + +void bleio_service_from_connection(bleio_service_obj_t *self, mp_obj_t connection) { + self->handle = 0xFFFF; + self->uuid = NULL; + self->characteristic_list = mp_obj_new_list(0, NULL); + self->is_remote = true; + self->is_secondary = false; + self->connection = connection; +} + +bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self) { + return self->uuid; +} + +mp_obj_tuple_t *common_hal_bleio_service_get_characteristics(bleio_service_obj_t *self) { + return mp_obj_new_tuple(self->characteristic_list->len, self->characteristic_list->items); +} + +bool common_hal_bleio_service_get_is_remote(bleio_service_obj_t *self) { + return self->is_remote; +} + +bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self) { + return self->is_secondary; +} + +void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, + bleio_characteristic_obj_t *characteristic, + mp_buffer_info_t *initial_value_bufinfo) { + + if (self->handle != common_hal_bleio_adapter_obj.last_added_service_handle) { + mp_raise_bleio_BluetoothError( + translate("Characteristic can only be added to most recently added service")); + } + characteristic->decl_handle = bleio_adapter_add_attribute( + &common_hal_bleio_adapter_obj, MP_OBJ_TO_PTR(characteristic)); + // This is the value handle. + characteristic->handle = bleio_adapter_add_attribute( + &common_hal_bleio_adapter_obj, MP_OBJ_TO_PTR(characteristic)); + + self->end_handle = characteristic->handle; + + if (characteristic->props & (CHAR_PROP_NOTIFY | CHAR_PROP_INDICATE)) { + // We need a CCCD if this characteristic is doing notify or indicate. + bleio_descriptor_obj_t *cccd = m_new_obj(bleio_descriptor_obj_t); + cccd->base.type = &bleio_descriptor_type; + + uint16_t zero = 0; + mp_buffer_info_t zero_cccd_value = { + .buf = &zero, + .len = sizeof(zero), + }; + + common_hal_bleio_descriptor_construct( + cccd, + characteristic, + &cccd_uuid, // 0x2902 + SECURITY_MODE_OPEN, // CCCD read perm + characteristic->read_perm, // Make CCCD write perm match characteristic read perm. + 2, // 2 bytes + true, // fixed length + &zero_cccd_value // Initial value is 0. + ); + + // Adds CCCD to attribute table, and also extends self->end_handle to include the CCCD. + common_hal_bleio_characteristic_add_descriptor(characteristic, cccd); + characteristic->cccd = cccd; + } + + mp_obj_list_append(self->characteristic_list, MP_OBJ_FROM_PTR(characteristic)); +} diff --git a/devices/ble_hci/common-hal/_bleio/Service.h b/devices/ble_hci/common-hal/_bleio/Service.h new file mode 100644 index 0000000000..11e7d1c960 --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/Service.h @@ -0,0 +1,54 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_SERVICE_H +#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_SERVICE_H + +#include "py/objlist.h" +#include "common-hal/_bleio/UUID.h" + +typedef struct bleio_service_obj { + mp_obj_base_t base; + // Handle for the local service. + uint16_t handle; + // True if created during discovery. + bool is_remote; + bool is_secondary; + bleio_uuid_obj_t *uuid; + // The connection object is set only when this is a remote service. + // A local service doesn't know the connection. + mp_obj_t connection; + mp_obj_list_t *characteristic_list; + // Range of attribute handles of this service. + uint16_t start_handle; + uint16_t end_handle; + struct bleio_service_obj* next; +} bleio_service_obj_t; + +void bleio_service_from_connection(bleio_service_obj_t *self, mp_obj_t connection); + +#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_SERVICE_H diff --git a/devices/ble_hci/common-hal/_bleio/UUID.c b/devices/ble_hci/common-hal/_bleio/UUID.c new file mode 100644 index 0000000000..a50efc3b1e --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/UUID.c @@ -0,0 +1,75 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * Copyright (c) 2016 Glenn Ruben Bakke + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "py/runtime.h" +#include "common-hal/_bleio/UUID.h" +#include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Adapter.h" + +// If uuid128 is NULL, this is a Bluetooth SIG 16-bit UUID. +// If uuid128 is not NULL, it's a 128-bit (16-byte) UUID, with bytes 12 and 13 zero'd out, where +// the 16-bit part goes. Those 16 bits are passed in uuid16. +void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, mp_int_t uuid16, const uint8_t uuid128[16]) { + self->size = uuid128 == NULL ? 16 : 128; + self->uuid16 = uuid16; + if (uuid128) { + memcpy(self->uuid128, uuid128, 16); + self->uuid128[12] = uuid16 & 0xff; + self->uuid128[13] = uuid16 >> 8; + } else { + memset(self->uuid128, 0, 16); + } +} + +uint32_t common_hal_bleio_uuid_get_size(bleio_uuid_obj_t *self) { + return self->size; +} + +uint32_t common_hal_bleio_uuid_get_uuid16(bleio_uuid_obj_t *self) { + return self->uuid16; +} + +void common_hal_bleio_uuid_get_uuid128(bleio_uuid_obj_t *self, uint8_t uuid128[16]) { + memcpy(uuid128, self->uuid128, 16); +} + +void common_hal_bleio_uuid_pack_into(bleio_uuid_obj_t *self, uint8_t* buf) { + if (self->size == 16) { + buf[0] = self->uuid16 & 0xff; + buf[1] = self->uuid16 >> 8; + } else { + common_hal_bleio_uuid_get_uuid128(self, buf); + } +} + +// Return a uui16 only if this is a standard uuid. Otherwise return BLE_UUID_UNKNOWN. +uint16_t bleio_uuid_get_uuid16_or_unknown(bleio_uuid_obj_t *uuid) { + return uuid->size == 16 ? uuid->uuid16 : BLE_UUID_UNKNOWN; +} diff --git a/devices/ble_hci/common-hal/_bleio/UUID.h b/devices/ble_hci/common-hal/_bleio/UUID.h new file mode 100644 index 0000000000..1a0ab91c44 --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/UUID.h @@ -0,0 +1,58 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * Copyright (c) 2016 Glenn Ruben Bakke + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_UUID_H +#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_UUID_H + +#include "py/obj.h" + +// Types returned by attribute table lookups. These are UUIDs. +typedef enum { + BLE_UUID_UNKNOWN = 0x0000, + BLE_UUID_SERVICE_PRIMARY = 0x2800, + BLE_UUID_SERVICE_SECONDARY = 0x2801, + BLE_UUID_SERVICE_INCLUDE = 0x2802, // not yet implemented by us + BLE_UUID_CHARACTERISTIC = 0x2803, + BLE_UUID_CHAR_EXTENDED_PROPS = 0x2900, // not yet implemented by us + BLE_UUID_CHAR_USER_DESC = 0x2901, // not yet implemented by us + BLE_UUID_CCCD = 0x2902, + BLE_UUID_SCCD = 0x2903, // not yet implemented by us + BLE_UUID_CHAR_PRESENTATION_FMT = 0x2904, // not yet implemented by us + BLE_UUID_CHAR_AGGREGATE_FMT = 0x2905, // not yet implemented by us +} ble_standard_uuid; + +typedef struct { + mp_obj_base_t base; + uint8_t size; + uint16_t uuid16; + uint8_t uuid128[16]; +} bleio_uuid_obj_t; + +uint16_t bleio_uuid_get_uuid16_or_unknown(bleio_uuid_obj_t *uuid); + +#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_UUID_H diff --git a/devices/ble_hci/common-hal/_bleio/__init__.c b/devices/ble_hci/common-hal/_bleio/__init__.c new file mode 100644 index 0000000000..9fc4b480d9 --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/__init__.c @@ -0,0 +1,112 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Dan Halbert for Adafruit Industries + * Copyright (c) 2018 Artur Pacholec + * Copyright (c) 2016 Glenn Ruben Bakke + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "py/runtime.h" +#include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Adapter.h" +#include "shared-bindings/_bleio/Characteristic.h" +#include "shared-bindings/_bleio/Connection.h" +#include "shared-bindings/_bleio/Descriptor.h" +#include "shared-bindings/_bleio/Service.h" +#include "shared-bindings/_bleio/UUID.h" +#include "supervisor/shared/bluetooth.h" + +// UUID shared by all cccd's. +bleio_uuid_obj_t cccd_uuid; + +bool vm_used_ble; + +// void check_sec_status(uint8_t sec_status) { +// if (sec_status == BLE_GAP_SEC_STATUS_SUCCESS) { +// return; +// } + +// switch (sec_status) { +// case BLE_GAP_SEC_STATUS_UNSPECIFIED: +// mp_raise_bleio_SecurityError(translate("Unspecified issue. Can be that the pairing prompt on the other device was declined or ignored.")); +// return; +// default: +// mp_raise_bleio_SecurityError(translate("Unknown security error: 0x%04x"), sec_status); +// } +// } + +// Turn off BLE on a reset or reload. +void bleio_reset() { + // Create a UUID object for all CCCD's. + cccd_uuid.base.type = &bleio_uuid_type; + common_hal_bleio_uuid_construct(&cccd_uuid, BLE_UUID_CCCD, NULL); + + bleio_hci_reset(); + + if (!common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) { + return; + } + bleio_adapter_reset(&common_hal_bleio_adapter_obj); + if (!vm_used_ble) { + // No user-code BLE operations were done, so we can maintain the supervisor state. + return; + } + common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, false); + common_hal_bleio_adapter_obj.allocated = false; + + bleio_set_adapter(mp_const_none); + + //FIX bonding_reset(); + supervisor_start_bluetooth(); +} + +// The singleton _bleio.Adapter object, bound to _bleio.adapter +bleio_adapter_obj_t common_hal_bleio_adapter_obj = { + .base = { + .type = &bleio_adapter_type, + }, +}; + +bleio_adapter_obj_t *common_hal_bleio_allocate_adapter_or_raise(void) { + if (common_hal_bleio_adapter_obj.allocated) { + mp_raise_RuntimeError(translate("Too many Adapters")); + } + return &common_hal_bleio_adapter_obj; +} + +void common_hal_bleio_check_connected(uint16_t conn_handle) { + if (conn_handle == BLE_CONN_HANDLE_INVALID) { + mp_raise_bleio_ConnectionError(translate("Not connected")); + } +} + +void common_hal_bleio_gc_collect(void) { + bleio_adapter_gc_collect(&common_hal_bleio_adapter_obj); +} + + +void bleio_background(void) { + bleio_adapter_background(&common_hal_bleio_adapter_obj); +} diff --git a/devices/ble_hci/common-hal/_bleio/__init__.h b/devices/ble_hci/common-hal/_bleio/__init__.h new file mode 100644 index 0000000000..cd9940bf06 --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/__init__.h @@ -0,0 +1,62 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Dan Halbert for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_INIT_H +#define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_INIT_H + +#include + +#include "shared-bindings/_bleio/UUID.h" + +#include "att.h" +#include "hci.h" + +void bleio_background(void); +void bleio_reset(void); + +typedef struct { + // ble_gap_enc_key_t own_enc; + // ble_gap_enc_key_t peer_enc; + // ble_gap_id_key_t peer_id; +} bonding_keys_t; + +// We assume variable length data. +// 20 bytes max (23 - 3). +#define GATT_MAX_DATA_LENGTH (BT_ATT_DEFAULT_LE_MTU - 3) + +//FIX +#define BLE_GATT_HANDLE_INVALID 0x0000 +#define BLE_CONN_HANDLE_INVALID 0xFFFF +#define BLE_GATTS_FIX_ATTR_LEN_MAX (510) /**< Maximum length for fixed length Attribute Values. */ +#define BLE_GATTS_VAR_ATTR_LEN_MAX (512) /**< Maximum length for variable length Attribute Values. */ + +// Track if the user code modified the BLE state to know if we need to undo it on reload. +extern bool vm_used_ble; + +// UUID shared by all CCCD's. +extern bleio_uuid_obj_t cccd_uuid; + +#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_INIT_H diff --git a/devices/ble_hci/common-hal/_bleio/att.c b/devices/ble_hci/common-hal/_bleio/att.c new file mode 100644 index 0000000000..591e508a65 --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/att.c @@ -0,0 +1,1787 @@ +// Derived from ArduinoBLE. +// Copyright 2020 Dan Halbert for Adafruit Industries + +/* + This file is part of the ArduinoBLE library. + Copyright (c) 2018 Arduino SA. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "hci.h" +#include "att.h" + +// Zephyr include files to define HCI communication values and structs. +//#include "hci_include/hci.h" +//#include "hci_include/hci_err.h" +#include "hci_include/l2cap_internal.h" + +#include "py/obj.h" +#include "common-hal/_bleio/Adapter.h" +#include "common-hal/_bleio/Attribute.h" +#include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Characteristic.h" +#include "shared-bindings/_bleio/Descriptor.h" +#include "shared-bindings/_bleio/Service.h" +#include "shared-bindings/_bleio/UUID.h" +#include "supervisor/shared/tick.h" + +STATIC uint16_t max_mtu = BT_ATT_DEFAULT_LE_MTU; // 23 +STATIC unsigned long timeout = 5000; + +STATIC volatile bool confirm; + +STATIC uint16_t long_write_handle = BLE_GATT_HANDLE_INVALID; +STATIC uint8_t* long_write_value = NULL; +STATIC uint16_t long_write_value_length = 0; + +// When we send a request, fill this struct with info about the expected response. +// We check this against the actual received response. +STATIC struct { + uint16_t conn_handle; // Expected handle. + uint8_t opcode; // Expected RSP opcode. + uint8_t* buffer; // Pointer to response packet + uint8_t length; // Length of response packet. +} expected_rsp; + +// A characteristic declaration has this data, in this order: +// See Bluetooth v5.1 spec, section 3.3.1 Characteristic declaration. +typedef struct __packed { + uint8_t properties; + uint16_t value_handle; + uint8_t uuid[0]; // 2 or 16 bytes +} characteristic_declaration_t; + +STATIC uint8_t bleio_properties_to_ble_spec_properties(uint8_t bleio_properties) { + uint8_t ble_spec_properties = 0; + if (bleio_properties & CHAR_PROP_BROADCAST) { + ble_spec_properties |= BT_GATT_CHRC_BROADCAST; + } + if (bleio_properties & CHAR_PROP_INDICATE) { + ble_spec_properties |= BT_GATT_CHRC_INDICATE; + } + if (bleio_properties & CHAR_PROP_NOTIFY) { + ble_spec_properties |= BT_GATT_CHRC_NOTIFY; + } + if (bleio_properties & CHAR_PROP_READ) { + ble_spec_properties |= BT_GATT_CHRC_READ; + } + if (bleio_properties & CHAR_PROP_WRITE) { + ble_spec_properties |= BT_GATT_CHRC_WRITE; + } + if (bleio_properties & CHAR_PROP_WRITE_NO_RESPONSE) { + ble_spec_properties |= BT_GATT_CHRC_WRITE_WITHOUT_RESP; + } + + return ble_spec_properties; +} + +//FIX not currently used; reenable when used. +#if 0 +STATIC uint8_t ble_spec_properties_to_bleio_properties(uint8_t ble_spec_properties) { + uint8_t bleio_properties = 0; + if (ble_spec_properties & BT_GATT_CHRC_BROADCAST) { + bleio_properties |= CHAR_PROP_BROADCAST; + } + if (ble_spec_properties & BT_GATT_CHRC_INDICATE) { + bleio_properties |= CHAR_PROP_INDICATE; + } + if (ble_spec_properties & BT_GATT_CHRC_NOTIFY) { + bleio_properties |= CHAR_PROP_NOTIFY; + } + if (ble_spec_properties & BT_GATT_CHRC_READ) { + bleio_properties |= CHAR_PROP_READ; + } + if (ble_spec_properties & BT_GATT_CHRC_WRITE) { + bleio_properties |= CHAR_PROP_WRITE; + } + if (ble_spec_properties & BT_GATT_CHRC_WRITE_WITHOUT_RESP) { + bleio_properties |= CHAR_PROP_WRITE_NO_RESPONSE; + } + + return bleio_properties; +} +#endif // #if 0 + +STATIC void send_error(uint16_t conn_handle, uint8_t opcode, uint16_t handle, uint8_t code) { + struct __packed { + struct bt_att_hdr h; + struct bt_att_error_rsp r; + } rsp = { { + .code = BT_ATT_OP_ERROR_RSP, + }, { + .request = opcode, + } + }; + + hci_send_acl_pkt(conn_handle, BT_L2CAP_CID_ATT, sizeof(rsp), (uint8_t *) &rsp); +} + +STATIC void send_req(uint16_t conn_handle, size_t request_length, uint8_t* request_buffer) { + hci_send_acl_pkt(conn_handle, BT_L2CAP_CID_ATT, request_length, request_buffer); +} + +STATIC int send_req_wait_for_rsp(uint16_t conn_handle, size_t request_length, uint8_t* request_buffer, uint8_t response_buffer[]) { + // We expect a particular kind of response after this request. + expected_rsp.conn_handle = conn_handle; + // The response opcode is the request opcode + 1. + expected_rsp.opcode = request_buffer[0] + 1; + expected_rsp.buffer = response_buffer; + expected_rsp.length = 0; + + send_req(conn_handle, request_length, request_buffer); + + if (response_buffer == NULL) { + // not expecting a response. + return 0; + } + + for (uint64_t start = supervisor_ticks_ms64(); supervisor_ticks_ms64() - start < timeout;) { + // RUN_BACKGROUND_TASKS includes hci_poll_for_incoming_pkt(); + RUN_BACKGROUND_TASKS; + + if (!att_handle_is_connected(conn_handle)) { + break; + } + + if (expected_rsp.length != 0) { + expected_rsp.conn_handle = 0xffff; + return expected_rsp.length; + } + } + + expected_rsp.conn_handle = 0xffff; + return 0; +} + +// If a response matches what is in expected_rsp, copy the rest of it into the buffer. +STATIC void check_and_save_expected_rsp(uint16_t conn_handle, uint8_t opcode, uint8_t dlen, uint8_t data[]) { + if (conn_handle == expected_rsp.conn_handle && expected_rsp.opcode == opcode) { + expected_rsp.buffer[0] = opcode; + memcpy(&expected_rsp.buffer[1], data, dlen); + expected_rsp.length = dlen + 1; + } +} + +void bleio_att_reset(void) { + max_mtu = BT_ATT_DEFAULT_LE_MTU; + timeout = 5000; + long_write_handle = BLE_GATT_HANDLE_INVALID; + long_write_value = NULL; + long_write_value_length = 0; + + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connections[i].conn_handle = BLE_CONN_HANDLE_INVALID; + bleio_connections[i].role = 0x00; + bleio_connections[i].addr.type = 0; + memset(bleio_connections[i].addr.a.val, 0, sizeof_field(bt_addr_t, val)); + bleio_connections[i].mtu = BT_ATT_DEFAULT_LE_MTU; + } +} + +bool att_connect_to_address(bt_addr_le_t *addr) { + //FIX + if (hci_le_create_conn(0x0060, 0x0030, 0x00, addr, 0x00, + 0x0006, 0x000c, 0x0000, 0x00c8, 0x0004, 0x0006) != 0) { + return false; + } + + bool is_connected = false; + + for (uint64_t start = supervisor_ticks_ms64(); supervisor_ticks_ms64() - start < timeout;) { + // RUN_BACKGROUND_TASKS includes hci_poll_for_incoming_pkt(); + RUN_BACKGROUND_TASKS; + + is_connected = att_address_is_connected(addr); + + if (is_connected) { + break; + } + } + + if (!is_connected) { + hci_le_cancel_conn(); + } + + return is_connected; +} + +bool att_disconnect(uint16_t conn_handle) { + if (conn_handle == BLE_CONN_HANDLE_INVALID) { + return false; + } + + hci_disconnect(conn_handle); + + // Confirm we're now disconnected. + return !att_handle_is_connected(conn_handle); +} + +//FIX +// STATIC bool discover_services(uint16_t conn_handle, BLERemoteDevice* device, const char* serviceUuidFilter) { +// uint16_t reqStart_handle = 0x0001; +// uint16_t reqEnd_handle = 0xffff; + +// uint8_t response_buffer[max_mtu]; + +// BLEUuid serviceUuid(serviceUuidFilter); + +// while (reqEnd_handle == 0xffff) { +// int respLength = readByGroupReq(conn_handle, reqStart_handle, reqEnd_handle, BLE_UUID_SERVICE_PRIMARY, response_buffer); + +// if (respLength == 0) { +// return false; +// } + +// if (response_buffer[0] == BT_ATT_OP_READ_GROUP_RSP) { +// uint16_t lengthPerService = response_buffer[1]; +// uint8_t uuidLen = lengthPerService - 4; + +// for (size_t i = 2; i < respLength; i += lengthPerService) { +// struct __attribute__ ((packed)) RawService { +// uint16_t start_handle; +// uint16_t end_handle; +// uint8_t uuid[16]; +// } *rawService = (RawService*)&response_buffer[i]; + +// if (serviceUuidFilter == NULL || +// (uuidLen == serviceUuid.length() && memcmp(rawService->uuid, serviceUuid.data(), uuidLen) == 0)) { + +// BLERemoteService* service = new BLERemoteService(rawService->uuid, uuidLen, +// rawService->start_handle, +// rawService->end_handle); + +// if (service == NULL) { +// return false; +// } + +// device->addService(service); + +// } + +// reqStart_handle = rawService->end_handle + 1; + +// if (reqStart_handle == BLE_GATT_HANDLE_INVALID) { +// reqEnd_handle = BLE_GATT_HANDLE_INVALID; +// } +// } +// } else { +// reqEnd_handle = BLE_GATT_HANDLE_INVALID; +// } +// } + +// return true; +// } + +// STATIC bool discover_characteristics(uint16_t conn_handle, BLERemoteDevice* device) { +// uint16_t reqStart_handle = 0x0001; +// uint16_t reqEnd_handle = 0xffff; + +// uint8_t response_buffer[max_mtu]; + +// int serviceCount = device->serviceCount(); + +// for (size_t i = 0; i < serviceCount; i++) { +// BLERemoteService* service = device->service(i); + +// reqStart_handle = service->start_handle(); +// reqEnd_handle = service->end_handle(); + +// while (1) { +// int respLength = readByTypeReq(conn_handle, reqStart_handle, reqEnd_handle, BLE_UUID_CHARACTERISTIC, response_buffer); + +// if (respLength == 0) { +// return false; +// } + +// if (response_buffer[0] == BT_ATT_OP_READ_TYPE_RSP) { +// uint16_t lengthPerCharacteristic = response_buffer[1]; +// uint8_t uuidLen = lengthPerCharacteristic - 5; + +// for (size_t i = 2; i < respLength; i += lengthPerCharacteristic) { +// struct __attribute__ ((packed)) RawCharacteristic { +// uint16_t start_handle; +// uint8_t properties; +// uint16_t value_handle; +// uint8_t uuid[16]; +// } *rawCharacteristic = (RawCharacteristic*)&response_buffer[i]; + +// BLERemoteCharacteristic* characteristic = new BLERemoteCharacteristic(rawCharacteristic->uuid, uuidLen, +// conn_handle, +// rawCharacteristic->start_handle, +// rawCharacteristic->properties, +// rawCharacteristic->value_handle); + +// if (characteristic == NULL) { +// return false; +// } + +// service->addCharacteristic(characteristic); + +// reqStart_handle = rawCharacteristic->value_handle + 1; +// } +// } else { +// break; +// } +// } +// } + +// return true; +// } + +// STATIC bool discover_descriptors(uint16_t conn_handle, BLERemoteDevice* device) { +// uint16_t reqStart_handle = 0x0001; +// uint16_t reqEnd_handle = 0xffff; + +// uint8_t response_buffer[max_mtu]; + +// int serviceCount = device->serviceCount(); + +// for (size_t i = 0; i < serviceCount; i++) { +// BLERemoteService* service = device->service(i); + +// uint16_t serviceEnd_handle = service->end_handle(); + +// int characteristicCount = service->characteristicCount(); + +// for (int j = 0; j < characteristicCount; j++) { +// BLERemoteCharacteristic* characteristic = service->characteristic(j); +// BLERemoteCharacteristic* nextCharacteristic = (j == (characteristicCount - 1)) ? NULL : service->characteristic(j); + +// reqStart_handle = characteristic->value_handle() + 1; +// reqEnd_handle = nextCharacteristic ? nextCharacteristic->value_handle() : serviceEnd_handle; + +// if (reqStart_handle > reqEnd_handle) { +// continue; +// } + +// while (1) { +// int respLength = findInfoReq(conn_handle, reqStart_handle, reqEnd_handle, response_buffer); + +// if (respLength == 0) { +// return false; +// } + +// if (response_buffer[0] == BT_ATT_OP_FIND_INFO_RSP) { +// uint16_t lengthPerDescriptor = response_buffer[1] * 4; +// uint8_t uuidLen = 2; + +// for (size_t i = 2; i < respLength; i += lengthPerDescriptor) { +// struct __attribute__ ((packed)) RawDescriptor { +// uint16_t handle; +// uint8_t uuid[16]; +// } *rawDescriptor = (RawDescriptor*)&response_buffer[i]; + +// BLERemoteDescriptor* descriptor = new BLERemoteDescriptor(rawDescriptor->uuid, uuidLen, +// conn_handle, +// rawDescriptor->handle); + +// if (descriptor == NULL) { +// return false; +// } + +// characteristic->addDescriptor(descriptor); + +// reqStart_handle = rawDescriptor->handle + 1; +// } +// } else { +// break; +// } +// } +// } +// } + +// return true; +// } + +bool att_discover_attributes(bt_addr_le_t *addr, const char* service_uuid_filter) { + uint16_t conn_handle = att_conn_handle(addr); + if (conn_handle == 0xffff) { + return false; + } + + // send MTU request + if (!att_exchange_mtu(conn_handle)) { + return false; + } + + // find the device entry for the peeer + //FIX BLERemoteDevice* device = NULL; + + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + // if (bleio_connections[i].conn_handle == conn_handle) { + // //FIX if (bleio_connections[i].device == NULL) { + // //FIX + // //bleio_connections[i].device = new BLERemoteDevice(); + // //} + + // //device = bleio_connections[i].device; + + // break; + // } + // } + + // //FIX if (device == NULL) { + // // return false; + // // } + + // if (service_uuid_filter == NULL) { + // // clear existing services + // //FIX device->clear_services(); + // } else { + // //FIX int service_count = device->service_count(); + + // for (size_t i = 0; i < service_count; i++) { + // //FIX BLERemoteService* service = device->service(i); + + // if (strcasecmp(service->uuid(), service_uuid_filter) == 0) { + // // found an existing service with same UUID + // return true; + // } + // } + } + + // discover services + //FIX + // if (!att_discover_services(conn_handle, device, service_uuid_filter)) { + // return false; + // } + + // // discover characteristics + // if (!discover_characteristics(conn_handle, device)) { + // return false; + // } + + // // discover descriptors396 + // if (!discover_descriptors(conn_handle, device)) { + // return false; + // } + + return true; +} + +void att_set_max_mtu(uint16_t max_mtu_in) { + max_mtu = max_mtu_in; +} + +void att_set_timeout(unsigned long timeout_in) { + timeout = timeout_in; +} + +void att_add_connection(uint16_t handle, uint8_t role, bt_addr_le_t *peer_addr, uint16_t interval, uint16_t latency, uint16_t supervision_timeout, uint8_t master_clock_accuracy) { + (void) interval; + (void) latency; + (void) supervision_timeout; + (void) master_clock_accuracy; + + int peer_index = -1; + + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + if (bleio_connections[i].conn_handle == 0xffff) { + peer_index = i; + break; + } + } + + if (peer_index == -1) { + // bail, no space + return; + } + + bleio_connections[peer_index].conn_handle = handle; + bleio_connections[peer_index].role = role; + bleio_connections[peer_index].mtu = BT_ATT_DEFAULT_LE_MTU; + memcpy(&bleio_connections[peer_index].addr, peer_addr, sizeof(bleio_connections[peer_index].addr)); +} + + +void att_remove_connection(uint16_t conn_handle, uint8_t reason) { + (void) reason; + int peer_index = -1; + int peer_count = 0; + + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + if (bleio_connections[i].conn_handle == conn_handle) { + peer_index = i; + } + + if (bleio_connections[i].conn_handle != 0xffff) { + peer_count++; + } + } + + if (peer_index == -1) { + // Peer not found + return; + } + + if (peer_count == 1) { + + // Clear CCCD values on disconnect. + size_t max_attribute_handle = bleio_adapter_max_attribute_handle(&common_hal_bleio_adapter_obj); + for (size_t handle = 1; handle <= max_attribute_handle; handle++) { + mp_obj_t attribute_obj = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, handle); + + uint16_t zero = 0; + mp_buffer_info_t zero_cccd_value = { + .buf = &zero, + .len = sizeof(zero), + }; + + if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_descriptor_type)) { + bleio_descriptor_obj_t *descriptor = MP_OBJ_TO_PTR(attribute_obj); + if (bleio_uuid_get_uuid16_or_unknown(descriptor->uuid) == BLE_UUID_CCCD) { + common_hal_bleio_descriptor_set_value(descriptor, &zero_cccd_value); + } + } + } + + long_write_handle = BLE_GATT_HANDLE_INVALID; + long_write_value_length = 0; + } + + bleio_connections[peer_index].conn_handle = 0xffff; + bleio_connections[peer_index].role = 0x00; + memset(&bleio_connections[peer_index].addr, 0x00, sizeof(bleio_connections[peer_index].addr)); + bleio_connections[peer_index].mtu = BT_ATT_DEFAULT_LE_MTU; +} + +uint16_t att_conn_handle(bt_addr_le_t *addr) { + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + if (bleio_connections[i].addr.type == addr->type && + memcmp(&bleio_connections[i].addr.a.val, addr->a.val, sizeof(addr->a.val)) == 0) { + return bleio_connections[i].conn_handle; + } + } + + return 0xffff; +} + +bool att_is_connected(void) { + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + if (bleio_connections[i].conn_handle != 0xffff) { + return true; + } + } + + return false; +} + +bool att_address_is_connected(bt_addr_le_t *addr) { + return (att_conn_handle(addr) != 0xffff); +} + +bool att_handle_is_connected(uint16_t handle) { + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + if (bleio_connections[i].conn_handle == handle) { + return true; + } + } + + return false; +} + +uint16_t att_mtu(uint16_t handle) { + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + if (bleio_connections[i].conn_handle == handle) { + return bleio_connections[i].mtu; + } + } + + return BT_ATT_DEFAULT_LE_MTU; +} + +bool att_disconnect_all(void) { + int num_disconnects = 0; + + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + if (bleio_connections[i].conn_handle == 0xffff) { + continue; + } + + if (att_disconnect(bleio_connections[i].conn_handle) != 0) { + continue; + } + + num_disconnects++; + + bleio_connections[i].conn_handle = 0xffff; + bleio_connections[i].role = 0x00; + bleio_connections[i].addr.type = 0; + memset(bleio_connections[i].addr.a.val, 0, sizeof(bleio_connections[i].addr.a.val)); + bleio_connections[i].mtu = BT_ATT_DEFAULT_LE_MTU; + } + + return (num_disconnects > 0); +} + +bool att_notify(uint16_t handle, const uint8_t* value, int length) { + int num_notifications = 0; + + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + if (bleio_connections[i].conn_handle == 0xffff) { + continue; + } + + typedef struct __packed { + struct bt_att_hdr hdr; + struct bt_att_notify ntf; + } notify_t; + + size_t allowed_length = MIN((uint16_t)(bleio_connections[i].mtu - sizeof(notify_t)), (uint16_t)length); + + uint8_t notify_bytes[sizeof(notify_t) + allowed_length]; + notify_t *notify = (notify_t *) notify_bytes; + notify->hdr.code = BT_ATT_OP_NOTIFY;; + notify->ntf.handle = handle; + memcpy(notify->ntf.value, value, allowed_length); + hci_send_acl_pkt(bleio_connections[i].conn_handle, BT_L2CAP_CID_ATT, + sizeof(notify_bytes), notify_bytes); + + num_notifications++; + } + + return (num_notifications > 0); +} + +bool att_indicate(uint16_t handle, const uint8_t* value, int length) { + int num_indications = 0; + + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + if (bleio_connections[i].conn_handle == 0xffff) { + continue; + } + + typedef struct __packed { + struct bt_att_hdr hdr; + struct bt_att_indicate ind; + } indicate_t; + + size_t allowed_length = MIN((uint16_t)(bleio_connections[i].mtu - sizeof(indicate_t)), (uint16_t)length); + + uint8_t indicate_bytes[sizeof(indicate_t) + allowed_length]; + indicate_t *indicate = (indicate_t *) indicate_bytes; + indicate->hdr.code = BT_ATT_OP_INDICATE;; + indicate->ind.handle = handle; + memcpy(indicate->ind.value, value, allowed_length); + + confirm = false; + + hci_send_acl_pkt(bleio_connections[i].conn_handle, BT_L2CAP_CID_ATT, + sizeof(indicate_bytes), indicate_bytes); + + while (!confirm) { + // RUN_BACKGROUND_TASKS includes hci_poll_for_incoming_pkt(); + RUN_BACKGROUND_TASKS; + + if (!att_address_is_connected(&bleio_connections[i].addr)) { + break; + } + } + + num_indications++; + } + + return (num_indications > 0); +} + +STATIC void process_error(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) { + struct bt_att_error_rsp *rsp = (struct bt_att_error_rsp *) data; + + if (dlen != sizeof(struct bt_att_error_rsp)) { + // Incorrect size; ignore. + return; + } + + // expected_rsp.opcode is an RSP opcode. Does it match the REQ opcode in this response? + if (expected_rsp.conn_handle == conn_handle && (expected_rsp.opcode - 1) == rsp->request) { + expected_rsp.buffer[0] = BT_ATT_OP_ERROR_RSP; + memcpy(&expected_rsp.buffer[1], data, dlen); + expected_rsp.length = dlen + 1; + } +} + +STATIC void process_mtu_req(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) { + struct bt_att_exchange_mtu_req *req = (struct bt_att_exchange_mtu_req *) data; + + if (dlen != sizeof(struct bt_att_exchange_mtu_req)) { + send_error(conn_handle, BT_ATT_OP_MTU_REQ, BLE_GATT_HANDLE_INVALID, BT_ATT_ERR_INVALID_PDU); + return; + } + + uint16_t mtu = req->mtu; + + if (mtu > max_mtu) { + mtu = max_mtu; + } + + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + if (bleio_connections[i].conn_handle == conn_handle) { + bleio_connections[i].mtu = mtu; + break; + } + } + + struct __packed { + struct bt_att_hdr h; + struct bt_att_exchange_mtu_rsp r; + } rsp = { { + .code = BT_ATT_OP_MTU_RSP, + }, { + .mtu = mtu, + } + }; + + hci_send_acl_pkt(conn_handle, BT_L2CAP_CID_ATT, sizeof(rsp), (uint8_t *) &rsp); +} + +STATIC void process_mtu_rsp(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) { + struct bt_att_exchange_mtu_rsp *rsp = (struct bt_att_exchange_mtu_rsp *) data; + + if (dlen != sizeof(struct bt_att_exchange_mtu_rsp)) { + return; + } + + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + if (bleio_connections[i].conn_handle == conn_handle) { + bleio_connections[i].mtu = rsp->mtu; + break; + } + } + + check_and_save_expected_rsp(conn_handle, BT_ATT_OP_MTU_RSP, dlen, data); +} + +STATIC void process_find_info_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen, uint8_t data[]) { + struct bt_att_find_info_req *req = (struct bt_att_find_info_req *) data; + + if (dlen != sizeof(struct bt_att_find_info_req)) { + send_error(conn_handle, BT_ATT_OP_FIND_INFO_REQ, req->start_handle, BT_ATT_ERR_INVALID_PDU); + return; + } + + typedef struct __packed { + struct bt_att_hdr h; + struct bt_att_find_info_rsp r; + } rsp_t; + + uint8_t rsp_bytes[mtu]; + rsp_t *rsp = (rsp_t *) rsp_bytes; + rsp->h.code = BT_ATT_OP_FIND_INFO_RSP; + + // Keeps track of total length of the response. + size_t rsp_length = sizeof(rsp_t); + + bool no_data = true; + + // All the data chunks must have uuid's that are the same size. + // Keep track of the first one to make sure. + size_t sizeof_first_uuid = 0; + + const uint16_t max_attribute_handle = bleio_adapter_max_attribute_handle(&common_hal_bleio_adapter_obj); + for (uint16_t handle = req->start_handle; + handle <= max_attribute_handle && handle <= req->end_handle; + handle++) { + + mp_obj_t *attribute_obj = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, handle); + + // Fetch the uuid for the given attribute, which might be a characteristic or a descriptor. + bleio_uuid_obj_t *uuid; + + if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_characteristic_type)) { + bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(attribute_obj); + if (characteristic->handle != handle) { + // If the handles don't match, this is the characteristic definition attribute. + // Skip it. We want the characteristic value attribute. + continue; + } + uuid = characteristic->uuid; + + } else { + uuid = bleio_attribute_get_uuid(attribute_obj); + } + + const uint32_t sizeof_uuid = common_hal_bleio_uuid_get_size(uuid) / 8; + if (sizeof_first_uuid == 0) { + sizeof_first_uuid = sizeof_uuid; + // All the uuids in the response will be the same size. + rsp->r.format = sizeof_uuid == 2 ? BT_ATT_INFO_16 : BT_ATT_INFO_128; + } + + if (sizeof_uuid != sizeof_first_uuid) { + // Previous UUID was a different size. We can't mix sizes. + // Stop and send what we have so far. + break; + } + + if (rsp_length + sizeof_uuid > mtu) { + // No remaining room in response for this uuid. + break; + } + + if (sizeof_uuid == 2) { + struct bt_att_info_16 *info_16 = (struct bt_att_info_16 *) &rsp_bytes[rsp_length]; + info_16->handle = handle; + info_16->uuid = common_hal_bleio_uuid_get_uuid16(uuid); + + rsp_length += sizeof(struct bt_att_info_16); + } else { + struct bt_att_info_128 *info_128 = (struct bt_att_info_128 *) &rsp_bytes[rsp_length]; + info_128->handle = handle; + common_hal_bleio_uuid_get_uuid128(uuid, info_128->uuid); + + rsp_length += sizeof(struct bt_att_info_128); + } + + no_data =false; + } // end for + + + if (no_data) { + send_error(conn_handle, BT_ATT_OP_FIND_INFO_REQ, req->start_handle, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND); + } else { + hci_send_acl_pkt(conn_handle, BT_L2CAP_CID_ATT, rsp_length, rsp_bytes); + } +} + +int att_find_info_req(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, uint8_t response_buffer[]) { + struct __packed req { + struct bt_att_hdr h; + struct bt_att_find_info_req r; + } req = { { + .code = BT_ATT_OP_FIND_INFO_REQ, + }, { + .start_handle = start_handle, + .end_handle = end_handle, + } + }; + + return send_req_wait_for_rsp(conn_handle, sizeof(req), (uint8_t *) &req, response_buffer); +} + +STATIC void process_find_info_rsp(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) { + if (dlen < 2) { + return; // invalid, drop + } + + check_and_save_expected_rsp(conn_handle, BT_ATT_OP_FIND_INFO_RSP, dlen, data); +} + +STATIC void process_find_type_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen, uint8_t data[]) { + struct bt_att_find_type_req *req = (struct bt_att_find_type_req *) data; + + if (dlen < sizeof(struct bt_att_find_type_req)) { + send_error(conn_handle, BT_ATT_OP_FIND_TYPE_RSP, req->start_handle, BT_ATT_ERR_INVALID_PDU); + return; + } + + uint8_t response[mtu]; + uint16_t response_length; + + response[0] = BT_ATT_OP_FIND_TYPE_RSP; + response_length = 1; + + //FIX + // if (find_type_req->type == BLE_UUID_SERVICE_PRIMARY) { + // for (uint16_t i = (find_type_req->start_handle - 1); i < GATT.attributeCount() && i <= (find_type_req->end_handle - 1); i++) { + // BLELocalAttribute* attribute = GATT.attribute(i); + + // if ((attribute->type() == find_type_req->type) && (attribute->uuidLength() == value_length) && memcmp(attribute->uuidData(), value, value_length) == 0) { + // BLELocalService* service = (BLELocalService*)attribute; + + // // add the start handle + // uint16_t start_handle = service->start_handle(); + // memcpy(&response[response_length], &start_handle, sizeof(start_handle)); + // response_length += sizeof(start_handle); + + // // add the end handle + // uint16_t end_handle = service->end_handle(); + // memcpy(&response[response_length], &end_handle, sizeof(end_handle)); + // response_length += sizeof(end_handle); + // } + + // if ((response_length + 4) > mtu) { + // break; + // } + // } + // } + + if (response_length == 1) { + send_error(conn_handle, BT_ATT_OP_FIND_TYPE_RSP, req->start_handle, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND); + } else { + hci_send_acl_pkt(conn_handle, BT_L2CAP_CID_ATT, response_length, response); + } +} + +void process_read_group_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen, uint8_t data[]) { + struct bt_att_read_group_req *req = (struct bt_att_read_group_req *) data; + uint16_t type_uuid = req->uuid[0] | (req->uuid[1] << 8); + + // We only support returning services for BT_ATT_OP_READ_GROUP_REQ, which is typically used + // for service discovery. + if (dlen != sizeof(struct bt_att_read_group_req) + sizeof(type_uuid) || + (type_uuid != BLE_UUID_SERVICE_PRIMARY && + type_uuid != BLE_UUID_SERVICE_SECONDARY)) { + send_error(conn_handle, BT_ATT_OP_READ_GROUP_REQ, req->start_handle, BT_ATT_ERR_UNSUPPORTED_GROUP_TYPE); + return; + } + + typedef struct __packed { + struct bt_att_hdr h; + struct bt_att_read_group_rsp r; + } rsp_t; + + uint8_t rsp_bytes[mtu]; + rsp_t *rsp = (rsp_t *) rsp_bytes; + rsp->h.code = BT_ATT_OP_READ_GROUP_RSP; + rsp->r.len = 0; + + // Keeps track of total length of the response. + size_t rsp_length = sizeof(rsp_t); + + bool no_data = true; + + // All the data chunks must have uuid's that are the same size. + // Keep track of the first one to make sure. + size_t sizeof_first_service_uuid = 0; + + // Size of a single bt_att_group_data chunk. Start with the intial size, and + // add the uuid size in the loop below. + size_t data_length = sizeof(struct bt_att_group_data); + + const uint16_t max_attribute_handle = bleio_adapter_max_attribute_handle(&common_hal_bleio_adapter_obj); + for (uint16_t handle = req->start_handle; + handle <= max_attribute_handle && handle <= req->end_handle; + handle++) { + + if (rsp_length + data_length > mtu) { + // The next possible bt_att_group_data chunk won't fit. The response is full. + break; + } + + mp_obj_t *attribute_obj = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, handle); + if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_service_type)) { + bleio_service_obj_t *service = MP_OBJ_TO_PTR(attribute_obj); + + // Is this a 16-bit or a 128-bit uuid? It must match in size with any previous attribute + // in this transmission. + const uint32_t sizeof_service_uuid = common_hal_bleio_uuid_get_size(service->uuid) / 8; + if (sizeof_first_service_uuid == 0) { + sizeof_first_service_uuid = sizeof_service_uuid; + data_length += sizeof_service_uuid; + } else if (sizeof_first_service_uuid != sizeof_service_uuid) { + // Mismatched sizes, which can't be in the same batch. + // Transmit just what we have so far in this batch. + break; + } + + // Pass the length of ONE bt_att_group_data chunk. + // There may be multiple chunks in this transmission. + rsp->r.len = data_length; + + struct bt_att_group_data *group_data = (struct bt_att_group_data *) &rsp_bytes[rsp_length]; + + group_data->start_handle = service->start_handle; + group_data->end_handle = service->end_handle; + common_hal_bleio_uuid_pack_into(service->uuid, group_data->value); + + rsp_length += data_length; + no_data = false; + } + } + + if (no_data) { + send_error(conn_handle, BT_ATT_OP_READ_GROUP_REQ, req->start_handle, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND); + } else { + hci_send_acl_pkt(conn_handle, BT_L2CAP_CID_ATT, rsp_length, rsp_bytes); + } +} + +int att_read_group_req(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, uint16_t uuid, uint8_t response_buffer[]) { + struct __packed { + struct bt_att_hdr h; + struct bt_att_read_group_req r; + } req = { { + .code = BT_ATT_OP_READ_GROUP_REQ, + }, { + .start_handle = start_handle, + .end_handle = end_handle, + } + }; + req.r.uuid[0] = uuid & 0xff; + req.r.uuid[1] = uuid >> 8; + + + return send_req_wait_for_rsp(conn_handle, sizeof(req), (uint8_t *) &req, response_buffer); +} + +STATIC void process_read_group_rsp(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) { + if (dlen < 2) { + return; // invalid, drop + } + + check_and_save_expected_rsp(conn_handle, BT_ATT_OP_READ_GROUP_RSP, dlen, data); +} + +STATIC void process_read_or_read_blob_req(uint16_t conn_handle, uint16_t mtu, uint8_t opcode, uint8_t dlen, uint8_t data[]) { + uint16_t handle; + uint16_t offset = 0; + uint8_t response_opcode; + + if (opcode == BT_ATT_OP_READ_REQ) { + if (dlen != sizeof(struct bt_att_read_req)) { + send_error(conn_handle, BT_ATT_OP_READ_REQ, BLE_GATT_HANDLE_INVALID, BT_ATT_ERR_INVALID_PDU); + return; + } + + struct bt_att_read_req *req = (struct bt_att_read_req *) data; + handle = req->handle; + response_opcode = BT_ATT_OP_READ_RSP; + + } else if (opcode == BT_ATT_OP_READ_BLOB_REQ) { + if (dlen != sizeof(struct bt_att_read_blob_req)) { + send_error(conn_handle, BT_ATT_OP_READ_BLOB_REQ, BLE_GATT_HANDLE_INVALID, BT_ATT_ERR_INVALID_PDU); + return; + } + + struct bt_att_read_blob_req *req = (struct bt_att_read_blob_req *) data; + handle = req->handle; + offset = req->offset; + response_opcode = BT_ATT_OP_READ_BLOB_RSP; + } else { + return; + } + + + if (handle > bleio_adapter_max_attribute_handle(&common_hal_bleio_adapter_obj)) { + send_error(conn_handle, opcode, handle, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND); + return; + } + + typedef struct __packed { + struct bt_att_hdr h; + struct bt_att_read_rsp r; // Same as bt_att_read_blob_rsp. + } rsp_t; + + uint8_t rsp_bytes[mtu]; + rsp_t *rsp = (rsp_t *) rsp_bytes; + rsp->h.code = response_opcode; + + // Keeps track of total length of the response. + size_t rsp_length = sizeof(rsp_t); + + mp_obj_t *attribute_obj = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, handle); + if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_service_type)) { + if (offset) { + send_error(conn_handle, BT_ATT_ERR_ATTRIBUTE_NOT_LONG, handle, BT_ATT_ERR_INVALID_PDU); + return; + } + + bleio_service_obj_t *service = MP_OBJ_TO_PTR(attribute_obj); + const uint32_t sizeof_service_uuid = common_hal_bleio_uuid_get_size(service->uuid) / 8; + + common_hal_bleio_uuid_pack_into(service->uuid, rsp->r.value); + rsp_length += sizeof_service_uuid; + + } else if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_characteristic_type)) { + bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(attribute_obj); + if (characteristic->decl_handle == handle) { + // Read characteristic declaration. Return properties, value handle, and uuid. + if (offset) { + send_error(conn_handle, opcode, handle, BT_ATT_ERR_ATTRIBUTE_NOT_LONG); + return; + } + + characteristic_declaration_t *char_decl = (characteristic_declaration_t *) rsp->r.value; + + // Convert from the bleio properties bit values to the BLE spec properties bit values. + // They are not the same :(. + char_decl->properties = bleio_properties_to_ble_spec_properties(characteristic->props); + char_decl->value_handle = characteristic->handle; + + const uint32_t sizeof_char_uuid = common_hal_bleio_uuid_get_size(characteristic->uuid) / 8; + common_hal_bleio_uuid_pack_into(characteristic->uuid, char_decl->uuid); + rsp_length += sizeof_char_uuid; + + } else { + // Read characteristic value. + + if ((characteristic->props & CHAR_PROP_READ) == 0) { + send_error(conn_handle, opcode, handle, BT_ATT_ERR_READ_NOT_PERMITTED); + return; + } + + mp_buffer_info_t bufinfo; + mp_get_buffer(characteristic->value, &bufinfo, MP_BUFFER_READ); + + if (offset >= bufinfo.len) { + send_error(conn_handle, opcode, handle, BT_ATT_ERR_INVALID_OFFSET); + return; + } + + size_t value_length = MIN(mtu - rsp_length, bufinfo.len - offset); + memcpy(rsp->r.value, bufinfo.buf + offset, value_length); + rsp_length += value_length; + } + } else if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_descriptor_type)) { + bleio_descriptor_obj_t *descriptor = MP_OBJ_TO_PTR(attribute_obj); + + mp_buffer_info_t bufinfo; + mp_get_buffer(descriptor->value, &bufinfo, MP_BUFFER_READ); + + if (offset >= bufinfo.len) { + send_error(conn_handle, opcode, handle, BT_ATT_ERR_INVALID_OFFSET); + return; + } + + size_t value_length = MIN(mtu - rsp_length, bufinfo.len - offset); + memcpy(rsp->r.value, bufinfo.buf + offset, value_length); + rsp_length += value_length; + } + + hci_send_acl_pkt(conn_handle, BT_L2CAP_CID_ATT, rsp_length, rsp_bytes); +} + +STATIC void process_read_rsp(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) { + check_and_save_expected_rsp(conn_handle, BT_ATT_OP_READ_RSP, dlen, data); +} + +STATIC void process_read_type_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen, uint8_t data[]) { + struct bt_att_read_type_req *req = (struct bt_att_read_type_req *) data; + uint16_t type_uuid = req->uuid[0] | (req->uuid[1] << 8); + + if (dlen != sizeof(struct bt_att_read_type_req) + sizeof(type_uuid)) { + send_error(conn_handle, BT_ATT_OP_READ_TYPE_REQ, req->start_handle, BT_ATT_ERR_INVALID_PDU); + return; + } + + typedef struct __packed { + struct bt_att_hdr h; + struct bt_att_read_type_rsp r; + } rsp_t; + + uint8_t rsp_bytes[mtu]; + rsp_t *rsp = (rsp_t *) rsp_bytes; + rsp->h.code = BT_ATT_OP_READ_TYPE_RSP; + rsp->r.len = 0; + + // Keeps track of total length of the response. + size_t rsp_length = sizeof(rsp_t); + + bool no_data = true; + + // All the data chunks must have uuid's that are the same size. + // Keep track of the first one to make sure. + size_t sizeof_first_uuid = 0; + + // Size of a single bt_att_data chunk. Start with the initial size, and + // add the uuid size and other data sizes in the loop below. + size_t data_length = sizeof(struct bt_att_data); + + const uint16_t max_attribute_handle = bleio_adapter_max_attribute_handle(&common_hal_bleio_adapter_obj); + for (uint16_t handle = req->start_handle; + handle <= max_attribute_handle && handle <= req->end_handle; + handle++) { + + if (rsp_length + data_length > mtu) { + // The next possible bt_att_data chunk won't fit. The response is full. + break; + } + + mp_obj_t *attribute_obj = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, handle); + + if (type_uuid == BLE_UUID_CHARACTERISTIC && + MP_OBJ_IS_TYPE(attribute_obj, &bleio_characteristic_type)) { + // Request is for characteristic declarations. + bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(attribute_obj); + + if (characteristic->handle == handle) { + // If the characteristic's handle is this attribute's handle, skip it: + // it's the attribute for characteristic value. We want to return the declaration + // handle attribute instead. (It will probably get skipped below, by the + // handle++). + continue; + } + + // Is this a 16-bit or a 128-bit uuid? It must match in size with any previous attribute + // in this transmission. + const uint32_t sizeof_uuid = common_hal_bleio_uuid_get_size(characteristic->uuid) / 8; + if (sizeof_first_uuid == 0) { + sizeof_first_uuid = sizeof_uuid; + data_length += sizeof_uuid; + data_length += sizeof(characteristic_declaration_t); + } else if (sizeof_first_uuid != sizeof_uuid) { + // Mismatched sizes, which can't be in the same batch. + // Transmit just what we have so far in this batch. + break; + } + + // Pass the length of ONE bt_att_data chunk. + // There may be multiple chunks in this transmission. + rsp->r.len = data_length; + + struct bt_att_data *att_data = (struct bt_att_data *) &rsp_bytes[rsp_length]; + + att_data->handle = characteristic->decl_handle; + + characteristic_declaration_t *char_decl = (characteristic_declaration_t *) att_data->value; + + // Convert from the bleio properties bit values to the BLE spec properties bit values. + // They are not the same :(. + char_decl->properties = bleio_properties_to_ble_spec_properties(characteristic->props); + char_decl->value_handle = characteristic->handle; + common_hal_bleio_uuid_pack_into(characteristic->uuid, char_decl->uuid); + + // We know the next handle will be the characteristic value handle, so skip it. + handle++; + + rsp_length += data_length; + no_data = false; + + } else if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_descriptor_type)) { + // See if request is for a descriptor value with a 16-bit UUID, such as the CCCD. + bleio_descriptor_obj_t *descriptor = MP_OBJ_TO_PTR(attribute_obj); + if (bleio_uuid_get_uuid16_or_unknown(descriptor->uuid) == type_uuid) { + struct bt_att_data *att_data = (struct bt_att_data *) &rsp_bytes[rsp_length]; + + att_data->handle = handle; + + mp_buffer_info_t bufinfo; + if (!mp_get_buffer(descriptor->value, &bufinfo, MP_BUFFER_READ)) { + break; + } + uint16_t value_size = MIN(mtu - rsp_length, bufinfo.len); + memcpy(att_data->value, bufinfo.buf, value_size); + rsp_length += value_size; + + // Only return one descriptor value. + no_data = false; + break; + } + + } else if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_characteristic_type)) { + // See if request is for a characteristic value with a 16-bit UUID. + bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(attribute_obj); + if (bleio_uuid_get_uuid16_or_unknown(characteristic->uuid) == type_uuid) { + + struct bt_att_data *att_data = (struct bt_att_data *) &rsp_bytes[rsp_length]; + + att_data->handle = handle; + + mp_buffer_info_t bufinfo; + if (!mp_get_buffer(characteristic->value, &bufinfo, MP_BUFFER_READ)) { + // This shouldn't happen. There should be a buf in characteristic->value. + break; + } + uint16_t value_size = MIN(mtu - rsp_length, bufinfo.len); + memcpy(att_data->value, bufinfo.buf, value_size); + rsp_length += value_size; + + // Only return one characteristic value. + no_data = false; + break; + } + } + } // end for loop + + if (no_data) { + send_error(conn_handle, BT_ATT_OP_READ_TYPE_REQ, + req->start_handle, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND); + } else { + hci_send_acl_pkt(conn_handle, BT_L2CAP_CID_ATT, rsp_length, rsp_bytes); + } +} + +int att_read_type_req(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, uint16_t type, uint8_t response_buffer[]) { + struct __packed { + struct bt_att_hdr h; + struct bt_att_read_type_req r; + } req = { { + .code = BT_ATT_OP_READ_TYPE_REQ, + }, { + .start_handle = start_handle, + .end_handle = end_handle, + } + }; + req.r.uuid[0] = type & 0xff; + req.r.uuid[1] = type >> 8; + + return send_req_wait_for_rsp(conn_handle, sizeof(req), (uint8_t *) &req, response_buffer); +} + +STATIC void process_read_type_rsp(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) { + if (dlen < 1) { + return; // invalid, drop + } + + check_and_save_expected_rsp(conn_handle, BT_ATT_OP_READ_TYPE_RSP, dlen, data); +} + +// Handles BT_ATT_OP_WRITE_REQ or BT_ATT_OP_WRITE_ +STATIC void process_write_req_or_cmd(uint16_t conn_handle, uint16_t mtu, uint8_t op, uint8_t dlen, uint8_t data[]) { + // struct bt_att_write_cmd is identical, so don't bother to split code paths based on opcode. + struct bt_att_write_req *req = (struct bt_att_write_req *) data; + + bool with_response = (op == BT_ATT_OP_WRITE_REQ); + + if (dlen < sizeof(struct bt_att_write_req)) { + if (with_response) { + send_error(conn_handle, BT_ATT_OP_WRITE_REQ, BLE_GATT_HANDLE_INVALID, BT_ATT_ERR_INVALID_PDU); + } + return; + } + + if (req->handle > bleio_adapter_max_attribute_handle(&common_hal_bleio_adapter_obj)) { + if (with_response) { + send_error(conn_handle, BT_ATT_OP_WRITE_REQ, req->handle, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND); + } + return; + } + + size_t value_length = dlen - sizeof(struct bt_att_write_req); + + mp_buffer_info_t bufinfo; + bufinfo.buf = req->value; + bufinfo.len = value_length; + + mp_obj_t attribute_obj = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, req->handle); + + if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_characteristic_type)) { + bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(attribute_obj); + + // Don't write the characteristic declaration. + // Also, this must be a writable characteristic. + if (req->handle != characteristic->handle || + (with_response + ? (characteristic->props & CHAR_PROP_WRITE) == 0 + : (characteristic->props & CHAR_PROP_WRITE_NO_RESPONSE) == 0)) { + if (with_response) { + send_error(conn_handle, BT_ATT_OP_WRITE_REQ, req->handle, BT_ATT_ERR_WRITE_NOT_PERMITTED); + } + return; + } + + // Just change the local value. Don't fire off notifications, etc. + bleio_characteristic_set_local_value(characteristic, &bufinfo); + + } else if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_descriptor_type)) { + bleio_descriptor_obj_t *descriptor = MP_OBJ_TO_PTR(attribute_obj); + // Only CCCD's are writable. + if (bleio_uuid_get_uuid16_or_unknown(descriptor->uuid) != BLE_UUID_CCCD) { + if (with_response) { + send_error(conn_handle, BT_ATT_OP_WRITE_REQ, req->handle, BT_ATT_ERR_WRITE_NOT_PERMITTED); + } + return; + } + + common_hal_bleio_descriptor_set_value(descriptor, &bufinfo); + } + + if (with_response) { + // There's no data in the response. We just indicate the write happened. + struct bt_att_hdr rsp = { + .code = BT_ATT_OP_WRITE_RSP, + }; + + hci_send_acl_pkt(conn_handle, BT_L2CAP_CID_ATT, sizeof(rsp), (uint8_t *) &rsp); + } +} + +STATIC void process_write_rsp(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) { + if (dlen != 0) { + return; // drop + } + + check_and_save_expected_rsp(conn_handle, BT_ATT_OP_WRITE_RSP, dlen, data); +} + +STATIC void process_prepare_write_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen, uint8_t data[]) { + struct bt_att_prepare_write_req *req = (struct bt_att_prepare_write_req *) data; + + if (dlen < sizeof(struct bt_att_prepare_write_req)) { + send_error(conn_handle, BT_ATT_OP_PREPARE_WRITE_REQ, BLE_GATT_HANDLE_INVALID, BT_ATT_ERR_INVALID_PDU); + return; + } + + uint16_t handle = req->handle; + uint16_t offset = req->offset; + (void) offset; + + if (handle > bleio_adapter_max_attribute_handle(&common_hal_bleio_adapter_obj)) { + send_error(conn_handle, BT_ATT_OP_PREPARE_WRITE_REQ, handle, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND); + return; + } + + mp_obj_t *attribute = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, handle); + + if (!MP_OBJ_IS_TYPE(attribute, &bleio_characteristic_type)) { + send_error(conn_handle, BT_ATT_OP_PREPARE_WRITE_REQ, handle, BT_ATT_ERR_ATTRIBUTE_NOT_LONG); + return; + } + + bleio_characteristic_obj_t* characteristic = MP_OBJ_TO_PTR(attribute); + + if (handle != characteristic->handle) { + send_error(conn_handle, BT_ATT_OP_PREPARE_WRITE_REQ, handle, BT_ATT_ERR_ATTRIBUTE_NOT_LONG); + return; + } + + if ((characteristic->props & CHAR_PROP_WRITE) == 0) { + send_error(conn_handle, BT_ATT_OP_PREPARE_WRITE_REQ, handle, BT_ATT_ERR_WRITE_NOT_PERMITTED); + return; + } + + //FIX if (long_write_handle == BLE_GATT_HANDLE_INVALID) + // int valueSize = characteristic->valueSize(); + + // long_write_value = (uint8_t*)realloc(long_write_value, valueSize); + // long_write_value_length = 0; + // long_write_handle = handle; + + // memset(long_write_value, 0x00, valueSize); + // } else if (long_write_handle != handle) { + // send_error(conn_handle, BT_ATT_OP_PREPARE_WRITE_REQ, handle, BT_ATT_ERR_UNLIKELY); + // return; + // } + + // uint8_t value_length = dlen - sizeof(struct bt_att_prepare_write_req); + // uint8_t* value = &data[sizeof(struct bt_att_prepare_write_req)]; + + // if ((offset != long_write_value_length) || ((offset + value_length) > (uint16_t)characteristic->valueSize())) { + // send_error(conn_handle, BT_ATT_OP_PREPARE_WRITE_REQ, handle, BT_ATT_ERR_INVALID_OFFSET); + // return; + // } + + // memcpy(long_write_value + offset, value, value_length); + // long_write_value_length += value_length; + + // uint8_t response[mtu]; + // uint16_t response_length; + + // response[0] = BT_ATT_OP_PREP_WRITE_RSP; + // memcpy(&response[1], data, dlen); + // response_length = dlen + 1; + + // hci_send_acl_pkt(conn_handle, BT_L2CAP_CID_ATT, response_length, response); +} + +STATIC void process_exec_write_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen, uint8_t data[]) { + struct bt_att_exec_write_req *req = (struct bt_att_exec_write_req *) data; + + if (dlen != sizeof(struct bt_att_exec_write_req)) { + send_error(conn_handle, BT_ATT_OP_EXEC_WRITE_REQ, BLE_GATT_HANDLE_INVALID, BT_ATT_ERR_INVALID_PDU); + return; + } + + if (long_write_handle && (req->flags & 0x01)) { + //FIX BLELocalCharacteristic* characteristic = (BLELocalCharacteristic*)GATT.attribute(long_write_handle - 1); + + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + if (bleio_connections[i].conn_handle == conn_handle) { + //FIX characteristic->writeValue(BLEDevice(bleio_connections[i].address_type, bleio_connections[i].address), long_write_value, long_write_value_length); + break; + } + } + } + + long_write_handle = BLE_GATT_HANDLE_INVALID; + long_write_value_length = 0; + + uint8_t response[mtu]; + uint16_t response_length; + + response[0] = BT_ATT_OP_EXEC_WRITE_RSP; + response_length = 1; + + hci_send_acl_pkt(conn_handle, BT_L2CAP_CID_ATT, response_length, response); +} + +STATIC void process_notify_or_indicate(uint16_t conn_handle, uint8_t opcode, uint8_t dlen, uint8_t data[]) { + if (dlen < 2) { + return; // drop + } + + // struct bt_att_notify and bt_att_indicate are identical. + //FIXunused struct bt_att_notify *req = (struct bt_att_notify *) data; + + //FIXunused uint8_t handle = req->handle; + + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + if (bleio_connections[i].conn_handle != conn_handle) { + continue; + } + + //FIX BLERemoteDevice* device = bleio_connections[i].device; + + // if (!device) { + // break; + // } + + // int serviceCount = device->serviceCount(); + + // for (size_t i = 0; i < serviceCount; i++) { + // BLERemoteService* s = device->service(i); + + // if (s->start_handle() < handle && s->end_handle() >= handle) { + // int characteristicCount = s->characteristicCount(); + + // for (int j = 0; j < characteristicCount; j++) { + // BLERemoteCharacteristic* c = s->characteristic(j); + + // if (c->value_handle() == handle) { + // //FIX c->writeValue(BLEDevice(bleio_connections[i].address_type, bleio_connections[i].address), &data[2], dlen - 2); + // } + // } + + // break; + // } + // } + } + + if (opcode == BT_ATT_OP_INDICATE) { + // send CONFIRM for INDICATE + + uint8_t op_confirm = BT_ATT_OP_CONFIRM; + + hci_send_acl_pkt(conn_handle, BT_L2CAP_CID_ATT, sizeof(op_confirm), &op_confirm); + } +} + +STATIC void process_confirm(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) { + (void) conn_handle; + (void) dlen; + (void) data; + + confirm = true; +} + +bool att_exchange_mtu(uint16_t conn_handle) { + uint8_t response_buffer[max_mtu]; + struct bt_att_exchange_mtu_req req = { + .mtu = max_mtu, + }; + return send_req_wait_for_rsp(conn_handle, sizeof(req), (uint8_t *) &req, response_buffer); +} + +int att_read_req(uint16_t conn_handle, uint16_t handle, uint8_t response_buffer[]) { + struct __packed { + struct bt_att_hdr h; + struct bt_att_read_req r; + } req = { { + .code = BT_ATT_OP_READ_REQ, + }, { + .handle = handle, + } + }; + + return send_req_wait_for_rsp(conn_handle, sizeof(req), (uint8_t *) &req, response_buffer); +} + +int att_write_req(uint16_t conn_handle, uint16_t handle, const uint8_t* data, uint8_t data_len, uint8_t response_buffer[]) { + typedef struct __packed { + struct bt_att_hdr h; + struct bt_att_write_req r; + } req_t; + + uint8_t req_bytes[sizeof(req_t) + data_len]; + req_t *req = (req_t *) req_bytes; + req->h.code = BT_ATT_OP_WRITE_REQ; + req->r.handle = handle; + memcpy(req->r.value, data, data_len); + + return send_req_wait_for_rsp(conn_handle, sizeof(req_bytes), req_bytes, response_buffer); +} + +void att_write_cmd(uint16_t conn_handle, uint16_t handle, const uint8_t* data, uint8_t data_len) { + typedef struct __packed { + struct bt_att_hdr h; + struct bt_att_write_cmd r; + } cmd_t; + + uint8_t cmd_bytes[sizeof(cmd_t) + data_len]; + cmd_t *cmd = (cmd_t *) cmd_bytes; + cmd->h.code = BT_ATT_OP_WRITE_CMD; + cmd->r.handle = handle; + memcpy(cmd->r.value, data, data_len); + + send_req(conn_handle, sizeof(cmd_bytes), cmd_bytes); +} + +void att_process_data(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) { + // Opcode is a single byte at the front of the data. + uint8_t opcode = data[0]; + + // Skip over opcode. + dlen--; + data++; + + uint16_t mtu = att_mtu(conn_handle); + + switch (opcode) { + case BT_ATT_OP_ERROR_RSP: + process_error(conn_handle, dlen, data); + break; + + case BT_ATT_OP_MTU_REQ: + process_mtu_req(conn_handle, dlen, data); + break; + + case BT_ATT_OP_MTU_RSP: + process_mtu_rsp(conn_handle, dlen, data); + break; + + case BT_ATT_OP_FIND_INFO_REQ: + process_find_info_req(conn_handle, mtu, dlen, data); + break; + + case BT_ATT_OP_FIND_INFO_RSP: + process_find_info_rsp(conn_handle, dlen, data); + break; + + case BT_ATT_OP_FIND_TYPE_REQ: + process_find_type_req(conn_handle, mtu, dlen, data); + break; + + case BT_ATT_OP_READ_TYPE_REQ: + process_read_type_req(conn_handle, mtu, dlen, data); + break; + + case BT_ATT_OP_READ_TYPE_RSP: + process_read_type_rsp(conn_handle, dlen, data); + break; + + case BT_ATT_OP_READ_GROUP_REQ: + process_read_group_req(conn_handle, mtu, dlen, data); + break; + + case BT_ATT_OP_READ_GROUP_RSP: + process_read_group_rsp(conn_handle, dlen, data); + break; + + case BT_ATT_OP_READ_REQ: + case BT_ATT_OP_READ_BLOB_REQ: + process_read_or_read_blob_req(conn_handle, mtu, opcode, dlen, data); + break; + + case BT_ATT_OP_READ_RSP: + process_read_rsp(conn_handle, dlen, data); + break; + + case BT_ATT_OP_WRITE_REQ: + case BT_ATT_OP_WRITE_CMD: + process_write_req_or_cmd(conn_handle, mtu, opcode, dlen, data); + break; + + case BT_ATT_OP_WRITE_RSP: + process_write_rsp(conn_handle, dlen, data); + break; + + case BT_ATT_OP_PREPARE_WRITE_REQ: + process_prepare_write_req(conn_handle, mtu, dlen, data); + break; + + case BT_ATT_OP_EXEC_WRITE_REQ: + process_exec_write_req(conn_handle, mtu, dlen, data); + break; + + case BT_ATT_OP_NOTIFY: + case BT_ATT_OP_INDICATE: + process_notify_or_indicate(conn_handle, opcode, dlen, data); + break; + + case BT_ATT_OP_CONFIRM: + process_confirm(conn_handle, dlen, data); + break; + + case BT_ATT_OP_READ_MULT_REQ: + case BT_ATT_OP_SIGNED_WRITE_CMD: + default: + send_error(conn_handle, opcode, 0x00, BT_ATT_ERR_NOT_SUPPORTED); + break; + } +} + +//FIX Do we need all of these? +void check_att_err(uint8_t err) { + const compressed_string_t *msg = NULL; + switch (err) { + case 0: + return; + case BT_ATT_ERR_INVALID_HANDLE: + msg = translate("Invalid handle"); + break; + case BT_ATT_ERR_READ_NOT_PERMITTED: + msg = translate("Read not permitted"); + break; + case BT_ATT_ERR_WRITE_NOT_PERMITTED: + msg = translate("Write not permitted"); + break; + case BT_ATT_ERR_INVALID_PDU: + msg = translate("Invalid PDU"); + break; + case BT_ATT_ERR_NOT_SUPPORTED: + msg = translate("Not supported"); + break; + case BT_ATT_ERR_INVALID_OFFSET: + msg = translate("Invalid offset"); + break; + case BT_ATT_ERR_PREPARE_QUEUE_FULL: + msg = translate("Prepare queue full"); + break; + case BT_ATT_ERR_ATTRIBUTE_NOT_FOUND: + msg = translate("Attribute not found"); + break; + case BT_ATT_ERR_ATTRIBUTE_NOT_LONG: + msg = translate("Attribute not long"); + break; + case BT_ATT_ERR_ENCRYPTION_KEY_SIZE: + msg = translate("Encryption key size"); + case BT_ATT_ERR_INVALID_ATTRIBUTE_LEN: + msg = translate("Invalid attribute length"); + break; + case BT_ATT_ERR_UNLIKELY: + msg = translate("Unlikely"); + break; + case BT_ATT_ERR_UNSUPPORTED_GROUP_TYPE: + msg = translate("Unsupported group type"); + break; + case BT_ATT_ERR_INSUFFICIENT_RESOURCES: + msg = translate("Insufficient resources"); + break; + case BT_ATT_ERR_DB_OUT_OF_SYNC: + msg = translate("DB out of sync"); + break; + case BT_ATT_ERR_VALUE_NOT_ALLOWED: + msg = translate("Value not allowed"); + break; + } + if (msg) { + mp_raise_bleio_BluetoothError(msg); + } + + switch (err) { + case BT_ATT_ERR_AUTHENTICATION: + msg = translate("Insufficient authentication"); + break; + case BT_ATT_ERR_INSUFFICIENT_ENCRYPTION: + msg = translate("Insufficient encryption"); + break; + } + if (msg) { + mp_raise_bleio_SecurityError(msg); + } + + mp_raise_bleio_BluetoothError(translate("Unknown ATT error: 0x%02x"), err); +} diff --git a/devices/ble_hci/common-hal/_bleio/att.h b/devices/ble_hci/common-hal/_bleio/att.h new file mode 100644 index 0000000000..b34b74dc37 --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/att.h @@ -0,0 +1,57 @@ +// Derived from ArduinoBLE. +// Copyright 2020 Dan Halbert for Adafruit Industries + +/* + This file is part of the ArduinoBLE library. + Copyright (c) 2018 Arduino SA. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef MICROPY_INCLUDED_DEVICES_BLE_HCI_COMMON_HAL_BLEIO_ATT_H +#define MICROPY_INCLUDED_DEVICES_BLE_HCI_COMMON_HAL_BLEIO_ATT_H + +#include +#include + +#include "hci_include/addr.h" +#include "hci_include/att.h" +#include "hci_include/att_internal.h" + +void bleio_att_reset(void); + +//FIX void att_set_event_handler(BLEDeviceEvent event, BLEDeviceEventHandler eventHandler); +bool att_address_is_connected(bt_addr_le_t *addr); +bool att_connect_to_address(bt_addr_le_t *addr); +bool att_disconnect(uint16_t conn_handle); +bool att_disconnect_all(void); +bool att_discover_attributes(bt_addr_le_t *addr, const char* service_uuid_filter); +bool att_exchange_mtu(uint16_t conn_handle); +bool att_handle_is_connected(uint16_t handle); +bool att_indicate(uint16_t handle, const uint8_t* value, int length); +bool att_is_connected(void); +bool att_notify(uint16_t handle, const uint8_t* value, int length); +int att_read_req(uint16_t conn_handle, uint16_t handle, uint8_t response_buffer[]); +int att_write_req(uint16_t conn_handle, uint16_t handle, const uint8_t* data, uint8_t data_len, uint8_t response_buffer[]); +uint16_t att_conn_handle(bt_addr_le_t *addr); +uint16_t att_mtu(uint16_t handle); +void att_add_connection(uint16_t handle, uint8_t role, bt_addr_le_t *peer_addr, uint16_t interval, uint16_t latency, uint16_t supervision_timeout, uint8_t master_clock_accuracy); +void att_process_data(uint16_t conn_handle, uint8_t dlen, uint8_t data[]); +void att_remove_connection(uint16_t conn_handle, uint8_t reason); +void att_set_max_mtu(uint16_t max_mtu); +void att_set_timeout(unsigned long timeout); +void att_write_cmd(uint16_t conn_handle, uint16_t handle, const uint8_t* data, uint8_t data_len); + +#endif // MICROPY_INCLUDED_DEVICES_BLE_HCI_COMMON_HAL_BLEIO_ATT_H diff --git a/devices/ble_hci/common-hal/_bleio/hci.c b/devices/ble_hci/common-hal/_bleio/hci.c new file mode 100644 index 0000000000..e261a98475 --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/hci.c @@ -0,0 +1,806 @@ +// This file is derived from the ArduinoBLE library. Its header is below. +/* + This file is part of the ArduinoBLE library. + Copyright (c) 2018 Arduino SA. All rights reserved. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "att.h" +#include "hci.h" + +#include "py/obj.h" +#include "py/mperrno.h" +#include "py/runtime.h" + +// Zephyr include files to define HCI communication values and structs. +#include "hci_include/hci.h" +#include "hci_include/hci_err.h" +#include "hci_include/l2cap_internal.h" + +#include + +#include "py/mphal.h" //***************************** +#include "supervisor/shared/tick.h" +#include "shared-bindings/_bleio/__init__.h" +#include "common-hal/_bleio/Adapter.h" +#include "shared-bindings/microcontroller/__init__.h" + +// Set to 1 for extensive HCI packet logging. +#define HCI_DEBUG 0 + +// HCI H4 protocol packet types: first byte in the packet. +#define H4_CMD 0x01 +#define H4_ACL 0x02 +#define H4_SCO 0x03 +#define H4_EVT 0x04 + +#define CTS_TIMEOUT_MSECS (1000) +#define RESPONSE_TIMEOUT_MSECS (1000) + +// These are the headers of the full packets that are sent over the serial interface. +// They all have a one-byte type-field at the front, one of the H4_xxx packet types. + +typedef struct __attribute__ ((packed)) { + uint8_t pkt_type; + uint16_t opcode; + uint8_t param_len; + uint8_t params[]; +} h4_hci_cmd_pkt_t; + +#define ACL_DATA_PB_FIRST_NON_FLUSH 0 +#define ACL_DATA_PB_MIDDLE 1 +#define ACL_DATA_PB_FIRST_FLUSH 2 +#define ACL_DATA_PB_FULL 3 + +typedef struct __attribute__ ((packed)) { + uint8_t pkt_type; + uint16_t handle : 12; + uint8_t pb: 2; // Packet boundary flag: ACL_DATA_PB values. + uint8_t bc: 2; // Broadcast flag: always 0b00 for BLE. + uint16_t data_len; // length of data[] in this packet. + uint8_t data[]; +} h4_hci_acl_pkt_t; + +// The ACL data in an h4_hci_acl_pkt_t may be fragmented across +// multiple ACL_DATA packets, and need to be recombined. This is the +// structure of the combined packet or the first fragment. +typedef struct __attribute__ ((packed)) { + uint16_t acl_data_len; // Length of acl_data. Does not include this header. + uint16_t cid; // Channel ID. + uint8_t acl_data[]; // Length is acl_data_len of full packet. +} acl_data_t; + +typedef struct __attribute__ ((packed)) { + uint8_t pkt_type; + uint8_t evt; + uint8_t param_len; + uint8_t params[]; +} h4_hci_evt_pkt_t; + + +////////////////////////////////////////////////////////////////////// +// Static storage: + +//FIX size +#define RX_BUFFER_SIZE (3 + 255) +#define ACL_DATA_BUFFER_SIZE (255) + +STATIC uint8_t rx_buffer[RX_BUFFER_SIZE]; +STATIC size_t rx_idx; + +STATIC uint8_t acl_data_buffer[ACL_DATA_BUFFER_SIZE]; +STATIC size_t acl_data_len; + +STATIC size_t num_command_packets_allowed; +STATIC volatile size_t pending_pkt; + +// Results from parsing a command response packet. +STATIC bool cmd_response_received; +STATIC uint16_t cmd_response_opcode; +STATIC uint8_t cmd_response_status; +STATIC size_t cmd_response_len; +STATIC uint8_t* cmd_response_data; + +STATIC volatile bool hci_poll_in_progress = false; + + +////////////////////////////////////////////////////////////////////// + +#if HCI_DEBUG +#include "hci_debug.c" +#endif // HCI_DEBUG + +STATIC void process_acl_data_pkt(uint8_t pkt_len, uint8_t pkt_data[]) { + h4_hci_acl_pkt_t *pkt = (h4_hci_acl_pkt_t*) pkt_data; + + if (pkt->pb != ACL_DATA_PB_MIDDLE) { + // This is the start of a fragmented acl_data packet or is a full packet. + memcpy(acl_data_buffer, pkt->data, pkt->data_len); + acl_data_len = pkt->data_len; + } else { + // This is a middle or end fragment of acl data. + // Append to the accumulated data so far. + memcpy(&acl_data_buffer[acl_data_len], pkt->data, pkt->data_len); + acl_data_len += pkt->data_len; + } + + acl_data_t *acl = (acl_data_t *) &acl_data_buffer; + if (acl_data_len != sizeof(acl) + acl->acl_data_len) { + // We don't have the full packet yet. + return; + } + + if (acl->cid == BT_L2CAP_CID_ATT) { + att_process_data(pkt->handle, acl->acl_data_len, acl->acl_data); + } + // } else if (aclHdr->cid == BT_L2CAP_CID_LE_SIG) { + // L2CAPSignaling.handleData(aclHdr->handle & 0x0fff, aclHdr->len, &rx_buffer[1 + sizeof(HCIACLHdr)]); + // } else { + // struct __attribute__ ((packed)) { + // uint8_t op; + // uint8_t id; + // uint16_t length; + // uint16_t reason; + // uint16_t localCid; + // uint16_t remoteCid; + // } l2capRejectCid= { 0x01, 0x00, 0x006, 0x0002, aclHdr->cid, 0x0000 }; + + // sendAclPkt(aclHdr->handle & 0x0fff, 0x0005, sizeof(l2capRejectCid), &l2capRejectCid); + // } +} + +// Process number of completed packets. Reduce number of pending packets by reported +// number of completed. +STATIC void process_num_comp_pkts(uint16_t handle, uint16_t num_pkts) { + if (num_pkts && pending_pkt > num_pkts) { + pending_pkt -= num_pkts; + } else { + pending_pkt = 0; + } +} + +STATIC void process_evt_pkt(size_t pkt_len, uint8_t pkt_data[]) +{ + h4_hci_evt_pkt_t *pkt = (h4_hci_evt_pkt_t*) pkt_data; + + switch (pkt->evt) { + case BT_HCI_EVT_DISCONN_COMPLETE: { + struct bt_hci_evt_disconn_complete *disconn_complete = + (struct bt_hci_evt_disconn_complete*) pkt->params; + (void) disconn_complete; + + att_remove_connection(disconn_complete->handle, disconn_complete->reason); + //FIX L2CAPSignaling.removeConnection(disconn_complete->handle, disconn_complete->reason); + break; + } + + case BT_HCI_EVT_CMD_COMPLETE: { + struct cmd_complete_with_status { + struct bt_hci_evt_cmd_complete cmd_complete; + struct bt_hci_evt_cc_status cc_status; + } __packed; + + struct cmd_complete_with_status *evt = (struct cmd_complete_with_status *) pkt->params; + + num_command_packets_allowed = evt->cmd_complete.ncmd; + + cmd_response_received = true; + cmd_response_opcode = evt->cmd_complete.opcode; + cmd_response_status = evt->cc_status.status; + // All the bytes following cmd_complete, -including- the status byte, which is + // included in all the _bt_hci_rp_* structs. + cmd_response_data = (uint8_t *) &evt->cc_status; + // Includes status byte. + cmd_response_len = pkt->param_len - sizeof_field(struct cmd_complete_with_status, cmd_complete); + + break; + } + + case BT_HCI_EVT_CMD_STATUS: { + struct bt_hci_evt_cmd_status *evt = (struct bt_hci_evt_cmd_status *) pkt->params; + + num_command_packets_allowed = evt->ncmd; + + cmd_response_received = true; + cmd_response_opcode = evt->opcode; + cmd_response_status = evt->status; + cmd_response_data = NULL; + cmd_response_len = 0; + + break; + } + + case BT_HCI_EVT_NUM_COMPLETED_PACKETS: { + struct bt_hci_evt_num_completed_packets *evt = + (struct bt_hci_evt_num_completed_packets *) pkt->params; + + // Start at zero-th pair: (conn handle, num completed packets). + struct bt_hci_handle_count *handle_and_count = &(evt->h[0]); + for (uint8_t i = 0; i < evt->num_handles; i++) { + process_num_comp_pkts(handle_and_count->handle, handle_and_count->count); + handle_and_count++; + } + break; + } + + case BT_HCI_EVT_LE_META_EVENT: { + struct bt_hci_evt_le_meta_event *meta_evt = (struct bt_hci_evt_le_meta_event *) pkt->params; + uint8_t *le_evt = pkt->params + sizeof (struct bt_hci_evt_le_meta_event); + + if (meta_evt->subevent == BT_HCI_EVT_LE_CONN_COMPLETE) { + // Advertising stops when connection occurs. + // We don't tell the adapter to stop, because stopping advertising + // when it's already stopped seems to exercise a bug in the ESP32 HCI code: + // It doesn't return a response. + bleio_adapter_advertising_was_stopped(&common_hal_bleio_adapter_obj); + + struct bt_hci_evt_le_conn_complete *le_conn_complete = + (struct bt_hci_evt_le_conn_complete *) le_evt; + + if (le_conn_complete->status == BT_HCI_ERR_SUCCESS) { + att_add_connection( + le_conn_complete->handle, + le_conn_complete->role, + &le_conn_complete->peer_addr, + le_conn_complete->interval, + le_conn_complete->latency, + le_conn_complete->supv_timeout, + le_conn_complete->clock_accuracy); + + } + } else if (meta_evt->subevent == BT_HCI_EVT_LE_ADVERTISING_REPORT) { + struct bt_hci_evt_le_advertising_info *le_advertising_info = + (struct bt_hci_evt_le_advertising_info *) le_evt; + if (le_advertising_info->evt_type == BT_HCI_ADV_DIRECT_IND) { + //FIX + // last byte is RSSI + // GAP.handleLeAdvertisingReport(leAdvertisingReport->type, + // leAdvertisingReport->peerBdaddrType, + // leAdvertisingReport->peerBdaddr, + // leAdvertisingReport->eirLength, + // leAdvertisingReport->eirData, + // rssi); //FIX, don't separate + + } + } + break; + } + + default: +#if HCI_DEBUG + mp_printf(&mp_plat_print, "process_evt_pkt: Unknown event: %02x\n"); +#endif + break; + } +} + +void bleio_hci_reset(void) { + rx_idx = 0; + pending_pkt = 0; + hci_poll_in_progress = false; + bleio_att_reset(); +} + +hci_result_t hci_poll_for_incoming_pkt(void) { + common_hal_mcu_disable_interrupts(); + if (hci_poll_in_progress) { + common_hal_mcu_enable_interrupts(); + return HCI_OK; + } + hci_poll_in_progress = true; + common_hal_mcu_enable_interrupts(); + + // Assert RTS low to say we're ready to read data. + common_hal_digitalio_digitalinout_set_value(common_hal_bleio_adapter_obj.rts_digitalinout, false); + + int errcode = 0; + bool packet_is_complete = false; + + // Read bytes until we run out. There may be more than one packet in the input buffer. + while (!packet_is_complete && + common_hal_busio_uart_rx_characters_available(common_hal_bleio_adapter_obj.hci_uart) > 0) { + + // Read just one character a a time, so we don't accidentally get part of a second + // packet. + size_t num_read = + common_hal_busio_uart_read(common_hal_bleio_adapter_obj.hci_uart, rx_buffer + rx_idx, 1, &errcode); + if (num_read == 0) { + return HCI_OK; + } + if (errcode) { + if (errcode == EAGAIN) { + continue; + } + hci_poll_in_progress = false; + mp_printf(&mp_plat_print, "HCI_READ_ERROR, errcode: %x\n", errcode); + return HCI_READ_ERROR; + } + rx_idx++; + if (rx_idx >= sizeof(rx_buffer)) { + // Incoming packet is too large. Should not happen. + return HCI_READ_ERROR; + } + + switch (rx_buffer[0]) { + case H4_ACL: + if (rx_idx >= sizeof(h4_hci_acl_pkt_t)) { + const size_t total_len = + sizeof(h4_hci_acl_pkt_t) + ((h4_hci_acl_pkt_t *) rx_buffer)->data_len; + if (rx_idx == total_len) { + packet_is_complete = true; + } + if (rx_idx > total_len) { + return HCI_PACKET_SIZE_ERROR; + } + } + break; + + case H4_EVT: + if (rx_idx >= sizeof(h4_hci_evt_pkt_t)) { + const size_t total_len = + sizeof(h4_hci_evt_pkt_t) + ((h4_hci_evt_pkt_t *) rx_buffer)->param_len; + if (rx_idx == total_len) { + packet_is_complete = true; + } + if (rx_idx > total_len) { + return HCI_PACKET_SIZE_ERROR; + } + } + break; + + default: + // Unknown or bad packet type. Start over. + rx_idx = 0; + break; + } + } // end while + + if (packet_is_complete) { + // Stop incoming data while processing packet. + common_hal_digitalio_digitalinout_set_value(common_hal_bleio_adapter_obj.rts_digitalinout, true); + size_t pkt_len = rx_idx; + + // Reset for next packet. + rx_idx = 0; + packet_is_complete = false; + + switch (rx_buffer[0]) { + case H4_ACL: +#if HCI_DEBUG + dump_acl_pkt(false, pkt_len, rx_buffer); +#endif + process_acl_data_pkt(pkt_len, rx_buffer); + break; + + case H4_EVT: +#if HCI_DEBUG + dump_evt_pkt(false, pkt_len, rx_buffer); +#endif + process_evt_pkt(pkt_len, rx_buffer); + break; + + default: +#if HCI_DEBUG + mp_printf(&mp_plat_print, "Unknown HCI packet type: %d\n", rx_buffer[0]); +#endif + break; + } + + // Let incoming bytes flow again. + common_hal_digitalio_digitalinout_set_value(common_hal_bleio_adapter_obj.rts_digitalinout, false); + } + + // All done with this batch. Hold off receiving bytes until we're ready again. + ///common_hal_digitalio_digitalinout_set_value(common_hal_bleio_adapter_obj.rts_digitalinout, true); + hci_poll_in_progress = false; + return HCI_OK; +} + + +STATIC hci_result_t write_pkt(uint8_t *buffer, size_t len) { + // Wait for CTS to go low before writing to HCI adapter. + uint64_t start = supervisor_ticks_ms64(); + + while (common_hal_digitalio_digitalinout_get_value(common_hal_bleio_adapter_obj.cts_digitalinout)) { + RUN_BACKGROUND_TASKS; + if (supervisor_ticks_ms64() - start > CTS_TIMEOUT_MSECS) { + return HCI_WRITE_TIMEOUT; + } + } + + int errcode = 0; + common_hal_busio_uart_write(common_hal_bleio_adapter_obj.hci_uart, buffer, len, &errcode); + if (errcode) { + return HCI_WRITE_ERROR; + } + + return HCI_OK; +} + +STATIC hci_result_t send_command(uint16_t opcode, uint8_t params_len, void* params) { + uint8_t cmd_pkt_len = sizeof(h4_hci_cmd_pkt_t) + params_len; + uint8_t tx_buffer[cmd_pkt_len]; + + // cmd header is at the beginning of tx_buffer + h4_hci_cmd_pkt_t *cmd_pkt = (h4_hci_cmd_pkt_t *) tx_buffer; + cmd_pkt->pkt_type = H4_CMD; + cmd_pkt->opcode = opcode; + cmd_pkt->param_len = params_len; + + memcpy(cmd_pkt->params, params, params_len); + +#if HCI_DEBUG + dump_cmd_pkt(true, sizeof(tx_buffer), tx_buffer); +#endif + + int result = write_pkt(tx_buffer, cmd_pkt_len); + if (result != HCI_OK) { + return result; + } + + cmd_response_received = false; + + // Wait for a response. Note that other packets may be received that are not + // command responses. + uint64_t start = supervisor_ticks_ms64(); + while (supervisor_ticks_ms64() - start < RESPONSE_TIMEOUT_MSECS) { + // RUN_BACKGROUND_TASKS includes hci_poll_for_incoming_pkt(); + RUN_BACKGROUND_TASKS; + if (cmd_response_received && cmd_response_opcode == opcode) { + // If this is definitely a response to the command that was sent, + // return the status value, which will will be + // BT_HCI_ERR_SUCCESS (0x00) if the command succeeded, + // or a BT_HCI_ERR_x value (> 0x00) if there was a problem. + return cmd_response_status; + } + } + + // No I/O error, but no response sent back in time. + return HCI_RESPONSE_TIMEOUT; +} + +hci_result_t hci_send_acl_pkt(uint16_t handle, uint8_t cid, uint16_t data_len, uint8_t *data) { + // Wait for all backlogged packets to finish. + while (pending_pkt >= common_hal_bleio_adapter_obj.max_acl_num_buffers) { + // RUN_BACKGROUND_TASKS includes hci_poll_for_incoming_pkt(); + RUN_BACKGROUND_TASKS; + } + + // buf_len is size of entire packet including header. + const size_t buf_len = sizeof(h4_hci_acl_pkt_t) + sizeof(acl_data_t) + data_len; + uint8_t tx_buffer[buf_len]; + + h4_hci_acl_pkt_t *acl_pkt = (h4_hci_acl_pkt_t *) tx_buffer; + acl_data_t *acl_data = (acl_data_t *) acl_pkt->data; + acl_pkt->pkt_type = H4_ACL; + acl_pkt->handle = handle; + acl_pkt->pb = ACL_DATA_PB_FIRST_FLUSH; + acl_pkt->bc = 0; + acl_pkt->data_len = (uint16_t)(sizeof(acl_data_t) + data_len); + acl_data->acl_data_len = data_len; + acl_data->cid = cid; + + memcpy(&acl_data->acl_data, data, data_len); + +#if HCI_DEBUG + dump_acl_pkt(true, buf_len, tx_buffer); +#endif + + pending_pkt++; + + int errcode = 0; + common_hal_busio_uart_write(common_hal_bleio_adapter_obj.hci_uart, tx_buffer, buf_len, &errcode); + if (errcode) { + return HCI_WRITE_ERROR; + } + return HCI_OK; +} + +hci_result_t hci_reset(void) { + return send_command(BT_HCI_OP_RESET, 0, NULL); +} + +hci_result_t hci_read_local_version(uint8_t *hci_version, uint16_t *hci_revision, uint8_t *lmp_version, uint16_t *manufacturer, uint16_t *lmp_subversion) { + hci_result_t result = send_command(BT_HCI_OP_READ_LOCAL_VERSION_INFO, 0, NULL); + if (result == HCI_OK) { + struct bt_hci_rp_read_local_version_info *response = + (struct bt_hci_rp_read_local_version_info *) cmd_response_data; + *hci_version = response->hci_version; + *hci_revision = response->hci_revision; + *lmp_version = response->lmp_version; + *manufacturer = response->manufacturer; + *lmp_subversion = response->lmp_subversion; + } + + return result; +} + +hci_result_t hci_read_bd_addr(bt_addr_t *addr) { + int result = send_command(BT_HCI_OP_READ_BD_ADDR, 0, NULL); + if (result == HCI_OK) { + struct bt_hci_rp_read_bd_addr *response = (struct bt_hci_rp_read_bd_addr *) cmd_response_data; + memcpy(addr->val, response->bdaddr.val, sizeof_field(bt_addr_t, val)); + } + + return result; +} + +hci_result_t hci_read_rssi(uint16_t handle, int *rssi) { + int result = send_command(BT_HCI_OP_READ_RSSI, sizeof(handle), &handle); + if (result == HCI_OK) { + struct bt_hci_rp_read_rssi *response = (struct bt_hci_rp_read_rssi *) cmd_response_data; + *rssi = response->rssi; + } + + return result; +} + +hci_result_t hci_set_event_mask(uint64_t event_mask) { + return send_command(BT_HCI_OP_SET_EVENT_MASK, sizeof(event_mask), &event_mask); +} + +hci_result_t hci_le_read_buffer_size(uint16_t *le_max_len, uint8_t *le_max_num) { + int result = send_command(BT_HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL); + if (result == HCI_OK) { + struct bt_hci_rp_le_read_buffer_size *response = + (struct bt_hci_rp_le_read_buffer_size *) cmd_response_data; + *le_max_len = response->le_max_len; + *le_max_num = response->le_max_num; + } + + return result; +} + +hci_result_t hci_read_buffer_size(uint16_t *acl_max_len, uint8_t *sco_max_len, uint16_t *acl_max_num, uint16_t *sco_max_num) { + int result = send_command(BT_HCI_OP_READ_BUFFER_SIZE, 0, NULL); + if (result == HCI_OK) { + struct bt_hci_rp_read_buffer_size *response = + (struct bt_hci_rp_read_buffer_size *) cmd_response_data; + *acl_max_len = response->acl_max_len; + *sco_max_len = response->sco_max_len; + *acl_max_num = response->acl_max_num; + *sco_max_num = response->sco_max_num; + } + + return result; +} + +hci_result_t hci_le_set_random_address(uint8_t addr[6]) { + return send_command(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, 6, addr); +} + +hci_result_t hci_le_set_advertising_parameters(uint16_t min_interval, uint16_t max_interval, uint8_t type, uint8_t own_addr_type, bt_addr_le_t *direct_addr, uint8_t channel_map, uint8_t filter_policy) { + struct bt_hci_cp_le_set_adv_param params = { + .min_interval = min_interval, + .max_interval = max_interval, + .type = type, + .own_addr_type = own_addr_type, + // .direct_addr set below. + .channel_map = channel_map, + .filter_policy = filter_policy, + }; + params.direct_addr.type = direct_addr->type; + memcpy(params.direct_addr.a.val, direct_addr->a.val, sizeof(params.direct_addr.a.val)); + + return send_command(BT_HCI_OP_LE_SET_ADV_PARAM, sizeof(params), ¶ms); +} + +hci_result_t hci_le_set_extended_advertising_parameters(uint8_t handle, uint16_t props, uint32_t prim_min_interval, uint32_t prim_max_interval, uint8_t prim_channel_map, uint8_t own_addr_type, bt_addr_le_t *peer_addr, uint8_t filter_policy, int8_t tx_power, uint8_t prim_adv_phy, uint8_t sec_adv_max_skip, uint8_t sec_adv_phy, uint8_t sid, uint8_t scan_req_notify_enable) { + struct bt_hci_cp_le_set_ext_adv_param params = { + .handle = handle, + .props = props, + // .prim_min_interval and .prim_max_interval set below + .prim_channel_map = prim_channel_map, + .own_addr_type = own_addr_type, + // .peer_addr set below. + .tx_power = tx_power, + .sec_adv_max_skip = sec_adv_max_skip, + .sec_adv_phy = sec_adv_phy, + .sid = sid, + .scan_req_notify_enable = scan_req_notify_enable, + }; + // Assumes little-endian. + memcpy(params.prim_min_interval, (void *) &prim_min_interval, + sizeof_field(struct bt_hci_cp_le_set_ext_adv_param, prim_min_interval)); + memcpy(params.prim_max_interval, (void *) &prim_max_interval, + sizeof_field(struct bt_hci_cp_le_set_ext_adv_param, prim_max_interval)); + memcpy(params.peer_addr.a.val, peer_addr->a.val, sizeof_field(bt_addr_le_t, a.val)); + return send_command(BT_HCI_OP_LE_SET_EXT_ADV_PARAM, sizeof(params), ¶ms); +} + +hci_result_t hci_le_read_maximum_advertising_data_length(uint16_t *max_adv_data_len) { + int result = send_command(BT_HCI_OP_LE_READ_MAX_ADV_DATA_LEN, 0, NULL); + if (result == HCI_OK) { + struct bt_hci_rp_le_read_max_adv_data_len *response = + (struct bt_hci_rp_le_read_max_adv_data_len *) cmd_response_data; + *max_adv_data_len = response->max_adv_data_len; + } + + return result; +} + +hci_result_t hci_le_read_local_supported_features(uint8_t features[8]) { + int result = send_command(BT_HCI_OP_LE_READ_LOCAL_FEATURES, 0, NULL); + if (result == HCI_OK) { + struct bt_hci_rp_le_read_local_features *response = + (struct bt_hci_rp_le_read_local_features *) cmd_response_data; + memcpy(features, response->features, + sizeof_field(struct bt_hci_rp_le_read_local_features, features)); + } + + return result; +} + +hci_result_t hci_le_set_advertising_data(uint8_t len, uint8_t data[]) { + struct bt_hci_cp_le_set_adv_data params = { + // Zero out unused data bytes. + .data = { 0 }, + }; + + params.len = len; + memcpy(params.data, data, len); + + // All data bytes are sent even if some are unused. + return send_command(BT_HCI_OP_LE_SET_ADV_DATA, sizeof(params), ¶ms); +} + +hci_result_t hci_le_set_extended_advertising_data(uint8_t handle, uint8_t op, uint8_t frag_pref, uint8_t len, uint8_t data[]) { + const uint8_t max_len = sizeof_field(struct bt_hci_cp_le_set_ext_adv_data, data); + uint8_t valid_len = MIN(len, max_len); + struct bt_hci_cp_le_set_ext_adv_data params = { + .handle = handle, + .op = op, + .frag_pref = frag_pref, + .len = valid_len, + }; + memcpy(params.data, data, valid_len); + return send_command(BT_HCI_OP_LE_SET_EXT_ADV_DATA, sizeof(params) - (max_len - valid_len), ¶ms); +} + + +hci_result_t hci_le_set_scan_response_data(uint8_t len, uint8_t data[]) { + struct bt_hci_cp_le_set_scan_rsp_data params = { + // Zero out unused data bytes. + .data = { 0 }, + }; + params.len = len; + memcpy(params.data, data, len); + + // All data bytes are sent even if some are unused. + return send_command(BT_HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(params), ¶ms); +} + +hci_result_t hci_le_set_advertising_enable(uint8_t enable) { + return send_command(BT_HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); +} + +hci_result_t hci_le_set_extended_advertising_enable(uint8_t enable, uint8_t set_num, uint8_t handle[], uint16_t duration[], uint8_t max_ext_adv_evts[]) { + uint8_t params[sizeof(struct bt_hci_cp_le_set_ext_adv_enable) + + set_num * (sizeof(struct bt_hci_ext_adv_set))]; + struct bt_hci_cp_le_set_ext_adv_enable *params_p = (struct bt_hci_cp_le_set_ext_adv_enable *) ¶ms; + params_p->enable = enable; + params_p->set_num = set_num; + for (size_t i = 0; i < set_num; i++) { + params_p->s[i].handle = handle[i]; + params_p->s[i].duration = duration[i]; + params_p->s[i].max_ext_adv_evts = max_ext_adv_evts[i]; + } + + return send_command(BT_HCI_OP_LE_SET_EXT_ADV_ENABLE, sizeof(params), ¶ms); +} + +hci_result_t hci_le_set_scan_parameters(uint8_t scan_type, uint16_t interval, uint16_t window, uint8_t addr_type, uint8_t filter_policy) { + struct bt_hci_cp_le_set_scan_param params = { + .scan_type = scan_type, + .interval = interval, + .window = window, + .addr_type = addr_type, + .filter_policy = filter_policy, + }; + + return send_command(BT_HCI_OP_LE_SET_SCAN_PARAM, sizeof(params), ¶ms); +} + +hci_result_t hci_le_set_scan_enable(uint8_t enable, uint8_t filter_dup) { + struct bt_hci_cp_le_set_scan_enable params = { + .enable = enable, + .filter_dup = filter_dup, + }; + + return send_command(BT_HCI_OP_LE_SET_SCAN_ENABLE, sizeof(params), ¶ms); +} + +hci_result_t hci_le_create_conn(uint16_t scan_interval, uint16_t scan_window, uint8_t filter_policy, bt_addr_le_t *peer_addr, uint8_t own_addr_type, uint16_t conn_interval_min, uint16_t conn_interval_max, uint16_t conn_latency, uint16_t supervision_timeout, uint16_t min_ce_len, uint16_t max_ce_len) { + struct bt_hci_cp_le_create_conn params = { + .scan_interval = scan_interval, + .scan_window = scan_window, + .filter_policy = filter_policy, + // .peer_addr is set below + .own_addr_type = own_addr_type, + .conn_interval_min = conn_interval_min, + .conn_interval_max = conn_interval_max, + .conn_latency = conn_latency, + .supervision_timeout = supervision_timeout, + .min_ce_len = min_ce_len, + .max_ce_len = max_ce_len, + }; + params.peer_addr.type = peer_addr->type; + memcpy(params.peer_addr.a.val, peer_addr->a.val, sizeof(params.peer_addr.a.val)); + + return send_command(BT_HCI_OP_LE_CREATE_CONN, sizeof(params), ¶ms); +} + +hci_result_t hci_le_cancel_conn(void) { + return send_command(BT_HCI_OP_CONNECT_CANCEL, 0, NULL); +} + +hci_result_t hci_le_conn_update(uint16_t handle, uint16_t conn_interval_min, uint16_t conn_interval_max, uint16_t conn_latency, uint16_t supervision_timeout) { + struct hci_cp_le_conn_update params = { + .handle = handle, + .conn_interval_min = conn_interval_min, + .conn_interval_max = conn_interval_max, + .conn_latency = conn_latency, + .supervision_timeout = supervision_timeout, + .min_ce_len = 4, + .max_ce_len = 6, + }; + + return send_command(BT_HCI_OP_LE_CONN_UPDATE, sizeof(params), ¶ms); +} + +hci_result_t hci_disconnect(uint16_t handle) { + struct bt_hci_cp_disconnect params = { + .handle = handle, + .reason = BT_HCI_ERR_REMOTE_USER_TERM_CONN, + }; + + return send_command(BT_HCI_OP_DISCONNECT, sizeof(params), ¶ms); +} + +void hci_check_error(hci_result_t result) { + switch (result) { + case HCI_OK: + return; + + case HCI_RESPONSE_TIMEOUT: + mp_raise_bleio_BluetoothError(translate("Timeout waiting for HCI response")); + return; + + case HCI_WRITE_TIMEOUT: + mp_raise_bleio_BluetoothError(translate("Timeout waiting to write HCI request")); + return; + + case HCI_READ_ERROR: + mp_raise_bleio_BluetoothError(translate("Error reading from HCI adapter")); + return; + + case HCI_WRITE_ERROR: + mp_raise_bleio_BluetoothError(translate("Error writing to HCI adapter")); + return; + + case HCI_PACKET_SIZE_ERROR: + mp_raise_RuntimeError(translate("HCI packet size mismatch")); + return; + + case HCI_ATT_ERROR: + mp_raise_RuntimeError(translate("Error in ATT protocol code")); + return; + + default: + // Should be an HCI status error, > 0. + if (result > 0) { + mp_raise_bleio_BluetoothError(translate("HCI status error: %02x"), result); + } else { + mp_raise_bleio_BluetoothError(translate("Unknown hci_result_t: %d"), result); + } + return; + } +} diff --git a/devices/ble_hci/common-hal/_bleio/hci.h b/devices/ble_hci/common-hal/_bleio/hci.h new file mode 100644 index 0000000000..c9fd2393af --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/hci.h @@ -0,0 +1,81 @@ +/* + This file is part of the ArduinoBLE library. + Copyright (c) 2018 Arduino SA. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef MICROPY_INCLUDED_DEVICES_BLE_HCI_COMMON_HAL_BLEIO_HCI_H +#define MICROPY_INCLUDED_DEVICES_BLE_HCI_COMMON_HAL_BLEIO_HCI_H + +#include + +#include "common-hal/_bleio/hci_include/hci.h" +#include "common-hal/_bleio/hci_include/hci_err.h" + +// Incomplete forward declaration to get around mutually-dependent include files. +typedef struct _bleio_adapter_obj_t bleio_adapter_obj_t; + +// An hci_result_t is one of the HCI_x values below, +// or it is > 0 and is an HCI command status value (see hci_include/hci_err.h) +typedef int hci_result_t; +#define HCI_OK (0) +#define HCI_RESPONSE_TIMEOUT (-1) +#define HCI_WRITE_TIMEOUT (-2) +#define HCI_READ_ERROR (-3) +#define HCI_WRITE_ERROR (-4) +#define HCI_ATT_ERROR (-5) +#define HCI_PACKET_SIZE_ERROR (-6) + +extern void bleio_hci_reset(void); + +void hci_check_error(hci_result_t result); + +hci_result_t hci_disconnect(uint16_t handle); + +hci_result_t hci_le_cancel_conn(void); +hci_result_t hci_le_conn_update(uint16_t handle, uint16_t conn_interval_min, uint16_t conn_interval_max, uint16_t conn_latency, uint16_t supervision_timeout); +hci_result_t hci_le_create_conn(uint16_t scan_interval, uint16_t scan_window, uint8_t filter_policy, bt_addr_le_t *peer_addr, uint8_t own_addr_type, uint16_t conn_interval_min, uint16_t conn_interval_max, uint16_t conn_latency, uint16_t supervision_timeout, uint16_t min_ce_len, uint16_t max_ce_len); + +hci_result_t hci_le_read_buffer_size(uint16_t *le_max_len, uint8_t *le_max_num); +hci_result_t hci_le_read_maximum_advertising_data_length(uint16_t *max_adv_data_len); +hci_result_t hci_le_read_local_supported_features(uint8_t features[8]); + +hci_result_t hci_le_set_advertising_data(uint8_t length, uint8_t data[]); +hci_result_t hci_le_set_advertising_enable(uint8_t enable); +hci_result_t hci_le_set_advertising_parameters(uint16_t min_interval, uint16_t max_interval, uint8_t type, uint8_t own_addr_type, bt_addr_le_t *direct_addr, uint8_t channel_map, uint8_t filter_policy); + +hci_result_t hci_le_set_extended_advertising_data(uint8_t handle, uint8_t op, uint8_t frag_pref, uint8_t len, uint8_t data[]); +hci_result_t hci_le_set_extended_advertising_enable(uint8_t enable, uint8_t set_num, uint8_t handle[], uint16_t duration[], uint8_t max_ext_adv_evts[]); +hci_result_t hci_le_set_extended_advertising_parameters(uint8_t handle, uint16_t props, uint32_t prim_min_interval, uint32_t prim_max_interval, uint8_t prim_channel_map, uint8_t own_addr_type, bt_addr_le_t *peer_addr, uint8_t filter_policy, int8_t tx_power, uint8_t prim_adv_phy, uint8_t sec_adv_max_skip, uint8_t sec_adv_phy, uint8_t sid, uint8_t scan_req_notify_enable); + +hci_result_t hci_le_set_random_address(uint8_t addr[6]); +hci_result_t hci_le_set_scan_enable(uint8_t enable, uint8_t filter_dup); +hci_result_t hci_le_set_scan_parameters(uint8_t scan_type, uint16_t interval, uint16_t window, uint8_t addr_type, uint8_t filter_policy); +hci_result_t hci_le_set_scan_response_data(uint8_t length, uint8_t data[]); + +hci_result_t hci_poll_for_incoming_pkt(void); + +hci_result_t hci_read_bd_addr(bt_addr_t *addr); +hci_result_t hci_read_buffer_size(uint16_t *acl_max_len, uint8_t *sco_max_len, uint16_t *acl_max_num, uint16_t *sco_max_num); +hci_result_t hci_read_local_version(uint8_t *hci_version, uint16_t *hci_revision, uint8_t *lmp_version, uint16_t *manufacturer, uint16_t *lmp_subversion); +hci_result_t hci_read_rssi(uint16_t handle, int *rssi); + +hci_result_t hci_reset(void); + +hci_result_t hci_send_acl_pkt(uint16_t handle, uint8_t cid, uint16_t data_len, uint8_t *data); +hci_result_t hci_set_event_mask(uint64_t event_mask); + +#endif // MICROPY_INCLUDED_DEVICES_BLE_HCI_COMMON_HAL_BLEIO_HCI_H diff --git a/devices/ble_hci/common-hal/_bleio/hci_debug.c b/devices/ble_hci/common-hal/_bleio/hci_debug.c new file mode 100644 index 0000000000..9cdd38981e --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/hci_debug.c @@ -0,0 +1,335 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Dan Halbert for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// This file is #include'd in hci.c when HCI_DEBUG is non-zero. + +STATIC const char* att_opcode_name(uint16_t opcode) { + switch (opcode) { + case BT_ATT_OP_ERROR_RSP: return "ERROR_RSP"; + case BT_ATT_OP_MTU_REQ: return "MTU_REQ"; + case BT_ATT_OP_MTU_RSP: return "MTU_RSP"; + case BT_ATT_OP_FIND_INFO_REQ: return "FIND_INFO_REQ"; + case BT_ATT_OP_FIND_INFO_RSP: return "FIND_INFO_RSP"; + case BT_ATT_OP_FIND_TYPE_REQ: return "FIND_TYPE_REQ"; + case BT_ATT_OP_FIND_TYPE_RSP: return "FIND_TYPE_RSP"; + case BT_ATT_OP_READ_TYPE_REQ: return "READ_TYPE_REQ"; + case BT_ATT_OP_READ_TYPE_RSP: return "READ_TYPE_RSP"; + case BT_ATT_OP_READ_REQ: return "READ_REQ"; + case BT_ATT_OP_READ_RSP: return "READ_RSP"; + case BT_ATT_OP_READ_BLOB_REQ: return "READ_BLOB_REQ"; + case BT_ATT_OP_READ_BLOB_RSP: return "READ_BLOB_RSP"; + case BT_ATT_OP_READ_MULT_REQ: return "READ_MULT_REQ"; + case BT_ATT_OP_READ_MULT_RSP: return "READ_MULT_RSP"; + case BT_ATT_OP_READ_GROUP_REQ: return "READ_GROUP_REQ"; + case BT_ATT_OP_READ_GROUP_RSP: return "READ_GROUP_RSP"; + case BT_ATT_OP_WRITE_REQ: return "WRITE_REQ"; + case BT_ATT_OP_WRITE_RSP: return "WRITE_RSP"; + case BT_ATT_OP_PREPARE_WRITE_REQ: return "PREPARE_WRITE_REQ"; + case BT_ATT_OP_PREPARE_WRITE_RSP: return "PREPARE_WRITE_RSP"; + case BT_ATT_OP_EXEC_WRITE_REQ: return "EXEC_WRITE_REQ"; + case BT_ATT_OP_EXEC_WRITE_RSP: return "EXEC_WRITE_RSP"; + case BT_ATT_OP_NOTIFY: return "NOTIFY"; + case BT_ATT_OP_INDICATE: return "INDICATE"; + case BT_ATT_OP_CONFIRM: return "CONFIRM"; + case BT_ATT_OP_READ_MULT_VL_REQ: return "READ_MULT_VL_REQ"; + case BT_ATT_OP_READ_MULT_VL_RSP: return "READ_MULT_VL_RSP"; + case BT_ATT_OP_NOTIFY_MULT: return "NOTIFY_MULT"; + case BT_ATT_OP_WRITE_CMD: return "WRITE_CMD"; + case BT_ATT_OP_SIGNED_WRITE_CMD: return "SIGNED_WRITE_CMD"; + default: return ""; + } +} + +STATIC const char* hci_evt_name(uint8_t evt) { + switch (evt) { + case BT_HCI_EVT_UNKNOWN: return "UNKNOWN"; + case BT_HCI_EVT_VENDOR: return "VENDOR"; + case BT_HCI_EVT_INQUIRY_COMPLETE: return "INQUIRY_COMPLETE"; + case BT_HCI_EVT_CONN_COMPLETE: return "CONN_COMPLETE"; + case BT_HCI_EVT_CONN_REQUEST: return "CONN_REQUEST"; + case BT_HCI_EVT_DISCONN_COMPLETE: return "DISCONN_COMPLETE"; + case BT_HCI_EVT_AUTH_COMPLETE: return "AUTH_COMPLETE"; + case BT_HCI_EVT_REMOTE_NAME_REQ_COMPLETE: return "REMOTE_NAME_REQ_COMPLETE"; + case BT_HCI_EVT_ENCRYPT_CHANGE: return "ENCRYPT_CHANGE"; + case BT_HCI_EVT_REMOTE_FEATURES: return "REMOTE_FEATURES"; + case BT_HCI_EVT_REMOTE_VERSION_INFO: return "REMOTE_VERSION_INFO"; + case BT_HCI_EVT_CMD_COMPLETE: return "CMD_COMPLETE"; + case BT_HCI_EVT_CMD_STATUS: return "CMD_STATUS"; + case BT_HCI_EVT_ROLE_CHANGE: return "ROLE_CHANGE"; + case BT_HCI_EVT_NUM_COMPLETED_PACKETS: return "NUM_COMPLETED_PACKETS"; + case BT_HCI_EVT_PIN_CODE_REQ: return "PIN_CODE_REQ"; + case BT_HCI_EVT_LINK_KEY_REQ: return "LINK_KEY_REQ"; + case BT_HCI_EVT_LINK_KEY_NOTIFY: return "LINK_KEY_NOTIFY"; + case BT_HCI_EVT_DATA_BUF_OVERFLOW: return "DATA_BUF_OVERFLOW"; + case BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI: return "INQUIRY_RESULT_WITH_RSSI"; + case BT_HCI_EVT_REMOTE_EXT_FEATURES: return "REMOTE_EXT_FEATURES"; + case BT_HCI_EVT_SYNC_CONN_COMPLETE: return "SYNC_CONN_COMPLETE"; + case BT_HCI_EVT_EXTENDED_INQUIRY_RESULT: return "EXTENDED_INQUIRY_RESULT"; + case BT_HCI_EVT_ENCRYPT_KEY_REFRESH_COMPLETE: return "ENCRYPT_KEY_REFRESH_COMPLETE"; + case BT_HCI_EVT_IO_CAPA_REQ: return "IO_CAPA_REQ"; + case BT_HCI_EVT_IO_CAPA_RESP: return "IO_CAPA_RESP"; + case BT_HCI_EVT_USER_CONFIRM_REQ: return "USER_CONFIRM_REQ"; + case BT_HCI_EVT_USER_PASSKEY_REQ: return "USER_PASSKEY_REQ"; + case BT_HCI_EVT_SSP_COMPLETE: return "SSP_COMPLETE"; + case BT_HCI_EVT_USER_PASSKEY_NOTIFY: return "USER_PASSKEY_NOTIFY"; + case BT_HCI_EVT_LE_META_EVENT: return "LE_META_EVENT"; + case BT_HCI_EVT_AUTH_PAYLOAD_TIMEOUT_EXP: return "AUTH_PAYLOAD_TIMEOUT_EXP"; + default: return ""; + } +} + +STATIC const char* hci_evt_le_name(uint8_t evt_le) { + switch (evt_le) { + case BT_HCI_EVT_LE_CONN_COMPLETE: return "LE_CONN_COMPLETE"; + case BT_HCI_EVT_LE_ADVERTISING_REPORT: return "LE_ADVERTISING_REPORT"; + case BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE: return "LE_CONN_UPDATE_COMPLETE"; + case BT_HCI_EVT_LE_LTK_REQUEST: return "LE_LTK_REQUEST"; + case BT_HCI_EVT_LE_CONN_PARAM_REQ: return "LE_CONN_PARAM_REQ"; + case BT_HCI_EVT_LE_DATA_LEN_CHANGE: return "LE_DATA_LEN_CHANGE"; + case BT_HCI_EVT_LE_P256_PUBLIC_KEY_COMPLETE: return "LE_P256_PUBLIC_KEY_COMPLETE"; + case BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE: return "LE_GENERATE_DHKEY_COMPLETE"; + case BT_HCI_EVT_LE_ENH_CONN_COMPLETE: return "LE_ENH_CONN_COMPLETE"; + case BT_HCI_EVT_LE_DIRECT_ADV_REPORT: return "LE_DIRECT_ADV_REPORT"; + case BT_HCI_EVT_LE_PHY_UPDATE_COMPLETE: return "LE_PHY_UPDATE_COMPLETE"; + case BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT: return "LE_EXT_ADVERTISING_REPORT"; + case BT_HCI_EVT_LE_PER_ADV_SYNC_ESTABLISHED: return "LE_PER_ADV_SYNC_ESTABLISHED"; + case BT_HCI_EVT_LE_PER_ADVERTISING_REPORT: return "LE_PER_ADVERTISING_REPORT"; + case BT_HCI_EVT_LE_PER_ADV_SYNC_LOST: return "LE_PER_ADV_SYNC_LOST"; + case BT_HCI_EVT_LE_SCAN_TIMEOUT: return "LE_SCAN_TIMEOUT"; + case BT_HCI_EVT_LE_ADV_SET_TERMINATED: return "LE_ADV_SET_TERMINATED"; + case BT_HCI_EVT_LE_SCAN_REQ_RECEIVED: return "LE_SCAN_REQ_RECEIVED"; + case BT_HCI_EVT_LE_CHAN_SEL_ALGO: return "LE_CHAN_SEL_ALGO"; + default: return ""; + } +} + +STATIC const char* hci_opcode_name(uint16_t opcode) { + switch (opcode) { + case BT_OP_NOP: return "NOP"; + case BT_HCI_OP_INQUIRY: return "INQUIRY"; + case BT_HCI_OP_INQUIRY_CANCEL: return "INQUIRY_CANCEL"; + case BT_HCI_OP_CONNECT: return "CONNECT"; + case BT_HCI_OP_DISCONNECT: return "DISCONNECT"; + case BT_HCI_OP_CONNECT_CANCEL: return "CONNECT_CANCEL"; + case BT_HCI_OP_ACCEPT_CONN_REQ: return "ACCEPT_CONN_REQ"; + case BT_HCI_OP_SETUP_SYNC_CONN: return "SETUP_SYNC_CONN"; + case BT_HCI_OP_ACCEPT_SYNC_CONN_REQ: return "ACCEPT_SYNC_CONN_REQ"; + case BT_HCI_OP_REJECT_CONN_REQ: return "REJECT_CONN_REQ"; + case BT_HCI_OP_LINK_KEY_REPLY: return "LINK_KEY_REPLY"; + case BT_HCI_OP_LINK_KEY_NEG_REPLY: return "LINK_KEY_NEG_REPLY"; + case BT_HCI_OP_PIN_CODE_REPLY: return "PIN_CODE_REPLY"; + case BT_HCI_OP_PIN_CODE_NEG_REPLY: return "PIN_CODE_NEG_REPLY"; + case BT_HCI_OP_AUTH_REQUESTED: return "AUTH_REQUESTED"; + case BT_HCI_OP_SET_CONN_ENCRYPT: return "SET_CONN_ENCRYPT"; + case BT_HCI_OP_REMOTE_NAME_REQUEST: return "REMOTE_NAME_REQUEST"; + case BT_HCI_OP_REMOTE_NAME_CANCEL: return "REMOTE_NAME_CANCEL"; + case BT_HCI_OP_READ_REMOTE_FEATURES: return "READ_REMOTE_FEATURES"; + case BT_HCI_OP_READ_REMOTE_EXT_FEATURES: return "READ_REMOTE_EXT_FEATURES"; + case BT_HCI_OP_READ_REMOTE_VERSION_INFO: return "READ_REMOTE_VERSION_INFO"; + case BT_HCI_OP_IO_CAPABILITY_REPLY: return "IO_CAPABILITY_REPLY"; + case BT_HCI_OP_USER_CONFIRM_REPLY: return "USER_CONFIRM_REPLY"; + case BT_HCI_OP_USER_CONFIRM_NEG_REPLY: return "USER_CONFIRM_NEG_REPLY"; + case BT_HCI_OP_USER_PASSKEY_REPLY: return "USER_PASSKEY_REPLY"; + case BT_HCI_OP_USER_PASSKEY_NEG_REPLY: return "USER_PASSKEY_NEG_REPLY"; + case BT_HCI_OP_IO_CAPABILITY_NEG_REPLY: return "IO_CAPABILITY_NEG_REPLY"; + case BT_HCI_OP_SET_EVENT_MASK: return "SET_EVENT_MASK"; + case BT_HCI_OP_RESET: return "RESET"; + case BT_HCI_OP_WRITE_LOCAL_NAME: return "WRITE_LOCAL_NAME"; + case BT_HCI_OP_WRITE_PAGE_TIMEOUT: return "WRITE_PAGE_TIMEOUT"; + case BT_HCI_OP_WRITE_SCAN_ENABLE: return "WRITE_SCAN_ENABLE"; + case BT_HCI_OP_READ_TX_POWER_LEVEL: return "READ_TX_POWER_LEVEL"; + case BT_HCI_OP_SET_CTL_TO_HOST_FLOW: return "SET_CTL_TO_HOST_FLOW"; + case BT_HCI_OP_HOST_BUFFER_SIZE: return "HOST_BUFFER_SIZE"; + case BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS: return "HOST_NUM_COMPLETED_PACKETS"; + case BT_HCI_OP_WRITE_INQUIRY_MODE: return "WRITE_INQUIRY_MODE"; + case BT_HCI_OP_WRITE_SSP_MODE: return "WRITE_SSP_MODE"; + case BT_HCI_OP_SET_EVENT_MASK_PAGE_2: return "SET_EVENT_MASK_PAGE_2"; + case BT_HCI_OP_LE_WRITE_LE_HOST_SUPP: return "LE_WRITE_LE_HOST_SUPP"; + case BT_HCI_OP_WRITE_SC_HOST_SUPP: return "WRITE_SC_HOST_SUPP"; + case BT_HCI_OP_READ_AUTH_PAYLOAD_TIMEOUT: return "READ_AUTH_PAYLOAD_TIMEOUT"; + case BT_HCI_OP_WRITE_AUTH_PAYLOAD_TIMEOUT: return "WRITE_AUTH_PAYLOAD_TIMEOUT"; + case BT_HCI_OP_READ_LOCAL_VERSION_INFO: return "READ_LOCAL_VERSION_INFO"; + case BT_HCI_OP_READ_SUPPORTED_COMMANDS: return "READ_SUPPORTED_COMMANDS"; + case BT_HCI_OP_READ_LOCAL_EXT_FEATURES: return "READ_LOCAL_EXT_FEATURES"; + case BT_HCI_OP_READ_LOCAL_FEATURES: return "READ_LOCAL_FEATURES"; + case BT_HCI_OP_READ_BUFFER_SIZE: return "READ_BUFFER_SIZE"; + case BT_HCI_OP_READ_BD_ADDR: return "READ_BD_ADDR"; + case BT_HCI_OP_READ_RSSI: return "READ_RSSI"; + case BT_HCI_OP_READ_ENCRYPTION_KEY_SIZE: return "READ_ENCRYPTION_KEY_SIZE"; + case BT_HCI_OP_LE_SET_EVENT_MASK: return "LE_SET_EVENT_MASK"; + case BT_HCI_OP_LE_READ_BUFFER_SIZE: return "LE_READ_BUFFER_SIZE"; + case BT_HCI_OP_LE_READ_LOCAL_FEATURES: return "LE_READ_LOCAL_FEATURES"; + case BT_HCI_OP_LE_SET_RANDOM_ADDRESS: return "LE_SET_RANDOM_ADDRESS"; + case BT_HCI_OP_LE_SET_ADV_PARAM: return "LE_SET_ADV_PARAM"; + case BT_HCI_OP_LE_READ_ADV_CHAN_TX_POWER: return "LE_READ_ADV_CHAN_TX_POWER"; + case BT_HCI_OP_LE_SET_ADV_DATA: return "LE_SET_ADV_DATA"; + case BT_HCI_OP_LE_SET_SCAN_RSP_DATA: return "LE_SET_SCAN_RSP_DATA"; + case BT_HCI_OP_LE_SET_ADV_ENABLE: return "LE_SET_ADV_ENABLE"; + case BT_HCI_OP_LE_SET_SCAN_PARAM: return "LE_SET_SCAN_PARAM"; + case BT_HCI_OP_LE_SET_SCAN_ENABLE: return "LE_SET_SCAN_ENABLE"; + case BT_HCI_OP_LE_CREATE_CONN: return "LE_CREATE_CONN"; + case BT_HCI_OP_LE_CREATE_CONN_CANCEL: return "LE_CREATE_CONN_CANCEL"; + case BT_HCI_OP_LE_READ_WL_SIZE: return "LE_READ_WL_SIZE"; + case BT_HCI_OP_LE_CLEAR_WL: return "LE_CLEAR_WL"; + case BT_HCI_OP_LE_ADD_DEV_TO_WL: return "LE_ADD_DEV_TO_WL"; + case BT_HCI_OP_LE_REM_DEV_FROM_WL: return "LE_REM_DEV_FROM_WL"; + case BT_HCI_OP_LE_CONN_UPDATE: return "LE_CONN_UPDATE"; + case BT_HCI_OP_LE_SET_HOST_CHAN_CLASSIF: return "LE_SET_HOST_CHAN_CLASSIF"; + case BT_HCI_OP_LE_READ_CHAN_MAP: return "LE_READ_CHAN_MAP"; + case BT_HCI_OP_LE_READ_REMOTE_FEATURES: return "LE_READ_REMOTE_FEATURES"; + case BT_HCI_OP_LE_ENCRYPT: return "LE_ENCRYPT"; + case BT_HCI_OP_LE_RAND: return "LE_RAND"; + case BT_HCI_OP_LE_START_ENCRYPTION: return "LE_START_ENCRYPTION"; + case BT_HCI_OP_LE_LTK_REQ_REPLY: return "LE_LTK_REQ_REPLY"; + case BT_HCI_OP_LE_LTK_REQ_NEG_REPLY: return "LE_LTK_REQ_NEG_REPLY"; + case BT_HCI_OP_LE_READ_SUPP_STATES: return "LE_READ_SUPP_STATES"; + case BT_HCI_OP_LE_RX_TEST: return "LE_RX_TEST"; + case BT_HCI_OP_LE_TX_TEST: return "LE_TX_TEST"; + case BT_HCI_OP_LE_TEST_END: return "LE_TEST_END"; + case BT_HCI_OP_LE_CONN_PARAM_REQ_REPLY: return "LE_CONN_PARAM_REQ_REPLY"; + case BT_HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY: return "LE_CONN_PARAM_REQ_NEG_REPLY"; + case BT_HCI_OP_LE_SET_DATA_LEN: return "LE_SET_DATA_LEN"; + case BT_HCI_OP_LE_READ_DEFAULT_DATA_LEN: return "LE_READ_DEFAULT_DATA_LEN"; + case BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN: return "LE_WRITE_DEFAULT_DATA_LEN"; + case BT_HCI_OP_LE_P256_PUBLIC_KEY: return "LE_P256_PUBLIC_KEY"; + case BT_HCI_OP_LE_GENERATE_DHKEY: return "LE_GENERATE_DHKEY"; + case BT_HCI_OP_LE_ADD_DEV_TO_RL: return "LE_ADD_DEV_TO_RL"; + case BT_HCI_OP_LE_REM_DEV_FROM_RL: return "LE_REM_DEV_FROM_RL"; + case BT_HCI_OP_LE_CLEAR_RL: return "LE_CLEAR_RL"; + case BT_HCI_OP_LE_READ_RL_SIZE: return "LE_READ_RL_SIZE"; + case BT_HCI_OP_LE_READ_PEER_RPA: return "LE_READ_PEER_RPA"; + case BT_HCI_OP_LE_READ_LOCAL_RPA: return "LE_READ_LOCAL_RPA"; + case BT_HCI_OP_LE_SET_ADDR_RES_ENABLE: return "LE_SET_ADDR_RES_ENABLE"; + case BT_HCI_OP_LE_SET_RPA_TIMEOUT: return "LE_SET_RPA_TIMEOUT"; + case BT_HCI_OP_LE_READ_MAX_DATA_LEN: return "LE_READ_MAX_DATA_LEN"; + case BT_HCI_OP_LE_READ_PHY: return "LE_READ_PHY"; + case BT_HCI_OP_LE_SET_DEFAULT_PHY: return "LE_SET_DEFAULT_PHY"; + case BT_HCI_OP_LE_SET_PHY: return "LE_SET_PHY"; + case BT_HCI_OP_LE_ENH_RX_TEST: return "LE_ENH_RX_TEST"; + case BT_HCI_OP_LE_ENH_TX_TEST: return "LE_ENH_TX_TEST"; + case BT_HCI_OP_LE_SET_ADV_SET_RANDOM_ADDR: return "LE_SET_ADV_SET_RANDOM_ADDR"; + case BT_HCI_OP_LE_SET_EXT_ADV_PARAM: return "LE_SET_EXT_ADV_PARAM"; + case BT_HCI_OP_LE_SET_EXT_ADV_DATA: return "LE_SET_EXT_ADV_DATA"; + case BT_HCI_OP_LE_SET_EXT_SCAN_RSP_DATA: return "LE_SET_EXT_SCAN_RSP_DATA"; + case BT_HCI_OP_LE_SET_EXT_ADV_ENABLE: return "LE_SET_EXT_ADV_ENABLE"; + case BT_HCI_OP_LE_READ_MAX_ADV_DATA_LEN: return "LE_READ_MAX_ADV_DATA_LEN"; + case BT_HCI_OP_LE_READ_NUM_ADV_SETS: return "LE_READ_NUM_ADV_SETS"; + case BT_HCI_OP_LE_REMOVE_ADV_SET: return "LE_REMOVE_ADV_SET"; + case BT_HCI_OP_CLEAR_ADV_SETS: return "CLEAR_ADV_SETS"; + case BT_HCI_OP_LE_SET_PER_ADV_PARAM: return "LE_SET_PER_ADV_PARAM"; + case BT_HCI_OP_LE_SET_PER_ADV_DATA: return "LE_SET_PER_ADV_DATA"; + case BT_HCI_OP_LE_SET_PER_ADV_ENABLE: return "LE_SET_PER_ADV_ENABLE"; + case BT_HCI_OP_LE_SET_EXT_SCAN_PARAM: return "LE_SET_EXT_SCAN_PARAM"; + case BT_HCI_OP_LE_SET_EXT_SCAN_ENABLE: return "LE_SET_EXT_SCAN_ENABLE"; + case BT_HCI_OP_LE_EXT_CREATE_CONN: return "LE_EXT_CREATE_CONN"; + case BT_HCI_OP_LE_PER_ADV_CREATE_SYNC: return "LE_PER_ADV_CREATE_SYNC"; + case BT_HCI_OP_LE_PER_ADV_CREATE_SYNC_CANCEL: return "LE_PER_ADV_CREATE_SYNC_CANCEL"; + case BT_HCI_OP_LE_PER_ADV_TERMINATE_SYNC: return "LE_PER_ADV_TERMINATE_SYNC"; + case BT_HCI_OP_LE_ADD_DEV_TO_PER_ADV_LIST: return "LE_ADD_DEV_TO_PER_ADV_LIST"; + case BT_HCI_OP_LE_REM_DEV_FROM_PER_ADV_LIST: return "LE_REM_DEV_FROM_PER_ADV_LIST"; + case BT_HCI_OP_LE_CLEAR_PER_ADV_LIST: return "LE_CLEAR_PER_ADV_LIST"; + case BT_HCI_OP_LE_READ_PER_ADV_LIST_SIZE: return "LE_READ_PER_ADV_LIST_SIZE"; + case BT_HCI_OP_LE_READ_TX_POWER: return "LE_READ_TX_POWER"; + case BT_HCI_OP_LE_READ_RF_PATH_COMP: return "LE_READ_RF_PATH_COMP"; + case BT_HCI_OP_LE_WRITE_RF_PATH_COMP: return "LE_WRITE_RF_PATH_COMP"; + case BT_HCI_OP_LE_SET_PRIVACY_MODE: return "LE_SET_PRIVACY_MODE"; + default: return ""; + } +} + + +STATIC void dump_cmd_pkt(bool tx, uint8_t pkt_len, uint8_t pkt_data[]) { + h4_hci_cmd_pkt_t *pkt = (h4_hci_cmd_pkt_t *) pkt_data; + mp_printf(&mp_plat_print, + "%s HCI COMMAND (%x) op: %s (%04x), len: %d, data: ", + tx ? "TX->" : "RX<-", + pkt->pkt_type, + hci_opcode_name(pkt->opcode), pkt->opcode, pkt->param_len); + for (size_t i = 0; i < pkt->param_len; i++) { + mp_printf(&mp_plat_print, "%02x ", pkt->params[i]); + } + if (pkt_len != sizeof(h4_hci_cmd_pkt_t) + pkt->param_len) { + mp_printf(&mp_plat_print, " LENGTH MISMATCH, pkt_len: %d", pkt_len); + } + mp_printf(&mp_plat_print, "\n"); +} + +STATIC void dump_acl_pkt(bool tx, uint8_t pkt_len, uint8_t pkt_data[]) { + h4_hci_acl_pkt_t *pkt = (h4_hci_acl_pkt_t *) pkt_data; + acl_data_t *acl = (acl_data_t *) pkt->data; + + mp_printf(&mp_plat_print, + "%s HCI ACLDATA (%x) ", + tx ? "TX->" : "RX<-", pkt->pkt_type); + + if (pkt->pb != ACL_DATA_PB_MIDDLE && acl->cid == BT_L2CAP_CID_ATT) { + // This is the start of a fragmented acl_data packet or is a full packet, + // and is an ATT protocol packet. + mp_printf(&mp_plat_print, "att: %s (%02x), ", att_opcode_name(acl->acl_data[0]), acl->acl_data[0]); + } + + mp_printf(&mp_plat_print, + "handle: %04x, pb: %d, bc: %d, data_len: %d, ", + pkt->handle, pkt->pb, pkt->bc, pkt->data_len); + + if (pkt->pb != ACL_DATA_PB_MIDDLE) { + // This is the start of a fragmented acl_data packet or is a full packet. + mp_printf(&mp_plat_print, + "acl data_len: %d, cid: %04x, data: ", + acl->acl_data_len, acl->cid); + for (size_t i = 0; i < acl->acl_data_len; i++) { + mp_printf(&mp_plat_print, "%02x ", acl->acl_data[i]); + } + } else { + for (size_t i = 0; i < pkt->data_len; i++) { + mp_printf(&mp_plat_print, "more data: %02x ", pkt->data[i]); + } + } + + if (pkt_len != sizeof(h4_hci_acl_pkt_t) + pkt->data_len) { + mp_printf(&mp_plat_print, " LENGTH MISMATCH, pkt_len: %d", pkt_len); + } + mp_printf(&mp_plat_print, "\n"); +} + +STATIC void dump_evt_pkt(bool tx, uint8_t pkt_len, uint8_t pkt_data[]) { + h4_hci_evt_pkt_t *pkt = (h4_hci_evt_pkt_t *) pkt_data; + mp_printf(&mp_plat_print, + "%s HCI EVENT (%x) evt: %s (%02x), param_len: %d, data: ", + tx ? "TX->" : "RX<-", + pkt->pkt_type, + pkt->evt == BT_HCI_EVT_LE_META_EVENT + ? hci_evt_le_name(pkt->params[0]) + : hci_evt_name(pkt->evt), + pkt->evt, pkt->param_len); + for (size_t i = 0; i < pkt->param_len; i++) { + mp_printf(&mp_plat_print, "%02x ", pkt->params[i]); + } + if (pkt_len != sizeof(h4_hci_evt_pkt_t) + pkt->param_len) { + mp_printf(&mp_plat_print, " LENGTH MISMATCH, pkt_len: %d", pkt_len); + } + mp_printf(&mp_plat_print, "\n"); +} diff --git a/devices/ble_hci/common-hal/_bleio/hci_include/NOTE.txt b/devices/ble_hci/common-hal/_bleio/hci_include/NOTE.txt new file mode 100644 index 0000000000..ac34c815ce --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/hci_include/NOTE.txt @@ -0,0 +1,2 @@ +The HCI-related include files here were copied from the Zephyr project, from this commit: +https://github.com/zephyrproject-rtos/zephyr/tree/0a87f9359edf1ec1c169626df3e19c2b4a4e9646/include/bluetooth diff --git a/devices/ble_hci/common-hal/_bleio/hci_include/addr.h b/devices/ble_hci/common-hal/_bleio/hci_include/addr.h new file mode 100644 index 0000000000..fd74a95e8d --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/hci_include/addr.h @@ -0,0 +1,101 @@ +// CircuitPython: Adapted from Zephyer include files. +/** @file + * @brief Bluetooth device address definitions and utilities. + */ + +/* + * Copyright (c) 2019 Nordic Semiconductor ASA + * Copyright 2020 Dan Halbert for Adafruit Industries + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_BLUETOOTH_ADDR_H_ +#define ZEPHYR_INCLUDE_BLUETOOTH_ADDR_H_ + +#include +#include + +/** + * @brief Bluetooth device address definitions and utilities. + * @defgroup bt_addr Device Address + * @ingroup bluetooth + * @{ + */ + +#define BT_ADDR_LE_PUBLIC 0x00 +#define BT_ADDR_LE_RANDOM 0x01 +#define BT_ADDR_LE_PUBLIC_ID 0x02 +#define BT_ADDR_LE_RANDOM_ID 0x03 + +/** Bluetooth Device Address */ +typedef struct { + uint8_t val[6]; +} bt_addr_t; + +/** Bluetooth LE Device Address */ +typedef struct { + uint8_t type; + bt_addr_t a; +} bt_addr_le_t; + +#define BT_ADDR_ANY ((bt_addr_t[]) { { { 0, 0, 0, 0, 0, 0 } } }) +#define BT_ADDR_NONE ((bt_addr_t[]) { { \ + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } } }) +#define BT_ADDR_LE_ANY ((bt_addr_le_t[]) { { 0, { { 0, 0, 0, 0, 0, 0 } } } }) +#define BT_ADDR_LE_NONE ((bt_addr_le_t[]) { { 0, \ + { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } } } }) + +static inline int bt_addr_cmp(const bt_addr_t *a, const bt_addr_t *b) +{ + return memcmp(a, b, sizeof(*a)); +} + +static inline int bt_addr_le_cmp(const bt_addr_le_t *a, const bt_addr_le_t *b) +{ + return memcmp(a, b, sizeof(*a)); +} + +static inline void bt_addr_copy(bt_addr_t *dst, const bt_addr_t *src) +{ + memcpy(dst, src, sizeof(*dst)); +} + +static inline void bt_addr_le_copy(bt_addr_le_t *dst, const bt_addr_le_t *src) +{ + memcpy(dst, src, sizeof(*dst)); +} + +#define BT_ADDR_IS_RPA(a) (((a)->val[5] & 0xc0) == 0x40) +#define BT_ADDR_IS_NRPA(a) (((a)->val[5] & 0xc0) == 0x00) +#define BT_ADDR_IS_STATIC(a) (((a)->val[5] & 0xc0) == 0xc0) + +#define BT_ADDR_SET_RPA(a) ((a)->val[5] = (((a)->val[5] & 0x3f) | 0x40)) +#define BT_ADDR_SET_NRPA(a) ((a)->val[5] &= 0x3f) +#define BT_ADDR_SET_STATIC(a) ((a)->val[5] |= 0xc0) + +int bt_addr_le_create_nrpa(bt_addr_le_t *addr); +int bt_addr_le_create_static(bt_addr_le_t *addr); + +static inline bool bt_addr_le_is_rpa(const bt_addr_le_t *addr) +{ + if (addr->type != BT_ADDR_LE_RANDOM) { + return false; + } + + return BT_ADDR_IS_RPA(&addr->a); +} + +static inline bool bt_addr_le_is_identity(const bt_addr_le_t *addr) +{ + if (addr->type == BT_ADDR_LE_PUBLIC) { + return true; + } + + return BT_ADDR_IS_STATIC(&addr->a); +} + +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_BLUETOOTH_ADDR_H_ */ diff --git a/devices/ble_hci/common-hal/_bleio/hci_include/att.h b/devices/ble_hci/common-hal/_bleio/hci_include/att.h new file mode 100644 index 0000000000..8117a48f45 --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/hci_include/att.h @@ -0,0 +1,41 @@ +// CircuitPython: Adapted from Zephyr include file. +/** @file + * @brief Attribute Protocol handling. + */ + +/* + * Copyright (c) 2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_BLUETOOTH_ATT_H_ +#define ZEPHYR_INCLUDE_BLUETOOTH_ATT_H_ + +/* Error codes for Error response PDU */ +#define BT_ATT_ERR_INVALID_HANDLE 0x01 +#define BT_ATT_ERR_READ_NOT_PERMITTED 0x02 +#define BT_ATT_ERR_WRITE_NOT_PERMITTED 0x03 +#define BT_ATT_ERR_INVALID_PDU 0x04 +#define BT_ATT_ERR_AUTHENTICATION 0x05 +#define BT_ATT_ERR_NOT_SUPPORTED 0x06 +#define BT_ATT_ERR_INVALID_OFFSET 0x07 +#define BT_ATT_ERR_AUTHORIZATION 0x08 +#define BT_ATT_ERR_PREPARE_QUEUE_FULL 0x09 +#define BT_ATT_ERR_ATTRIBUTE_NOT_FOUND 0x0a +#define BT_ATT_ERR_ATTRIBUTE_NOT_LONG 0x0b +#define BT_ATT_ERR_ENCRYPTION_KEY_SIZE 0x0c +#define BT_ATT_ERR_INVALID_ATTRIBUTE_LEN 0x0d +#define BT_ATT_ERR_UNLIKELY 0x0e +#define BT_ATT_ERR_INSUFFICIENT_ENCRYPTION 0x0f +#define BT_ATT_ERR_UNSUPPORTED_GROUP_TYPE 0x10 +#define BT_ATT_ERR_INSUFFICIENT_RESOURCES 0x11 +#define BT_ATT_ERR_DB_OUT_OF_SYNC 0x12 +#define BT_ATT_ERR_VALUE_NOT_ALLOWED 0x13 + +/* Common Profile Error Codes (from CSS) */ +#define BT_ATT_ERR_WRITE_REQ_REJECTED 0xfc +#define BT_ATT_ERR_CCC_IMPROPER_CONF 0xfd +#define BT_ATT_ERR_PROCEDURE_IN_PROGRESS 0xfe +#define BT_ATT_ERR_OUT_OF_RANGE 0xff + +#endif /* ZEPHYR_INCLUDE_BLUETOOTH_ATT_H_ */ diff --git a/devices/ble_hci/common-hal/_bleio/hci_include/att_internal.h b/devices/ble_hci/common-hal/_bleio/hci_include/att_internal.h new file mode 100644 index 0000000000..1c75275daa --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/hci_include/att_internal.h @@ -0,0 +1,266 @@ +// CircuitPython: Adapted from Zephyr include file. + +/* att_internal.h - Attribute protocol handling */ + +/* + * Copyright (c) 2015-2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#include +// for __packed +#include + +#define BT_EATT_PSM 0x27 +#define BT_ATT_DEFAULT_LE_MTU 23 +#define BT_ATT_TIMEOUT K_SECONDS(30) + +//FIX #if BT_L2CAP_RX_MTU < CONFIG_BT_L2CAP_TX_MTU +// #define BT_ATT_MTU BT_L2CAP_RX_MTU +// #else +// #define BT_ATT_MTU CONFIG_BT_L2CAP_TX_MTU +// #endif + +struct bt_att_hdr { + uint8_t code; +} __packed; + +#define BT_ATT_OP_ERROR_RSP 0x01 +struct bt_att_error_rsp { + uint8_t request; + uint16_t handle; + uint8_t error; +} __packed; + +#define BT_ATT_OP_MTU_REQ 0x02 +struct bt_att_exchange_mtu_req { + uint16_t mtu; +} __packed; + +#define BT_ATT_OP_MTU_RSP 0x03 +struct bt_att_exchange_mtu_rsp { + uint16_t mtu; +} __packed; + +/* Find Information Request */ +#define BT_ATT_OP_FIND_INFO_REQ 0x04 +struct bt_att_find_info_req { + uint16_t start_handle; + uint16_t end_handle; +} __packed; + +/* Format field values for BT_ATT_OP_FIND_INFO_RSP */ +#define BT_ATT_INFO_16 0x01 +#define BT_ATT_INFO_128 0x02 + +struct bt_att_info_16 { + uint16_t handle; + uint16_t uuid; +} __packed; + +struct bt_att_info_128 { + uint16_t handle; + uint8_t uuid[16]; +} __packed; + +/* Find Information Response */ +#define BT_ATT_OP_FIND_INFO_RSP 0x05 +struct bt_att_find_info_rsp { + uint8_t format; + uint8_t info[0]; +} __packed; + +/* Find By Type Value Request */ +#define BT_ATT_OP_FIND_TYPE_REQ 0x06 +struct bt_att_find_type_req { + uint16_t start_handle; + uint16_t end_handle; + uint16_t type; + uint8_t value[0]; +} __packed; + +struct bt_att_handle_group { + uint16_t start_handle; + uint16_t end_handle; +} __packed; + +/* Find By Type Value Response */ +#define BT_ATT_OP_FIND_TYPE_RSP 0x07 +struct bt_att_find_type_rsp { + struct bt_att_handle_group list[0]; +} __packed; + +/* Read By Type Request */ +#define BT_ATT_OP_READ_TYPE_REQ 0x08 +struct bt_att_read_type_req { + uint16_t start_handle; + uint16_t end_handle; + uint8_t uuid[0]; +} __packed; + +struct bt_att_data { + uint16_t handle; + uint8_t value[0]; +} __packed; + +/* Read By Type Response */ +#define BT_ATT_OP_READ_TYPE_RSP 0x09 +struct bt_att_read_type_rsp { + uint8_t len; + struct bt_att_data data[0]; +} __packed; + +/* Read Request */ +#define BT_ATT_OP_READ_REQ 0x0a +struct bt_att_read_req { + uint16_t handle; +} __packed; + +/* Read Response */ +#define BT_ATT_OP_READ_RSP 0x0b +struct bt_att_read_rsp { + uint8_t value[0]; +} __packed; + +/* Read Blob Request */ +#define BT_ATT_OP_READ_BLOB_REQ 0x0c +struct bt_att_read_blob_req { + uint16_t handle; + uint16_t offset; +} __packed; + +/* Read Blob Response */ +#define BT_ATT_OP_READ_BLOB_RSP 0x0d +struct bt_att_read_blob_rsp { + uint8_t value[0]; +} __packed; + +/* Read Multiple Request */ +#define BT_ATT_READ_MULT_MIN_LEN_REQ 0x04 + +#define BT_ATT_OP_READ_MULT_REQ 0x0e +struct bt_att_read_mult_req { + uint16_t handles[0]; +} __packed; + +/* Read Multiple Respose */ +#define BT_ATT_OP_READ_MULT_RSP 0x0f +struct bt_att_read_mult_rsp { + uint8_t value[0]; +} __packed; + +/* Read by Group Type Request */ +#define BT_ATT_OP_READ_GROUP_REQ 0x10 +struct bt_att_read_group_req { + uint16_t start_handle; + uint16_t end_handle; + uint8_t uuid[0]; +} __packed; + +struct bt_att_group_data { + uint16_t start_handle; + uint16_t end_handle; + uint8_t value[0]; +} __packed; + +/* Read by Group Type Response */ +#define BT_ATT_OP_READ_GROUP_RSP 0x11 +struct bt_att_read_group_rsp { + uint8_t len; + struct bt_att_group_data data[0]; +} __packed; + +/* Write Request */ +#define BT_ATT_OP_WRITE_REQ 0x12 +struct bt_att_write_req { + uint16_t handle; + uint8_t value[0]; +} __packed; + +/* Write Response */ +#define BT_ATT_OP_WRITE_RSP 0x13 + +/* Prepare Write Request */ +#define BT_ATT_OP_PREPARE_WRITE_REQ 0x16 +struct bt_att_prepare_write_req { + uint16_t handle; + uint16_t offset; + uint8_t value[0]; +} __packed; + +/* Prepare Write Respond */ +#define BT_ATT_OP_PREPARE_WRITE_RSP 0x17 +struct bt_att_prepare_write_rsp { + uint16_t handle; + uint16_t offset; + uint8_t value[0]; +} __packed; + +/* Execute Write Request */ +#define BT_ATT_FLAG_CANCEL 0x00 +#define BT_ATT_FLAG_EXEC 0x01 + +#define BT_ATT_OP_EXEC_WRITE_REQ 0x18 +struct bt_att_exec_write_req { + uint8_t flags; +} __packed; + +/* Execute Write Response */ +#define BT_ATT_OP_EXEC_WRITE_RSP 0x19 + +/* Handle Value Notification */ +#define BT_ATT_OP_NOTIFY 0x1b +struct bt_att_notify { + uint16_t handle; + uint8_t value[0]; +} __packed; + +/* Handle Value Indication */ +#define BT_ATT_OP_INDICATE 0x1d +struct bt_att_indicate { + uint16_t handle; + uint8_t value[0]; +} __packed; + +/* Handle Value Confirm */ +#define BT_ATT_OP_CONFIRM 0x1e + +struct bt_att_signature { + uint8_t value[12]; +} __packed; + +#define BT_ATT_OP_READ_MULT_VL_REQ 0x20 +struct bt_att_read_mult_vl_req { + uint16_t handles[0]; +} __packed; + +/* Read Multiple Respose */ +#define BT_ATT_OP_READ_MULT_VL_RSP 0x21 +struct bt_att_read_mult_vl_rsp { + uint16_t len; + uint8_t value[0]; +} __packed; + +/* Handle Multiple Value Notification */ +#define BT_ATT_OP_NOTIFY_MULT 0x23 +struct bt_att_notify_mult { + uint16_t handle; + uint16_t len; + uint8_t value[0]; +} __packed; + +/* Write Command */ +#define BT_ATT_OP_WRITE_CMD 0x52 +struct bt_att_write_cmd { + uint16_t handle; + uint8_t value[0]; +} __packed; + +/* Signed Write Command */ +#define BT_ATT_OP_SIGNED_WRITE_CMD 0xd2 +struct bt_att_signed_write_cmd { + uint16_t handle; + uint8_t value[0]; +} __packed; diff --git a/devices/ble_hci/common-hal/_bleio/hci_include/hci.h b/devices/ble_hci/common-hal/_bleio/hci_include/hci.h new file mode 100644 index 0000000000..6c3a2b5bd0 --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/hci_include/hci.h @@ -0,0 +1,1767 @@ +// CircuitPython: Adapted from Zephyr include file. + +/* hci.h - Bluetooth Host Control Interface definitions */ + +/* + * Copyright 2020 Dan Halbert for Adafruit Industries + * Copyright (c) 2015-2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_BLUETOOTH_HCI_H_ +#define ZEPHYR_INCLUDE_BLUETOOTH_HCI_H_ + +#include +#include +#include "addr.h" + +#define BIT(n) (1UL << (n)) + +/* Special own address types for LL privacy (used in adv & scan parameters) */ +#define BT_HCI_OWN_ADDR_RPA_OR_PUBLIC 0x02 +#define BT_HCI_OWN_ADDR_RPA_OR_RANDOM 0x03 +#define BT_HCI_OWN_ADDR_RPA_MASK 0x02 + +#define BT_HCI_PEER_ADDR_RPA_UNRESOLVED 0xfe +#define BT_HCI_PEER_ADDR_ANONYMOUS 0xff + +#define BT_ENC_KEY_SIZE_MIN 0x07 +#define BT_ENC_KEY_SIZE_MAX 0x10 + +struct bt_hci_evt_hdr { + uint8_t evt; + uint8_t len; +} __packed; +#define BT_HCI_EVT_HDR_SIZE 2 + +#define BT_ACL_START_NO_FLUSH 0x00 +#define BT_ACL_CONT 0x01 +#define BT_ACL_START 0x02 +#define BT_ACL_COMPLETE 0x03 + +#define BT_ACL_POINT_TO_POINT 0x00 +#define BT_ACL_BROADCAST 0x01 + +#define bt_acl_handle(h) ((h) & BIT_MASK(12)) +#define bt_acl_flags(h) ((h) >> 12) +#define bt_acl_flags_pb(f) ((f) & BIT_MASK(2)) +#define bt_acl_flags_bc(f) ((f) >> 2) +#define bt_acl_handle_pack(h, f) ((h) | ((f) << 12)) + +struct bt_hci_acl_hdr { + uint16_t handle; + uint16_t len; +} __packed; +#define BT_HCI_ACL_HDR_SIZE 4 + +struct bt_hci_cmd_hdr { + uint16_t opcode; + uint8_t param_len; +} __packed; +#define BT_HCI_CMD_HDR_SIZE 3 + +/* Supported Commands */ +#define BT_CMD_TEST(cmd, octet, bit) (cmd[octet] & BIT(bit)) +#define BT_CMD_LE_STATES(cmd) BT_CMD_TEST(cmd, 28, 3) + +#define BT_FEAT_TEST(feat, page, octet, bit) (feat[page][octet] & BIT(bit)) + +#define BT_FEAT_BREDR(feat) !BT_FEAT_TEST(feat, 0, 4, 5) +#define BT_FEAT_LE(feat) BT_FEAT_TEST(feat, 0, 4, 6) +#define BT_FEAT_EXT_FEATURES(feat) BT_FEAT_TEST(feat, 0, 7, 7) +#define BT_FEAT_HOST_SSP(feat) BT_FEAT_TEST(feat, 1, 0, 0) +#define BT_FEAT_SC(feat) BT_FEAT_TEST(feat, 2, 1, 0) + +#define BT_FEAT_LMP_ESCO_CAPABLE(feat) BT_FEAT_TEST(feat, 0, 3, 7) +#define BT_FEAT_HV2_PKT(feat) BT_FEAT_TEST(feat, 0, 1, 4) +#define BT_FEAT_HV3_PKT(feat) BT_FEAT_TEST(feat, 0, 1, 5) +#define BT_FEAT_EV4_PKT(feat) BT_FEAT_TEST(feat, 0, 4, 0) +#define BT_FEAT_EV5_PKT(feat) BT_FEAT_TEST(feat, 0, 4, 1) +#define BT_FEAT_2EV3_PKT(feat) BT_FEAT_TEST(feat, 0, 5, 5) +#define BT_FEAT_3EV3_PKT(feat) BT_FEAT_TEST(feat, 0, 5, 6) +#define BT_FEAT_3SLOT_PKT(feat) BT_FEAT_TEST(feat, 0, 5, 7) + +/* LE features */ +#define BT_LE_FEAT_BIT_ENC 0 +#define BT_LE_FEAT_BIT_CONN_PARAM_REQ 1 +#define BT_LE_FEAT_BIT_EXT_REJ_IND 2 +#define BT_LE_FEAT_BIT_SLAVE_FEAT_REQ 3 +#define BT_LE_FEAT_BIT_PING 4 +#define BT_LE_FEAT_BIT_DLE 5 +#define BT_LE_FEAT_BIT_PRIVACY 6 +#define BT_LE_FEAT_BIT_EXT_SCAN 7 +#define BT_LE_FEAT_BIT_PHY_2M 8 +#define BT_LE_FEAT_BIT_SMI_TX 9 +#define BT_LE_FEAT_BIT_SMI_RX 10 +#define BT_LE_FEAT_BIT_PHY_CODED 11 +#define BT_LE_FEAT_BIT_EXT_ADV 12 +#define BT_LE_FEAT_BIT_PER_ADV 13 +#define BT_LE_FEAT_BIT_CHAN_SEL_ALGO_2 14 +#define BT_LE_FEAT_BIT_PWR_CLASS_1 15 +#define BT_LE_FEAT_BIT_MIN_USED_CHAN_PROC 16 +#define BT_LE_FEAT_BIT_CONN_CTE_REQ 17 +#define BT_LE_FEAT_BIT_CONN_CTE_RESP 18 +#define BT_LE_FEAT_BIT_CONNECTIONLESS_CTE_TX 19 +#define BT_LE_FEAT_BIT_CONNECTIONLESS_CTE_RX 20 +#define BT_LE_FEAT_BIT_ANT_SWITCH_TX_AOD 21 +#define BT_LE_FEAT_BIT_ANT_SWITCH_RX_AOA 22 +#define BT_LE_FEAT_BIT_RX_CTE 23 +#define BT_LE_FEAT_BIT_PERIODIC_SYNC_XFER_SEND 24 +#define BT_LE_FEAT_BIT_PERIODIC_SYNC_XFER_RECV 25 +#define BT_LE_FEAT_BIT_SCA_UPDATE 26 +#define BT_LE_FEAT_BIT_REMOTE_PUB_KEY_VALIDATE 27 +#define BT_LE_FEAT_BIT_CIS_MASTER 28 +#define BT_LE_FEAT_BIT_CIS_SLAVE 29 +#define BT_LE_FEAT_BIT_ISO_BROADCASTER 30 +#define BT_LE_FEAT_BIT_SYNC_RECEIVER 31 +#define BT_LE_FEAT_BIT_ISO_CHANNELS 32 +#define BT_LE_FEAT_BIT_PWR_CTRL_REQ 33 +#define BT_LE_FEAT_BIT_PWR_CHG_IND 34 +#define BT_LE_FEAT_BIT_PATH_LOSS_MONITOR 35 + +#define BT_LE_FEAT_TEST(feat, n) (feat[(n) >> 3] & \ + BIT((n) & 7)) + +#define BT_FEAT_LE_ENCR(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_ENC) +#define BT_FEAT_LE_CONN_PARAM_REQ_PROC(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_CONN_PARAM_REQ) +#define BT_FEAT_LE_SLAVE_FEATURE_XCHG(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_SLAVE_FEAT_REQ) +#define BT_FEAT_LE_DLE(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_DLE) +#define BT_FEAT_LE_PHY_2M(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_PHY_2M) +#define BT_FEAT_LE_PHY_CODED(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_PHY_CODED) +#define BT_FEAT_LE_PRIVACY(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_PRIVACY) +#define BT_FEAT_LE_EXT_ADV(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_EXT_ADV) + +/* LE States */ +#define BT_LE_STATES_SLAVE_CONN_ADV(states) (states & 0x0000004000000000) + +/* Bonding/authentication types */ +#define BT_HCI_NO_BONDING 0x00 +#define BT_HCI_NO_BONDING_MITM 0x01 +#define BT_HCI_DEDICATED_BONDING 0x02 +#define BT_HCI_DEDICATED_BONDING_MITM 0x03 +#define BT_HCI_GENERAL_BONDING 0x04 +#define BT_HCI_GENERAL_BONDING_MITM 0x05 + +/* + * MITM protection is enabled in SSP authentication requirements octet when + * LSB bit is set. + */ +#define BT_MITM 0x01 + +/* I/O capabilities */ +#define BT_IO_DISPLAY_ONLY 0x00 +#define BT_IO_DISPLAY_YESNO 0x01 +#define BT_IO_KEYBOARD_ONLY 0x02 +#define BT_IO_NO_INPUT_OUTPUT 0x03 + +/* SCO packet types */ +#define HCI_PKT_TYPE_HV1 0x0020 +#define HCI_PKT_TYPE_HV2 0x0040 +#define HCI_PKT_TYPE_HV3 0x0080 + +/* eSCO packet types */ +#define HCI_PKT_TYPE_ESCO_HV1 0x0001 +#define HCI_PKT_TYPE_ESCO_HV2 0x0002 +#define HCI_PKT_TYPE_ESCO_HV3 0x0004 +#define HCI_PKT_TYPE_ESCO_EV3 0x0008 +#define HCI_PKT_TYPE_ESCO_EV4 0x0010 +#define HCI_PKT_TYPE_ESCO_EV5 0x0020 +#define HCI_PKT_TYPE_ESCO_2EV3 0x0040 +#define HCI_PKT_TYPE_ESCO_3EV3 0x0080 +#define HCI_PKT_TYPE_ESCO_2EV5 0x0100 +#define HCI_PKT_TYPE_ESCO_3EV5 0x0200 + + +#define ESCO_PKT_MASK (HCI_PKT_TYPE_ESCO_HV1 | \ + HCI_PKT_TYPE_ESCO_HV2 | \ + HCI_PKT_TYPE_ESCO_HV3) +#define SCO_PKT_MASK (HCI_PKT_TYPE_HV1 | \ + HCI_PKT_TYPE_HV2 | \ + HCI_PKT_TYPE_HV3) +#define EDR_ESCO_PKT_MASK (HCI_PKT_TYPE_ESCO_2EV3 | \ + HCI_PKT_TYPE_ESCO_3EV3 | \ + HCI_PKT_TYPE_ESCO_2EV5 | \ + HCI_PKT_TYPE_ESCO_3EV5) + +/* HCI BR/EDR link types */ +#define BT_HCI_SCO 0x00 +#define BT_HCI_ACL 0x01 +#define BT_HCI_ESCO 0x02 + +/* OpCode Group Fields */ +#define BT_OGF_LINK_CTRL 0x01 +#define BT_OGF_BASEBAND 0x03 +#define BT_OGF_INFO 0x04 +#define BT_OGF_STATUS 0x05 +#define BT_OGF_LE 0x08 +#define BT_OGF_VS 0x3f + +/* Construct OpCode from OGF and OCF */ +#define BT_OP(ogf, ocf) ((ocf) | ((ogf) << 10)) + +/* Invalid opcode */ +#define BT_OP_NOP 0x0000 + +/* Obtain OGF from OpCode */ +#define BT_OGF(opcode) (((opcode) >> 10) & BIT_MASK(6)) +/* Obtain OCF from OpCode */ +#define BT_OCF(opcode) ((opcode) & BIT_MASK(10)) + +#define BT_HCI_OP_INQUIRY BT_OP(BT_OGF_LINK_CTRL, 0x0001) +struct bt_hci_op_inquiry { + uint8_t lap[3]; + uint8_t length; + uint8_t num_rsp; +} __packed; + +#define BT_HCI_OP_INQUIRY_CANCEL BT_OP(BT_OGF_LINK_CTRL, 0x0002) + +#define BT_HCI_OP_CONNECT BT_OP(BT_OGF_LINK_CTRL, 0x0005) +struct bt_hci_cp_connect { + bt_addr_t bdaddr; + uint16_t packet_type; + uint8_t pscan_rep_mode; + uint8_t reserved; + uint16_t clock_offset; + uint8_t allow_role_switch; +} __packed; + +#define BT_HCI_OP_DISCONNECT BT_OP(BT_OGF_LINK_CTRL, 0x0006) +struct bt_hci_cp_disconnect { + uint16_t handle; + uint8_t reason; +} __packed; + +#define BT_HCI_OP_CONNECT_CANCEL BT_OP(BT_OGF_LINK_CTRL, 0x0008) +struct bt_hci_cp_connect_cancel { + bt_addr_t bdaddr; +} __packed; +struct bt_hci_rp_connect_cancel { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_ACCEPT_CONN_REQ BT_OP(BT_OGF_LINK_CTRL, 0x0009) +struct bt_hci_cp_accept_conn_req { + bt_addr_t bdaddr; + uint8_t role; +} __packed; + +#define BT_HCI_OP_SETUP_SYNC_CONN BT_OP(BT_OGF_LINK_CTRL, 0x0028) +struct bt_hci_cp_setup_sync_conn { + uint16_t handle; + uint32_t tx_bandwidth; + uint32_t rx_bandwidth; + uint16_t max_latency; + uint16_t content_format; + uint8_t retrans_effort; + uint16_t pkt_type; +} __packed; + +#define BT_HCI_OP_ACCEPT_SYNC_CONN_REQ BT_OP(BT_OGF_LINK_CTRL, 0x0029) +struct bt_hci_cp_accept_sync_conn_req { + bt_addr_t bdaddr; + uint32_t tx_bandwidth; + uint32_t rx_bandwidth; + uint16_t max_latency; + uint16_t content_format; + uint8_t retrans_effort; + uint16_t pkt_type; +} __packed; + +#define BT_HCI_OP_REJECT_CONN_REQ BT_OP(BT_OGF_LINK_CTRL, 0x000a) +struct bt_hci_cp_reject_conn_req { + bt_addr_t bdaddr; + uint8_t reason; +} __packed; + +#define BT_HCI_OP_LINK_KEY_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x000b) +struct bt_hci_cp_link_key_reply { + bt_addr_t bdaddr; + uint8_t link_key[16]; +} __packed; + +#define BT_HCI_OP_LINK_KEY_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x000c) +struct bt_hci_cp_link_key_neg_reply { + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_PIN_CODE_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x000d) +struct bt_hci_cp_pin_code_reply { + bt_addr_t bdaddr; + uint8_t pin_len; + uint8_t pin_code[16]; +} __packed; +struct bt_hci_rp_pin_code_reply { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_PIN_CODE_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x000e) +struct bt_hci_cp_pin_code_neg_reply { + bt_addr_t bdaddr; +} __packed; +struct bt_hci_rp_pin_code_neg_reply { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_AUTH_REQUESTED BT_OP(BT_OGF_LINK_CTRL, 0x0011) +struct bt_hci_cp_auth_requested { + uint16_t handle; +} __packed; + +#define BT_HCI_OP_SET_CONN_ENCRYPT BT_OP(BT_OGF_LINK_CTRL, 0x0013) +struct bt_hci_cp_set_conn_encrypt { + uint16_t handle; + uint8_t encrypt; +} __packed; + +#define BT_HCI_OP_REMOTE_NAME_REQUEST BT_OP(BT_OGF_LINK_CTRL, 0x0019) +struct bt_hci_cp_remote_name_request { + bt_addr_t bdaddr; + uint8_t pscan_rep_mode; + uint8_t reserved; + uint16_t clock_offset; +} __packed; + +#define BT_HCI_OP_REMOTE_NAME_CANCEL BT_OP(BT_OGF_LINK_CTRL, 0x001a) +struct bt_hci_cp_remote_name_cancel { + bt_addr_t bdaddr; +} __packed; +struct bt_hci_rp_remote_name_cancel { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_READ_REMOTE_FEATURES BT_OP(BT_OGF_LINK_CTRL, 0x001b) +struct bt_hci_cp_read_remote_features { + uint16_t handle; +} __packed; + +#define BT_HCI_OP_READ_REMOTE_EXT_FEATURES BT_OP(BT_OGF_LINK_CTRL, 0x001c) +struct bt_hci_cp_read_remote_ext_features { + uint16_t handle; + uint8_t page; +} __packed; + +#define BT_HCI_OP_READ_REMOTE_VERSION_INFO BT_OP(BT_OGF_LINK_CTRL, 0x001d) +struct bt_hci_cp_read_remote_version_info { + uint16_t handle; +} __packed; + +#define BT_HCI_OP_IO_CAPABILITY_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x002b) +struct bt_hci_cp_io_capability_reply { + bt_addr_t bdaddr; + uint8_t capability; + uint8_t oob_data; + uint8_t authentication; +} __packed; + +#define BT_HCI_OP_USER_CONFIRM_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x002c) +#define BT_HCI_OP_USER_CONFIRM_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x002d) +struct bt_hci_cp_user_confirm_reply { + bt_addr_t bdaddr; +} __packed; +struct bt_hci_rp_user_confirm_reply { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_USER_PASSKEY_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x002e) +struct bt_hci_cp_user_passkey_reply { + bt_addr_t bdaddr; + uint32_t passkey; +} __packed; + +#define BT_HCI_OP_USER_PASSKEY_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x002f) +struct bt_hci_cp_user_passkey_neg_reply { + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_IO_CAPABILITY_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x0034) +struct bt_hci_cp_io_capability_neg_reply { + bt_addr_t bdaddr; + uint8_t reason; +} __packed; + +#define BT_HCI_OP_SET_EVENT_MASK BT_OP(BT_OGF_BASEBAND, 0x0001) +struct bt_hci_cp_set_event_mask { + uint8_t events[8]; +} __packed; + +#define BT_HCI_OP_RESET BT_OP(BT_OGF_BASEBAND, 0x0003) + +#define BT_HCI_OP_WRITE_LOCAL_NAME BT_OP(BT_OGF_BASEBAND, 0x0013) +struct bt_hci_write_local_name { + uint8_t local_name[248]; +} __packed; + +#define BT_HCI_OP_WRITE_PAGE_TIMEOUT BT_OP(BT_OGF_BASEBAND, 0x0018) + +#define BT_HCI_OP_WRITE_SCAN_ENABLE BT_OP(BT_OGF_BASEBAND, 0x001a) +#define BT_BREDR_SCAN_DISABLED 0x00 +#define BT_BREDR_SCAN_INQUIRY 0x01 +#define BT_BREDR_SCAN_PAGE 0x02 + +#define BT_TX_POWER_LEVEL_CURRENT 0x00 +#define BT_TX_POWER_LEVEL_MAX 0x01 +#define BT_HCI_OP_READ_TX_POWER_LEVEL BT_OP(BT_OGF_BASEBAND, 0x002d) +struct bt_hci_cp_read_tx_power_level { + uint16_t handle; + uint8_t type; +} __packed; + +struct bt_hci_rp_read_tx_power_level { + uint8_t status; + uint16_t handle; + int8_t tx_power_level; +} __packed; + +#define BT_HCI_CTL_TO_HOST_FLOW_DISABLE 0x00 +#define BT_HCI_CTL_TO_HOST_FLOW_ENABLE 0x01 +#define BT_HCI_OP_SET_CTL_TO_HOST_FLOW BT_OP(BT_OGF_BASEBAND, 0x0031) +struct bt_hci_cp_set_ctl_to_host_flow { + uint8_t flow_enable; +} __packed; + +#define BT_HCI_OP_HOST_BUFFER_SIZE BT_OP(BT_OGF_BASEBAND, 0x0033) +struct bt_hci_cp_host_buffer_size { + uint16_t acl_mtu; + uint8_t sco_mtu; + uint16_t acl_pkts; + uint16_t sco_pkts; +} __packed; + +struct bt_hci_handle_count { + uint16_t handle; + uint16_t count; +} __packed; + +#define BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS BT_OP(BT_OGF_BASEBAND, 0x0035) +struct bt_hci_cp_host_num_completed_packets { + uint8_t num_handles; + struct bt_hci_handle_count h[0]; +} __packed; + +#define BT_HCI_OP_WRITE_INQUIRY_MODE BT_OP(BT_OGF_BASEBAND, 0x0045) +struct bt_hci_cp_write_inquiry_mode { + uint8_t mode; +} __packed; + +#define BT_HCI_OP_WRITE_SSP_MODE BT_OP(BT_OGF_BASEBAND, 0x0056) +struct bt_hci_cp_write_ssp_mode { + uint8_t mode; +} __packed; + +#define BT_HCI_OP_SET_EVENT_MASK_PAGE_2 BT_OP(BT_OGF_BASEBAND, 0x0063) +struct bt_hci_cp_set_event_mask_page_2 { + uint8_t events_page_2[8]; +} __packed; + +#define BT_HCI_OP_LE_WRITE_LE_HOST_SUPP BT_OP(BT_OGF_BASEBAND, 0x006d) +struct bt_hci_cp_write_le_host_supp { + uint8_t le; + uint8_t simul; +} __packed; + +#define BT_HCI_OP_WRITE_SC_HOST_SUPP BT_OP(BT_OGF_BASEBAND, 0x007a) +struct bt_hci_cp_write_sc_host_supp { + uint8_t sc_support; +} __packed; + +#define BT_HCI_OP_READ_AUTH_PAYLOAD_TIMEOUT BT_OP(BT_OGF_BASEBAND, 0x007b) +struct bt_hci_cp_read_auth_payload_timeout { + uint16_t handle; +} __packed; + +struct bt_hci_rp_read_auth_payload_timeout { + uint8_t status; + uint16_t handle; + uint16_t auth_payload_timeout; +} __packed; + +#define BT_HCI_OP_WRITE_AUTH_PAYLOAD_TIMEOUT BT_OP(BT_OGF_BASEBAND, 0x007c) +struct bt_hci_cp_write_auth_payload_timeout { + uint16_t handle; + uint16_t auth_payload_timeout; +} __packed; + +struct bt_hci_rp_write_auth_payload_timeout { + uint8_t status; + uint16_t handle; +} __packed; + +/* HCI version from Assigned Numbers */ +#define BT_HCI_VERSION_1_0B 0 +#define BT_HCI_VERSION_1_1 1 +#define BT_HCI_VERSION_1_2 2 +#define BT_HCI_VERSION_2_0 3 +#define BT_HCI_VERSION_2_1 4 +#define BT_HCI_VERSION_3_0 5 +#define BT_HCI_VERSION_4_0 6 +#define BT_HCI_VERSION_4_1 7 +#define BT_HCI_VERSION_4_2 8 +#define BT_HCI_VERSION_5_0 9 +#define BT_HCI_VERSION_5_1 10 +#define BT_HCI_VERSION_5_2 11 + +#define BT_HCI_OP_READ_LOCAL_VERSION_INFO BT_OP(BT_OGF_INFO, 0x0001) +struct bt_hci_rp_read_local_version_info { + uint8_t status; + uint8_t hci_version; + uint16_t hci_revision; + uint8_t lmp_version; + uint16_t manufacturer; + uint16_t lmp_subversion; +} __packed; + +#define BT_HCI_OP_READ_SUPPORTED_COMMANDS BT_OP(BT_OGF_INFO, 0x0002) +struct bt_hci_rp_read_supported_commands { + uint8_t status; + uint8_t commands[64]; +} __packed; + +#define BT_HCI_OP_READ_LOCAL_EXT_FEATURES BT_OP(BT_OGF_INFO, 0x0004) +struct bt_hci_cp_read_local_ext_features { + uint8_t page; +}; +struct bt_hci_rp_read_local_ext_features { + uint8_t status; + uint8_t page; + uint8_t max_page; + uint8_t ext_features[8]; +} __packed; + +#define BT_HCI_OP_READ_LOCAL_FEATURES BT_OP(BT_OGF_INFO, 0x0003) +struct bt_hci_rp_read_local_features { + uint8_t status; + uint8_t features[8]; +} __packed; + +#define BT_HCI_OP_READ_BUFFER_SIZE BT_OP(BT_OGF_INFO, 0x0005) +struct bt_hci_rp_read_buffer_size { + uint8_t status; + uint16_t acl_max_len; + uint8_t sco_max_len; + uint16_t acl_max_num; + uint16_t sco_max_num; +} __packed; + +#define BT_HCI_OP_READ_BD_ADDR BT_OP(BT_OGF_INFO, 0x0009) +struct bt_hci_rp_read_bd_addr { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_READ_RSSI BT_OP(BT_OGF_STATUS, 0x0005) +struct bt_hci_cp_read_rssi { + uint16_t handle; +} __packed; +struct bt_hci_rp_read_rssi { + uint8_t status; + uint16_t handle; + int8_t rssi; +} __packed; + +#define BT_HCI_ENCRYPTION_KEY_SIZE_MIN 7 +#define BT_HCI_ENCRYPTION_KEY_SIZE_MAX 16 + +#define BT_HCI_OP_READ_ENCRYPTION_KEY_SIZE BT_OP(BT_OGF_STATUS, 0x0008) +struct bt_hci_cp_read_encryption_key_size { + uint16_t handle; +} __packed; +struct bt_hci_rp_read_encryption_key_size { + uint8_t status; + uint16_t handle; + uint8_t key_size; +} __packed; + +/* BLE */ + +#define BT_HCI_OP_LE_SET_EVENT_MASK BT_OP(BT_OGF_LE, 0x0001) +struct bt_hci_cp_le_set_event_mask { + uint8_t events[8]; +} __packed; + +#define BT_HCI_OP_LE_READ_BUFFER_SIZE BT_OP(BT_OGF_LE, 0x0002) +struct bt_hci_rp_le_read_buffer_size { + uint8_t status; + uint16_t le_max_len; + uint8_t le_max_num; +} __packed; + +#define BT_HCI_OP_LE_READ_LOCAL_FEATURES BT_OP(BT_OGF_LE, 0x0003) +struct bt_hci_rp_le_read_local_features { + uint8_t status; + uint8_t features[8]; +} __packed; + +#define BT_HCI_OP_LE_SET_RANDOM_ADDRESS BT_OP(BT_OGF_LE, 0x0005) +struct bt_hci_cp_le_set_random_address { + bt_addr_t bdaddr; +} __packed; + +/* LE Advertising Types (LE Advertising Parameters Set)*/ +#define BT_LE_ADV_IND (__DEPRECATED_MACRO 0x00) +#define BT_LE_ADV_DIRECT_IND (__DEPRECATED_MACRO 0x01) +#define BT_LE_ADV_SCAN_IND (__DEPRECATED_MACRO 0x02) +#define BT_LE_ADV_NONCONN_IND (__DEPRECATED_MACRO 0x03) +#define BT_LE_ADV_DIRECT_IND_LOW_DUTY (__DEPRECATED_MACRO 0x04) +/* LE Advertising PDU Types. */ +#define BT_LE_ADV_SCAN_RSP (__DEPRECATED_MACRO 0x04) + +#define BT_HCI_ADV_IND 0x00 +#define BT_HCI_ADV_DIRECT_IND 0x01 +#define BT_HCI_ADV_SCAN_IND 0x02 +#define BT_HCI_ADV_NONCONN_IND 0x03 +#define BT_HCI_ADV_DIRECT_IND_LOW_DUTY 0x04 +#define BT_HCI_ADV_SCAN_RSP 0x04 + +#define BT_LE_ADV_FP_NO_WHITELIST 0x00 +#define BT_LE_ADV_FP_WHITELIST_SCAN_REQ 0x01 +#define BT_LE_ADV_FP_WHITELIST_CONN_IND 0x02 +#define BT_LE_ADV_FP_WHITELIST_BOTH 0x03 + +#define BT_HCI_OP_LE_SET_ADV_PARAM BT_OP(BT_OGF_LE, 0x0006) +struct bt_hci_cp_le_set_adv_param { + uint16_t min_interval; + uint16_t max_interval; + uint8_t type; + uint8_t own_addr_type; + bt_addr_le_t direct_addr; + uint8_t channel_map; + uint8_t filter_policy; +} __packed; + +#define BT_HCI_OP_LE_READ_ADV_CHAN_TX_POWER BT_OP(BT_OGF_LE, 0x0007) +struct bt_hci_rp_le_read_chan_tx_power { + uint8_t status; + int8_t tx_power_level; +} __packed; + +#define BT_HCI_OP_LE_SET_ADV_DATA BT_OP(BT_OGF_LE, 0x0008) +struct bt_hci_cp_le_set_adv_data { + uint8_t len; + uint8_t data[31]; +} __packed; + +#define BT_HCI_OP_LE_SET_SCAN_RSP_DATA BT_OP(BT_OGF_LE, 0x0009) +struct bt_hci_cp_le_set_scan_rsp_data { + uint8_t len; + uint8_t data[31]; +} __packed; + +#define BT_HCI_LE_ADV_DISABLE 0x00 +#define BT_HCI_LE_ADV_ENABLE 0x01 + +#define BT_HCI_OP_LE_SET_ADV_ENABLE BT_OP(BT_OGF_LE, 0x000a) +struct bt_hci_cp_le_set_adv_enable { + uint8_t enable; +} __packed; + +/* Scan types */ +#define BT_HCI_OP_LE_SET_SCAN_PARAM BT_OP(BT_OGF_LE, 0x000b) +#define BT_HCI_LE_SCAN_PASSIVE 0x00 +#define BT_HCI_LE_SCAN_ACTIVE 0x01 + +#define BT_HCI_LE_SCAN_FP_NO_WHITELIST 0x00 +#define BT_HCI_LE_SCAN_FP_USE_WHITELIST 0x01 + +struct bt_hci_cp_le_set_scan_param { + uint8_t scan_type; + uint16_t interval; + uint16_t window; + uint8_t addr_type; + uint8_t filter_policy; +} __packed; + +#define BT_HCI_OP_LE_SET_SCAN_ENABLE BT_OP(BT_OGF_LE, 0x000c) + +#define BT_HCI_LE_SCAN_DISABLE 0x00 +#define BT_HCI_LE_SCAN_ENABLE 0x01 + +#define BT_HCI_LE_SCAN_FILTER_DUP_DISABLE 0x00 +#define BT_HCI_LE_SCAN_FILTER_DUP_ENABLE 0x01 + +struct bt_hci_cp_le_set_scan_enable { + uint8_t enable; + uint8_t filter_dup; +} __packed; + +#define BT_HCI_OP_LE_CREATE_CONN BT_OP(BT_OGF_LE, 0x000d) + +#define BT_HCI_LE_CREATE_CONN_FP_DIRECT 0x00 +#define BT_HCI_LE_CREATE_CONN_FP_WHITELIST 0x01 + +struct bt_hci_cp_le_create_conn { + uint16_t scan_interval; + uint16_t scan_window; + uint8_t filter_policy; + bt_addr_le_t peer_addr; + uint8_t own_addr_type; + uint16_t conn_interval_min; + uint16_t conn_interval_max; + uint16_t conn_latency; + uint16_t supervision_timeout; + uint16_t min_ce_len; + uint16_t max_ce_len; +} __packed; + +#define BT_HCI_OP_LE_CREATE_CONN_CANCEL BT_OP(BT_OGF_LE, 0x000e) + +#define BT_HCI_OP_LE_READ_WL_SIZE BT_OP(BT_OGF_LE, 0x000f) +struct bt_hci_rp_le_read_wl_size { + uint8_t status; + uint8_t wl_size; +} __packed; + +#define BT_HCI_OP_LE_CLEAR_WL BT_OP(BT_OGF_LE, 0x0010) + +#define BT_HCI_OP_LE_ADD_DEV_TO_WL BT_OP(BT_OGF_LE, 0x0011) +struct bt_hci_cp_le_add_dev_to_wl { + bt_addr_le_t addr; +} __packed; + +#define BT_HCI_OP_LE_REM_DEV_FROM_WL BT_OP(BT_OGF_LE, 0x0012) +struct bt_hci_cp_le_rem_dev_from_wl { + bt_addr_le_t addr; +} __packed; + +#define BT_HCI_OP_LE_CONN_UPDATE BT_OP(BT_OGF_LE, 0x0013) +struct hci_cp_le_conn_update { + uint16_t handle; + uint16_t conn_interval_min; + uint16_t conn_interval_max; + uint16_t conn_latency; + uint16_t supervision_timeout; + uint16_t min_ce_len; + uint16_t max_ce_len; +} __packed; + +#define BT_HCI_OP_LE_SET_HOST_CHAN_CLASSIF BT_OP(BT_OGF_LE, 0x0014) +struct bt_hci_cp_le_set_host_chan_classif { + uint8_t ch_map[5]; +} __packed; + +#define BT_HCI_OP_LE_READ_CHAN_MAP BT_OP(BT_OGF_LE, 0x0015) +struct bt_hci_cp_le_read_chan_map { + uint16_t handle; +} __packed; +struct bt_hci_rp_le_read_chan_map { + uint8_t status; + uint16_t handle; + uint8_t ch_map[5]; +} __packed; + +#define BT_HCI_OP_LE_READ_REMOTE_FEATURES BT_OP(BT_OGF_LE, 0x0016) +struct bt_hci_cp_le_read_remote_features { + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_ENCRYPT BT_OP(BT_OGF_LE, 0x0017) +struct bt_hci_cp_le_encrypt { + uint8_t key[16]; + uint8_t plaintext[16]; +} __packed; +struct bt_hci_rp_le_encrypt { + uint8_t status; + uint8_t enc_data[16]; +} __packed; + +#define BT_HCI_OP_LE_RAND BT_OP(BT_OGF_LE, 0x0018) +struct bt_hci_rp_le_rand { + uint8_t status; + uint8_t rand[8]; +} __packed; + +#define BT_HCI_OP_LE_START_ENCRYPTION BT_OP(BT_OGF_LE, 0x0019) +struct bt_hci_cp_le_start_encryption { + uint16_t handle; + uint64_t rand; + uint16_t ediv; + uint8_t ltk[16]; +} __packed; + +#define BT_HCI_OP_LE_LTK_REQ_REPLY BT_OP(BT_OGF_LE, 0x001a) +struct bt_hci_cp_le_ltk_req_reply { + uint16_t handle; + uint8_t ltk[16]; +} __packed; +struct bt_hci_rp_le_ltk_req_reply { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_LTK_REQ_NEG_REPLY BT_OP(BT_OGF_LE, 0x001b) +struct bt_hci_cp_le_ltk_req_neg_reply { + uint16_t handle; +} __packed; +struct bt_hci_rp_le_ltk_req_neg_reply { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_READ_SUPP_STATES BT_OP(BT_OGF_LE, 0x001c) +struct bt_hci_rp_le_read_supp_states { + uint8_t status; + uint8_t le_states[8]; +} __packed; + +#define BT_HCI_OP_LE_RX_TEST BT_OP(BT_OGF_LE, 0x001d) +struct bt_hci_cp_le_rx_test { + uint8_t rx_ch; +} __packed; + +#define BT_HCI_OP_LE_TX_TEST BT_OP(BT_OGF_LE, 0x001e) +struct bt_hci_cp_le_tx_test { + uint8_t tx_ch; + uint8_t test_data_len; + uint8_t pkt_payload; +} __packed; + +#define BT_HCI_OP_LE_TEST_END BT_OP(BT_OGF_LE, 0x001f) +struct bt_hci_rp_le_test_end { + uint8_t status; + uint16_t rx_pkt_count; +} __packed; + +#define BT_HCI_OP_LE_CONN_PARAM_REQ_REPLY BT_OP(BT_OGF_LE, 0x0020) +struct bt_hci_cp_le_conn_param_req_reply { + uint16_t handle; + uint16_t interval_min; + uint16_t interval_max; + uint16_t latency; + uint16_t timeout; + uint16_t min_ce_len; + uint16_t max_ce_len; +} __packed; +struct bt_hci_rp_le_conn_param_req_reply { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY BT_OP(BT_OGF_LE, 0x0021) +struct bt_hci_cp_le_conn_param_req_neg_reply { + uint16_t handle; + uint8_t reason; +} __packed; +struct bt_hci_rp_le_conn_param_req_neg_reply { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_SET_DATA_LEN BT_OP(BT_OGF_LE, 0x0022) +struct bt_hci_cp_le_set_data_len { + uint16_t handle; + uint16_t tx_octets; + uint16_t tx_time; +} __packed; +struct bt_hci_rp_le_set_data_len { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_READ_DEFAULT_DATA_LEN BT_OP(BT_OGF_LE, 0x0023) +struct bt_hci_rp_le_read_default_data_len { + uint8_t status; + uint16_t max_tx_octets; + uint16_t max_tx_time; +} __packed; + +#define BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN BT_OP(BT_OGF_LE, 0x0024) +struct bt_hci_cp_le_write_default_data_len { + uint16_t max_tx_octets; + uint16_t max_tx_time; +} __packed; + +#define BT_HCI_OP_LE_P256_PUBLIC_KEY BT_OP(BT_OGF_LE, 0x0025) + +#define BT_HCI_OP_LE_GENERATE_DHKEY BT_OP(BT_OGF_LE, 0x0026) +struct bt_hci_cp_le_generate_dhkey { + uint8_t key[64]; +} __packed; + +#define BT_HCI_OP_LE_ADD_DEV_TO_RL BT_OP(BT_OGF_LE, 0x0027) +struct bt_hci_cp_le_add_dev_to_rl { + bt_addr_le_t peer_id_addr; + uint8_t peer_irk[16]; + uint8_t local_irk[16]; +} __packed; + +#define BT_HCI_OP_LE_REM_DEV_FROM_RL BT_OP(BT_OGF_LE, 0x0028) +struct bt_hci_cp_le_rem_dev_from_rl { + bt_addr_le_t peer_id_addr; +} __packed; + +#define BT_HCI_OP_LE_CLEAR_RL BT_OP(BT_OGF_LE, 0x0029) + +#define BT_HCI_OP_LE_READ_RL_SIZE BT_OP(BT_OGF_LE, 0x002a) +struct bt_hci_rp_le_read_rl_size { + uint8_t status; + uint8_t rl_size; +} __packed; + +#define BT_HCI_OP_LE_READ_PEER_RPA BT_OP(BT_OGF_LE, 0x002b) +struct bt_hci_cp_le_read_peer_rpa { + bt_addr_le_t peer_id_addr; +} __packed; +struct bt_hci_rp_le_read_peer_rpa { + uint8_t status; + bt_addr_t peer_rpa; +} __packed; + +#define BT_HCI_OP_LE_READ_LOCAL_RPA BT_OP(BT_OGF_LE, 0x002c) +struct bt_hci_cp_le_read_local_rpa { + bt_addr_le_t peer_id_addr; +} __packed; +struct bt_hci_rp_le_read_local_rpa { + uint8_t status; + bt_addr_t local_rpa; +} __packed; + +#define BT_HCI_ADDR_RES_DISABLE 0x00 +#define BT_HCI_ADDR_RES_ENABLE 0x01 + +#define BT_HCI_OP_LE_SET_ADDR_RES_ENABLE BT_OP(BT_OGF_LE, 0x002d) +struct bt_hci_cp_le_set_addr_res_enable { + uint8_t enable; +} __packed; + +#define BT_HCI_OP_LE_SET_RPA_TIMEOUT BT_OP(BT_OGF_LE, 0x002e) +struct bt_hci_cp_le_set_rpa_timeout { + uint16_t rpa_timeout; +} __packed; + +#define BT_HCI_OP_LE_READ_MAX_DATA_LEN BT_OP(BT_OGF_LE, 0x002f) +struct bt_hci_rp_le_read_max_data_len { + uint8_t status; + uint16_t max_tx_octets; + uint16_t max_tx_time; + uint16_t max_rx_octets; + uint16_t max_rx_time; +} __packed; + +#define BT_HCI_LE_PHY_1M 0x01 +#define BT_HCI_LE_PHY_2M 0x02 +#define BT_HCI_LE_PHY_CODED 0x03 + +#define BT_HCI_OP_LE_READ_PHY BT_OP(BT_OGF_LE, 0x0030) +struct bt_hci_cp_le_read_phy { + uint16_t handle; +} __packed; +struct bt_hci_rp_le_read_phy { + uint8_t status; + uint16_t handle; + uint8_t tx_phy; + uint8_t rx_phy; +} __packed; + +#define BT_HCI_LE_PHY_TX_ANY BIT(0) +#define BT_HCI_LE_PHY_RX_ANY BIT(1) + +#define BT_HCI_LE_PHY_PREFER_1M BIT(0) +#define BT_HCI_LE_PHY_PREFER_2M BIT(1) +#define BT_HCI_LE_PHY_PREFER_CODED BIT(2) + +#define BT_HCI_OP_LE_SET_DEFAULT_PHY BT_OP(BT_OGF_LE, 0x0031) +struct bt_hci_cp_le_set_default_phy { + uint8_t all_phys; + uint8_t tx_phys; + uint8_t rx_phys; +} __packed; + +#define BT_HCI_LE_PHY_CODED_ANY 0x00 +#define BT_HCI_LE_PHY_CODED_S2 0x01 +#define BT_HCI_LE_PHY_CODED_S8 0x02 + +#define BT_HCI_OP_LE_SET_PHY BT_OP(BT_OGF_LE, 0x0032) +struct bt_hci_cp_le_set_phy { + uint16_t handle; + uint8_t all_phys; + uint8_t tx_phys; + uint8_t rx_phys; + uint16_t phy_opts; +} __packed; + +#define BT_HCI_LE_MOD_INDEX_STANDARD 0x00 +#define BT_HCI_LE_MOD_INDEX_STABLE 0x01 + +#define BT_HCI_OP_LE_ENH_RX_TEST BT_OP(BT_OGF_LE, 0x0033) +struct bt_hci_cp_le_enh_rx_test { + uint8_t rx_ch; + uint8_t phy; + uint8_t mod_index; +} __packed; + +/* Extends BT_HCI_LE_PHY */ +#define BT_HCI_LE_TX_PHY_CODED_S8 0x03 +#define BT_HCI_LE_TX_PHY_CODED_S2 0x04 + +#define BT_HCI_OP_LE_ENH_TX_TEST BT_OP(BT_OGF_LE, 0x0034) +struct bt_hci_cp_le_enh_tx_test { + uint8_t tx_ch; + uint8_t test_data_len; + uint8_t pkt_payload; + uint8_t phy; +} __packed; + +#define BT_HCI_OP_LE_SET_ADV_SET_RANDOM_ADDR BT_OP(BT_OGF_LE, 0x0035) +struct bt_hci_cp_le_set_adv_set_random_addr { + uint8_t handle; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_LE_ADV_PROP_CONN BIT(0) +#define BT_HCI_LE_ADV_PROP_SCAN BIT(1) +#define BT_HCI_LE_ADV_PROP_DIRECT BIT(2) +#define BT_HCI_LE_ADV_PROP_HI_DC_CONN BIT(3) +#define BT_HCI_LE_ADV_PROP_LEGACY BIT(4) +#define BT_HCI_LE_ADV_PROP_ANON BIT(5) +#define BT_HCI_LE_ADV_PROP_TX_POWER BIT(6) + +#define BT_HCI_LE_ADV_SCAN_REQ_ENABLE 1 +#define BT_HCI_LE_ADV_SCAN_REQ_DISABLE 0 + +#define BT_HCI_LE_ADV_TX_POWER_NO_PREF 0x7F + +#define BT_HCI_OP_LE_SET_EXT_ADV_PARAM BT_OP(BT_OGF_LE, 0x0036) +struct bt_hci_cp_le_set_ext_adv_param { + uint8_t handle; + uint16_t props; + uint8_t prim_min_interval[3]; + uint8_t prim_max_interval[3]; + uint8_t prim_channel_map; + uint8_t own_addr_type; + bt_addr_le_t peer_addr; + uint8_t filter_policy; + int8_t tx_power; + uint8_t prim_adv_phy; + uint8_t sec_adv_max_skip; + uint8_t sec_adv_phy; + uint8_t sid; + uint8_t scan_req_notify_enable; +} __packed; +struct bt_hci_rp_le_set_ext_adv_param { + uint8_t status; + int8_t tx_power; +} __packed; + +#define BT_HCI_LE_EXT_ADV_OP_INTERM_FRAG 0x00 +#define BT_HCI_LE_EXT_ADV_OP_FIRST_FRAG 0x01 +#define BT_HCI_LE_EXT_ADV_OP_LAST_FRAG 0x02 +#define BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA 0x03 +#define BT_HCI_LE_EXT_ADV_OP_UNCHANGED_DATA 0x04 + +#define BT_HCI_LE_EXT_ADV_FRAG_ENABLED 0x00 +#define BT_HCI_LE_EXT_ADV_FRAG_DISABLED 0x01 + +#define BT_HCI_LE_EXT_ADV_FRAG_MAX_LEN 251 + +#define BT_HCI_OP_LE_SET_EXT_ADV_DATA BT_OP(BT_OGF_LE, 0x0037) +struct bt_hci_cp_le_set_ext_adv_data { + uint8_t handle; + uint8_t op; + uint8_t frag_pref; + uint8_t len; + uint8_t data[251]; +} __packed; + +#define BT_HCI_OP_LE_SET_EXT_SCAN_RSP_DATA BT_OP(BT_OGF_LE, 0x0038) +struct bt_hci_cp_le_set_ext_scan_rsp_data { + uint8_t handle; + uint8_t op; + uint8_t frag_pref; + uint8_t len; + uint8_t data[251]; +} __packed; + +#define BT_HCI_OP_LE_SET_EXT_ADV_ENABLE BT_OP(BT_OGF_LE, 0x0039) +struct bt_hci_ext_adv_set { + uint8_t handle; + uint16_t duration; + uint8_t max_ext_adv_evts; +} __packed; + +struct bt_hci_cp_le_set_ext_adv_enable { + uint8_t enable; + uint8_t set_num; + struct bt_hci_ext_adv_set s[0]; +} __packed; + +#define BT_HCI_OP_LE_READ_MAX_ADV_DATA_LEN BT_OP(BT_OGF_LE, 0x003a) +struct bt_hci_rp_le_read_max_adv_data_len { + uint8_t status; + uint16_t max_adv_data_len; +} __packed; + +#define BT_HCI_OP_LE_READ_NUM_ADV_SETS BT_OP(BT_OGF_LE, 0x003b) +struct bt_hci_rp_le_read_num_adv_sets { + uint8_t status; + uint8_t num_sets; +} __packed; + +#define BT_HCI_OP_LE_REMOVE_ADV_SET BT_OP(BT_OGF_LE, 0x003c) +struct bt_hci_cp_le_remove_adv_set { + uint8_t handle; +} __packed; + +#define BT_HCI_OP_CLEAR_ADV_SETS BT_OP(BT_OGF_LE, 0x003d) + +#define BT_HCI_OP_LE_SET_PER_ADV_PARAM BT_OP(BT_OGF_LE, 0x003e) +struct bt_hci_cp_le_set_per_adv_param { + uint8_t handle; + uint16_t min_interval; + uint16_t max_interval; + uint16_t props; +} __packed; + +#define BT_HCI_OP_LE_SET_PER_ADV_DATA BT_OP(BT_OGF_LE, 0x003f) +struct bt_hci_cp_le_set_per_adv_data { + uint8_t handle; + uint8_t op; + uint8_t len; + uint8_t data[251]; +} __packed; + +#define BT_HCI_OP_LE_SET_PER_ADV_ENABLE BT_OP(BT_OGF_LE, 0x0040) +struct bt_hci_cp_le_set_per_adv_enable { + uint8_t enable; + uint8_t handle; +} __packed; + +#define BT_HCI_OP_LE_SET_EXT_SCAN_PARAM BT_OP(BT_OGF_LE, 0x0041) +struct bt_hci_ext_scan_phy { + uint8_t type; + uint16_t interval; + uint16_t window; +} __packed; + +#define BT_HCI_LE_EXT_SCAN_PHY_1M BIT(0) +#define BT_HCI_LE_EXT_SCAN_PHY_2M BIT(1) +#define BT_HCI_LE_EXT_SCAN_PHY_CODED BIT(2) + +struct bt_hci_cp_le_set_ext_scan_param { + uint8_t own_addr_type; + uint8_t filter_policy; + uint8_t phys; + struct bt_hci_ext_scan_phy p[0]; +} __packed; + +/* Extends BT_HCI_LE_SCAN_FILTER_DUP */ +#define BT_HCI_LE_EXT_SCAN_FILTER_DUP_ENABLE_RESET 0x02 + +#define BT_HCI_OP_LE_SET_EXT_SCAN_ENABLE BT_OP(BT_OGF_LE, 0x0042) +struct bt_hci_cp_le_set_ext_scan_enable { + uint8_t enable; + uint8_t filter_dup; + uint16_t duration; + uint16_t period; +} __packed; + +#define BT_HCI_OP_LE_EXT_CREATE_CONN BT_OP(BT_OGF_LE, 0x0043) +struct bt_hci_ext_conn_phy { + uint16_t scan_interval; + uint16_t scan_window; + uint16_t conn_interval_min; + uint16_t conn_interval_max; + uint16_t conn_latency; + uint16_t supervision_timeout; + uint16_t min_ce_len; + uint16_t max_ce_len; +} __packed; + +struct bt_hci_cp_le_ext_create_conn { + uint8_t filter_policy; + uint8_t own_addr_type; + bt_addr_le_t peer_addr; + uint8_t phys; + struct bt_hci_ext_conn_phy p[0]; +} __packed; + +#define BT_HCI_OP_LE_PER_ADV_CREATE_SYNC BT_OP(BT_OGF_LE, 0x0044) +struct bt_hci_cp_le_per_adv_create_sync { + uint8_t filter_policy; + uint8_t sid; + bt_addr_le_t addr; + uint16_t skip; + uint16_t sync_timeout; + uint8_t unused; +} __packed; + +#define BT_HCI_OP_LE_PER_ADV_CREATE_SYNC_CANCEL BT_OP(BT_OGF_LE, 0x0045) + +#define BT_HCI_OP_LE_PER_ADV_TERMINATE_SYNC BT_OP(BT_OGF_LE, 0x0046) +struct bt_hci_cp_le_per_adv_terminate_sync { + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_ADD_DEV_TO_PER_ADV_LIST BT_OP(BT_OGF_LE, 0x0047) +struct bt_hci_cp_le_add_dev_to_per_adv_list { + bt_addr_le_t addr; + uint8_t sid; +} __packed; + +#define BT_HCI_OP_LE_REM_DEV_FROM_PER_ADV_LIST BT_OP(BT_OGF_LE, 0x0048) +struct bt_hci_cp_le_rem_dev_from_per_adv_list { + bt_addr_le_t addr; + uint8_t sid; +} __packed; + +#define BT_HCI_OP_LE_CLEAR_PER_ADV_LIST BT_OP(BT_OGF_LE, 0x0049) + +#define BT_HCI_OP_LE_READ_PER_ADV_LIST_SIZE BT_OP(BT_OGF_LE, 0x004a) +struct bt_hci_rp_le_read_per_adv_list_size { + uint8_t status; + uint8_t list_size; +} __packed; + +#define BT_HCI_OP_LE_READ_TX_POWER BT_OP(BT_OGF_LE, 0x004b) +struct bt_hci_rp_le_read_tx_power { + uint8_t status; + int8_t min_tx_power; + int8_t max_tx_power; +} __packed; + +#define BT_HCI_OP_LE_READ_RF_PATH_COMP BT_OP(BT_OGF_LE, 0x004c) +struct bt_hci_rp_le_read_rf_path_comp { + uint8_t status; + int16_t tx_path_comp; + int16_t rx_path_comp; +} __packed; + +#define BT_HCI_OP_LE_WRITE_RF_PATH_COMP BT_OP(BT_OGF_LE, 0x004d) +struct bt_hci_cp_le_write_rf_path_comp { + int16_t tx_path_comp; + int16_t rx_path_comp; +} __packed; + +#define BT_HCI_LE_PRIVACY_MODE_NETWORK 0x00 +#define BT_HCI_LE_PRIVACY_MODE_DEVICE 0x01 + +#define BT_HCI_OP_LE_SET_PRIVACY_MODE BT_OP(BT_OGF_LE, 0x004e) +struct bt_hci_cp_le_set_privacy_mode { + bt_addr_le_t id_addr; + uint8_t mode; +} __packed; + +/* Event definitions */ + +#define BT_HCI_EVT_UNKNOWN 0x00 +#define BT_HCI_EVT_VENDOR 0xff + +#define BT_HCI_EVT_INQUIRY_COMPLETE 0x01 +struct bt_hci_evt_inquiry_complete { + uint8_t status; +} __packed; + +#define BT_HCI_EVT_CONN_COMPLETE 0x03 +struct bt_hci_evt_conn_complete { + uint8_t status; + uint16_t handle; + bt_addr_t bdaddr; + uint8_t link_type; + uint8_t encr_enabled; +} __packed; + +#define BT_HCI_EVT_CONN_REQUEST 0x04 +struct bt_hci_evt_conn_request { + bt_addr_t bdaddr; + uint8_t dev_class[3]; + uint8_t link_type; +} __packed; + +#define BT_HCI_EVT_DISCONN_COMPLETE 0x05 +struct bt_hci_evt_disconn_complete { + uint8_t status; + uint16_t handle; + uint8_t reason; +} __packed; + +#define BT_HCI_EVT_AUTH_COMPLETE 0x06 +struct bt_hci_evt_auth_complete { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_EVT_REMOTE_NAME_REQ_COMPLETE 0x07 +struct bt_hci_evt_remote_name_req_complete { + uint8_t status; + bt_addr_t bdaddr; + uint8_t name[248]; +} __packed; + +#define BT_HCI_EVT_ENCRYPT_CHANGE 0x08 +struct bt_hci_evt_encrypt_change { + uint8_t status; + uint16_t handle; + uint8_t encrypt; +} __packed; + +#define BT_HCI_EVT_REMOTE_FEATURES 0x0b +struct bt_hci_evt_remote_features { + uint8_t status; + uint16_t handle; + uint8_t features[8]; +} __packed; + +#define BT_HCI_EVT_REMOTE_VERSION_INFO 0x0c +struct bt_hci_evt_remote_version_info { + uint8_t status; + uint16_t handle; + uint8_t version; + uint16_t manufacturer; + uint16_t subversion; +} __packed; + +#define BT_HCI_EVT_CMD_COMPLETE 0x0e +struct bt_hci_evt_cmd_complete { + uint8_t ncmd; + uint16_t opcode; +} __packed; + +struct bt_hci_evt_cc_status { + uint8_t status; +} __packed; + +#define BT_HCI_EVT_CMD_STATUS 0x0f +struct bt_hci_evt_cmd_status { + uint8_t status; + uint8_t ncmd; + uint16_t opcode; +} __packed; + +#define BT_HCI_EVT_ROLE_CHANGE 0x12 +struct bt_hci_evt_role_change { + uint8_t status; + bt_addr_t bdaddr; + uint8_t role; +} __packed; + +#define BT_HCI_EVT_NUM_COMPLETED_PACKETS 0x13 +struct bt_hci_evt_num_completed_packets { + uint8_t num_handles; + struct bt_hci_handle_count h[0]; +} __packed; + +#define BT_HCI_EVT_PIN_CODE_REQ 0x16 +struct bt_hci_evt_pin_code_req { + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_EVT_LINK_KEY_REQ 0x17 +struct bt_hci_evt_link_key_req { + bt_addr_t bdaddr; +} __packed; + +/* Link Key types */ +#define BT_LK_COMBINATION 0x00 +#define BT_LK_LOCAL_UNIT 0x01 +#define BT_LK_REMOTE_UNIT 0x02 +#define BT_LK_DEBUG_COMBINATION 0x03 +#define BT_LK_UNAUTH_COMBINATION_P192 0x04 +#define BT_LK_AUTH_COMBINATION_P192 0x05 +#define BT_LK_CHANGED_COMBINATION 0x06 +#define BT_LK_UNAUTH_COMBINATION_P256 0x07 +#define BT_LK_AUTH_COMBINATION_P256 0x08 + +#define BT_HCI_EVT_LINK_KEY_NOTIFY 0x18 +struct bt_hci_evt_link_key_notify { + bt_addr_t bdaddr; + uint8_t link_key[16]; + uint8_t key_type; +} __packed; + +/* Overflow link types */ +#define BT_OVERFLOW_LINK_SYNCH 0x00 +#define BT_OVERFLOW_LINK_ACL 0x01 + +#define BT_HCI_EVT_DATA_BUF_OVERFLOW 0x1a +struct bt_hci_evt_data_buf_overflow { + uint8_t link_type; +} __packed; + +#define BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI 0x22 +struct bt_hci_evt_inquiry_result_with_rssi { + bt_addr_t addr; + uint8_t pscan_rep_mode; + uint8_t reserved; + uint8_t cod[3]; + uint16_t clock_offset; + int8_t rssi; +} __packed; + +#define BT_HCI_EVT_REMOTE_EXT_FEATURES 0x23 +struct bt_hci_evt_remote_ext_features { + uint8_t status; + uint16_t handle; + uint8_t page; + uint8_t max_page; + uint8_t features[8]; +} __packed; + +#define BT_HCI_EVT_SYNC_CONN_COMPLETE 0x2c +struct bt_hci_evt_sync_conn_complete { + uint8_t status; + uint16_t handle; + bt_addr_t bdaddr; + uint8_t link_type; + uint8_t tx_interval; + uint8_t retansmission_window; + uint16_t rx_pkt_length; + uint16_t tx_pkt_length; + uint8_t air_mode; +} __packed; + +#define BT_HCI_EVT_EXTENDED_INQUIRY_RESULT 0x2f +struct bt_hci_evt_extended_inquiry_result { + uint8_t num_reports; + bt_addr_t addr; + uint8_t pscan_rep_mode; + uint8_t reserved; + uint8_t cod[3]; + uint16_t clock_offset; + int8_t rssi; + uint8_t eir[240]; +} __packed; + +#define BT_HCI_EVT_ENCRYPT_KEY_REFRESH_COMPLETE 0x30 +struct bt_hci_evt_encrypt_key_refresh_complete { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_EVT_IO_CAPA_REQ 0x31 +struct bt_hci_evt_io_capa_req { + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_EVT_IO_CAPA_RESP 0x32 +struct bt_hci_evt_io_capa_resp { + bt_addr_t bdaddr; + uint8_t capability; + uint8_t oob_data; + uint8_t authentication; +} __packed; + +#define BT_HCI_EVT_USER_CONFIRM_REQ 0x33 +struct bt_hci_evt_user_confirm_req { + bt_addr_t bdaddr; + uint32_t passkey; +} __packed; + +#define BT_HCI_EVT_USER_PASSKEY_REQ 0x34 +struct bt_hci_evt_user_passkey_req { + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_EVT_SSP_COMPLETE 0x36 +struct bt_hci_evt_ssp_complete { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_EVT_USER_PASSKEY_NOTIFY 0x3b +struct bt_hci_evt_user_passkey_notify { + bt_addr_t bdaddr; + uint32_t passkey; +} __packed; + +#define BT_HCI_EVT_LE_META_EVENT 0x3e +struct bt_hci_evt_le_meta_event { + uint8_t subevent; +} __packed; + +#define BT_HCI_EVT_AUTH_PAYLOAD_TIMEOUT_EXP 0x57 +struct bt_hci_evt_auth_payload_timeout_exp { + uint16_t handle; +} __packed; + +#define BT_HCI_ROLE_MASTER 0x00 +#define BT_HCI_ROLE_SLAVE 0x01 + +#define BT_HCI_EVT_LE_CONN_COMPLETE 0x01 +struct bt_hci_evt_le_conn_complete { + uint8_t status; + uint16_t handle; + uint8_t role; + bt_addr_le_t peer_addr; + uint16_t interval; + uint16_t latency; + uint16_t supv_timeout; + uint8_t clock_accuracy; +} __packed; + +#define BT_HCI_EVT_LE_ADVERTISING_REPORT 0x02 +struct bt_hci_evt_le_advertising_info { + uint8_t evt_type; + bt_addr_le_t addr; + uint8_t length; + uint8_t data[0]; +} __packed; +struct bt_hci_evt_le_advertising_report { + uint8_t num_reports; + struct bt_hci_evt_le_advertising_info adv_info[0]; +} __packed; + +#define BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE 0x03 +struct bt_hci_evt_le_conn_update_complete { + uint8_t status; + uint16_t handle; + uint16_t interval; + uint16_t latency; + uint16_t supv_timeout; +} __packed; + +#define BT_HCI_EV_LE_REMOTE_FEAT_COMPLETE 0x04 +struct bt_hci_evt_le_remote_feat_complete { + uint8_t status; + uint16_t handle; + uint8_t features[8]; +} __packed; + +#define BT_HCI_EVT_LE_LTK_REQUEST 0x05 +struct bt_hci_evt_le_ltk_request { + uint16_t handle; + uint64_t rand; + uint16_t ediv; +} __packed; + +#define BT_HCI_EVT_LE_CONN_PARAM_REQ 0x06 +struct bt_hci_evt_le_conn_param_req { + uint16_t handle; + uint16_t interval_min; + uint16_t interval_max; + uint16_t latency; + uint16_t timeout; +} __packed; + +#define BT_HCI_EVT_LE_DATA_LEN_CHANGE 0x07 +struct bt_hci_evt_le_data_len_change { + uint16_t handle; + uint16_t max_tx_octets; + uint16_t max_tx_time; + uint16_t max_rx_octets; + uint16_t max_rx_time; +} __packed; + +#define BT_HCI_EVT_LE_P256_PUBLIC_KEY_COMPLETE 0x08 +struct bt_hci_evt_le_p256_public_key_complete { + uint8_t status; + uint8_t key[64]; +} __packed; + +#define BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE 0x09 +struct bt_hci_evt_le_generate_dhkey_complete { + uint8_t status; + uint8_t dhkey[32]; +} __packed; + +#define BT_HCI_EVT_LE_ENH_CONN_COMPLETE 0x0a +struct bt_hci_evt_le_enh_conn_complete { + uint8_t status; + uint16_t handle; + uint8_t role; + bt_addr_le_t peer_addr; + bt_addr_t local_rpa; + bt_addr_t peer_rpa; + uint16_t interval; + uint16_t latency; + uint16_t supv_timeout; + uint8_t clock_accuracy; +} __packed; + +#define BT_HCI_EVT_LE_DIRECT_ADV_REPORT 0x0b +struct bt_hci_evt_le_direct_adv_info { + uint8_t evt_type; + bt_addr_le_t addr; + bt_addr_le_t dir_addr; + int8_t rssi; +} __packed; +struct bt_hci_evt_le_direct_adv_report { + uint8_t num_reports; + struct bt_hci_evt_le_direct_adv_info direct_adv_info[0]; +} __packed; + +#define BT_HCI_EVT_LE_PHY_UPDATE_COMPLETE 0x0c +struct bt_hci_evt_le_phy_update_complete { + uint8_t status; + uint16_t handle; + uint8_t tx_phy; + uint8_t rx_phy; +} __packed; + +#define BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT 0x0d + +#define BT_HCI_LE_ADV_EVT_TYPE_CONN BIT(0) +#define BT_HCI_LE_ADV_EVT_TYPE_SCAN BIT(1) +#define BT_HCI_LE_ADV_EVT_TYPE_DIRECT BIT(2) +#define BT_HCI_LE_ADV_EVT_TYPE_SCAN_RSP BIT(3) +#define BT_HCI_LE_ADV_EVT_TYPE_LEGACY BIT(4) + +#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS(ev_type) (((ev_type) >> 5) & 0x03) +#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_COMPLETE 0 +#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_PARTIAL 1 +#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_INCOMPLETE 2 + +struct bt_hci_evt_le_ext_advertising_info { + uint16_t evt_type; + bt_addr_le_t addr; + uint8_t prim_phy; + uint8_t sec_phy; + uint8_t sid; + int8_t tx_power; + int8_t rssi; + uint16_t interval; + bt_addr_le_t direct_addr; + uint8_t length; + uint8_t data[0]; +} __packed; +struct bt_hci_evt_le_ext_advertising_report { + uint8_t num_reports; + struct bt_hci_evt_le_ext_advertising_info adv_info[0]; +} __packed; + +#define BT_HCI_EVT_LE_PER_ADV_SYNC_ESTABLISHED 0x0e +struct bt_hci_evt_le_per_adv_sync_established { + uint8_t status; + uint16_t handle; + uint8_t sid; + bt_addr_le_t adv_addr; + uint8_t phy; + uint16_t interval; + uint8_t clock_accuracy; +} __packed; + +#define BT_HCI_EVT_LE_PER_ADVERTISING_REPORT 0x0f +struct bt_hci_evt_le_per_advertising_report { + uint16_t handle; + int8_t tx_power; + int8_t rssi; + uint8_t unused; + uint8_t data_status; + uint8_t length; + uint8_t data[0]; +} __packed; + +#define BT_HCI_EVT_LE_PER_ADV_SYNC_LOST 0x10 +struct bt_hci_evt_le_per_adv_sync_lost { + uint16_t handle; +} __packed; + +#define BT_HCI_EVT_LE_SCAN_TIMEOUT 0x11 + +#define BT_HCI_EVT_LE_ADV_SET_TERMINATED 0x12 +struct bt_hci_evt_le_adv_set_terminated { + uint8_t status; + uint8_t adv_handle; + uint16_t conn_handle; + uint8_t num_completed_ext_adv_evts; +} __packed; + +#define BT_HCI_EVT_LE_SCAN_REQ_RECEIVED 0x13 +struct bt_hci_evt_le_scan_req_received { + uint8_t handle; + bt_addr_le_t addr; +} __packed; + +#define BT_HCI_LE_CHAN_SEL_ALGO_1 0x00 +#define BT_HCI_LE_CHAN_SEL_ALGO_2 0x01 + +#define BT_HCI_EVT_LE_CHAN_SEL_ALGO 0x14 +struct bt_hci_evt_le_chan_sel_algo { + uint16_t handle; + uint8_t chan_sel_algo; +} __packed; + +/* Event mask bits */ + +#define BT_EVT_BIT(n) (1ULL << (n)) + +#define BT_EVT_MASK_INQUIRY_COMPLETE BT_EVT_BIT(0) +#define BT_EVT_MASK_CONN_COMPLETE BT_EVT_BIT(2) +#define BT_EVT_MASK_CONN_REQUEST BT_EVT_BIT(3) +#define BT_EVT_MASK_DISCONN_COMPLETE BT_EVT_BIT(4) +#define BT_EVT_MASK_AUTH_COMPLETE BT_EVT_BIT(5) +#define BT_EVT_MASK_REMOTE_NAME_REQ_COMPLETE BT_EVT_BIT(6) +#define BT_EVT_MASK_ENCRYPT_CHANGE BT_EVT_BIT(7) +#define BT_EVT_MASK_REMOTE_FEATURES BT_EVT_BIT(10) +#define BT_EVT_MASK_REMOTE_VERSION_INFO BT_EVT_BIT(11) +#define BT_EVT_MASK_HARDWARE_ERROR BT_EVT_BIT(15) +#define BT_EVT_MASK_ROLE_CHANGE BT_EVT_BIT(17) +#define BT_EVT_MASK_PIN_CODE_REQ BT_EVT_BIT(21) +#define BT_EVT_MASK_LINK_KEY_REQ BT_EVT_BIT(22) +#define BT_EVT_MASK_LINK_KEY_NOTIFY BT_EVT_BIT(23) +#define BT_EVT_MASK_DATA_BUFFER_OVERFLOW BT_EVT_BIT(25) +#define BT_EVT_MASK_INQUIRY_RESULT_WITH_RSSI BT_EVT_BIT(33) +#define BT_EVT_MASK_REMOTE_EXT_FEATURES BT_EVT_BIT(34) +#define BT_EVT_MASK_SYNC_CONN_COMPLETE BT_EVT_BIT(43) +#define BT_EVT_MASK_EXTENDED_INQUIRY_RESULT BT_EVT_BIT(46) +#define BT_EVT_MASK_ENCRYPT_KEY_REFRESH_COMPLETE BT_EVT_BIT(47) +#define BT_EVT_MASK_IO_CAPA_REQ BT_EVT_BIT(48) +#define BT_EVT_MASK_IO_CAPA_RESP BT_EVT_BIT(49) +#define BT_EVT_MASK_USER_CONFIRM_REQ BT_EVT_BIT(50) +#define BT_EVT_MASK_USER_PASSKEY_REQ BT_EVT_BIT(51) +#define BT_EVT_MASK_SSP_COMPLETE BT_EVT_BIT(53) +#define BT_EVT_MASK_USER_PASSKEY_NOTIFY BT_EVT_BIT(58) +#define BT_EVT_MASK_LE_META_EVENT BT_EVT_BIT(61) + +/* Page 2 */ +#define BT_EVT_MASK_PHY_LINK_COMPLETE BT_EVT_BIT(0) +#define BT_EVT_MASK_CH_SELECTED_COMPLETE BT_EVT_BIT(1) +#define BT_EVT_MASK_DISCONN_PHY_LINK_COMPLETE BT_EVT_BIT(2) +#define BT_EVT_MASK_PHY_LINK_LOSS_EARLY_WARN BT_EVT_BIT(3) +#define BT_EVT_MASK_PHY_LINK_RECOVERY BT_EVT_BIT(4) +#define BT_EVT_MASK_LOG_LINK_COMPLETE BT_EVT_BIT(5) +#define BT_EVT_MASK_DISCONN_LOG_LINK_COMPLETE BT_EVT_BIT(6) +#define BT_EVT_MASK_FLOW_SPEC_MODIFY_COMPLETE BT_EVT_BIT(7) +#define BT_EVT_MASK_NUM_COMPLETE_DATA_BLOCKS BT_EVT_BIT(8) +#define BT_EVT_MASK_AMP_START_TEST BT_EVT_BIT(9) +#define BT_EVT_MASK_AMP_TEST_END BT_EVT_BIT(10) +#define BT_EVT_MASK_AMP_RX_REPORT BT_EVT_BIT(11) +#define BT_EVT_MASK_AMP_SR_MODE_CHANGE_COMPLETE BT_EVT_BIT(12) +#define BT_EVT_MASK_AMP_STATUS_CHANGE BT_EVT_BIT(13) +#define BT_EVT_MASK_TRIGG_CLOCK_CAPTURE BT_EVT_BIT(14) +#define BT_EVT_MASK_SYNCH_TRAIN_COMPLETE BT_EVT_BIT(15) +#define BT_EVT_MASK_SYNCH_TRAIN_RX BT_EVT_BIT(16) +#define BT_EVT_MASK_CL_SLAVE_BC_RX BT_EVT_BIT(17) +#define BT_EVT_MASK_CL_SLAVE_BC_TIMEOUT BT_EVT_BIT(18) +#define BT_EVT_MASK_TRUNC_PAGE_COMPLETE BT_EVT_BIT(19) +#define BT_EVT_MASK_SLAVE_PAGE_RSP_TIMEOUT BT_EVT_BIT(20) +#define BT_EVT_MASK_CL_SLAVE_BC_CH_MAP_CHANGE BT_EVT_BIT(21) +#define BT_EVT_MASK_INQUIRY_RSP_NOT BT_EVT_BIT(22) +#define BT_EVT_MASK_AUTH_PAYLOAD_TIMEOUT_EXP BT_EVT_BIT(23) +#define BT_EVT_MASK_SAM_STATUS_CHANGE BT_EVT_BIT(24) + +#define BT_EVT_MASK_LE_CONN_COMPLETE BT_EVT_BIT(0) +#define BT_EVT_MASK_LE_ADVERTISING_REPORT BT_EVT_BIT(1) +#define BT_EVT_MASK_LE_CONN_UPDATE_COMPLETE BT_EVT_BIT(2) +#define BT_EVT_MASK_LE_REMOTE_FEAT_COMPLETE BT_EVT_BIT(3) +#define BT_EVT_MASK_LE_LTK_REQUEST BT_EVT_BIT(4) +#define BT_EVT_MASK_LE_CONN_PARAM_REQ BT_EVT_BIT(5) +#define BT_EVT_MASK_LE_DATA_LEN_CHANGE BT_EVT_BIT(6) +#define BT_EVT_MASK_LE_P256_PUBLIC_KEY_COMPLETE BT_EVT_BIT(7) +#define BT_EVT_MASK_LE_GENERATE_DHKEY_COMPLETE BT_EVT_BIT(8) +#define BT_EVT_MASK_LE_ENH_CONN_COMPLETE BT_EVT_BIT(9) +#define BT_EVT_MASK_LE_DIRECT_ADV_REPORT BT_EVT_BIT(10) +#define BT_EVT_MASK_LE_PHY_UPDATE_COMPLETE BT_EVT_BIT(11) +#define BT_EVT_MASK_LE_EXT_ADVERTISING_REPORT BT_EVT_BIT(12) +#define BT_EVT_MASK_LE_PER_ADV_SYNC_ESTABLISHED BT_EVT_BIT(13) +#define BT_EVT_MASK_LE_PER_ADVERTISING_REPORT BT_EVT_BIT(14) +#define BT_EVT_MASK_LE_PER_ADV_SYNC_LOST BT_EVT_BIT(15) +#define BT_EVT_MASK_LE_SCAN_TIMEOUT BT_EVT_BIT(16) +#define BT_EVT_MASK_LE_ADV_SET_TERMINATED BT_EVT_BIT(17) +#define BT_EVT_MASK_LE_SCAN_REQ_RECEIVED BT_EVT_BIT(18) +#define BT_EVT_MASK_LE_CHAN_SEL_ALGO BT_EVT_BIT(19) + +// + +#endif /* ZEPHYR_INCLUDE_BLUETOOTH_HCI_H_ */ diff --git a/devices/ble_hci/common-hal/_bleio/hci_include/hci_err.h b/devices/ble_hci/common-hal/_bleio/hci_include/hci_err.h new file mode 100644 index 0000000000..476d3f4638 --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/hci_include/hci_err.h @@ -0,0 +1,92 @@ +/** @file + * @brief Bluetooth Host Control Interface status codes. + */ + +/* + * Copyright (c) 2019 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_BLUETOOTH_HCI_STATUS_H_ +#define ZEPHYR_INCLUDE_BLUETOOTH_HCI_STATUS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** HCI Error Codes, BT Core Spec v5.2 [Vol 1, Part F]. */ +#define BT_HCI_ERR_SUCCESS 0x00 +#define BT_HCI_ERR_UNKNOWN_CMD 0x01 +#define BT_HCI_ERR_UNKNOWN_CONN_ID 0x02 +#define BT_HCI_ERR_HW_FAILURE 0x03 +#define BT_HCI_ERR_PAGE_TIMEOUT 0x04 +#define BT_HCI_ERR_AUTH_FAIL 0x05 +#define BT_HCI_ERR_PIN_OR_KEY_MISSING 0x06 +#define BT_HCI_ERR_MEM_CAPACITY_EXCEEDED 0x07 +#define BT_HCI_ERR_CONN_TIMEOUT 0x08 +#define BT_HCI_ERR_CONN_LIMIT_EXCEEDED 0x09 +#define BT_HCI_ERR_SYNC_CONN_LIMIT_EXCEEDED 0x0a +#define BT_HCI_ERR_CONN_ALREADY_EXISTS 0x0b +#define BT_HCI_ERR_CMD_DISALLOWED 0x0c +#define BT_HCI_ERR_INSUFFICIENT_RESOURCES 0x0d +#define BT_HCI_ERR_INSUFFICIENT_SECURITY 0x0e +#define BT_HCI_ERR_BD_ADDR_UNACCEPTABLE 0x0f +#define BT_HCI_ERR_CONN_ACCEPT_TIMEOUT 0x10 +#define BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL 0x11 +#define BT_HCI_ERR_INVALID_PARAM 0x12 +#define BT_HCI_ERR_REMOTE_USER_TERM_CONN 0x13 +#define BT_HCI_ERR_REMOTE_LOW_RESOURCES 0x14 +#define BT_HCI_ERR_REMOTE_POWER_OFF 0x15 +#define BT_HCI_ERR_LOCALHOST_TERM_CONN 0x16 +#define BT_HCI_ERR_REPEATED_ATTEMPTS 0x17 +#define BT_HCI_ERR_PAIRING_NOT_ALLOWED 0x18 +#define BT_HCI_ERR_UNKNOWN_LMP_PDU 0x19 +#define BT_HCI_ERR_UNSUPP_REMOTE_FEATURE 0x1a +#define BT_HCI_ERR_SCO_OFFSET_REJECTED 0x1b +#define BT_HCI_ERR_SCO_INTERVAL_REJECTED 0x1c +#define BT_HCI_ERR_SCO_AIR_MODE_REJECTED 0x1d +#define BT_HCI_ERR_INVALID_LL_PARAM 0x1e +#define BT_HCI_ERR_UNSPECIFIED 0x1f +#define BT_HCI_ERR_UNSUPP_LL_PARAM_VAL 0x20 +#define BT_HCI_ERR_ROLE_CHANGE_NOT_ALLOWED 0x21 +#define BT_HCI_ERR_LL_RESP_TIMEOUT 0x22 +#define BT_HCI_ERR_LL_PROC_COLLISION 0x23 +#define BT_HCI_ERR_LMP_PDU_NOT_ALLOWED 0x24 +#define BT_HCI_ERR_ENC_MODE_NOT_ACCEPTABLE 0x25 +#define BT_HCI_ERR_LINK_KEY_CANNOT_BE_CHANGED 0x26 +#define BT_HCI_ERR_REQUESTED_QOS_NOT_SUPPORTED 0x27 +#define BT_HCI_ERR_INSTANT_PASSED 0x28 +#define BT_HCI_ERR_PAIRING_NOT_SUPPORTED 0x29 +#define BT_HCI_ERR_DIFF_TRANS_COLLISION 0x2a +#define BT_HCI_ERR_QOS_UNACCEPTABLE_PARAM 0x2c +#define BT_HCI_ERR_QOS_REJECTED 0x2d +#define BT_HCI_ERR_CHAN_ASSESS_NOT_SUPPORTED 0x2e +#define BT_HCI_ERR_INSUFF_SECURITY 0x2f +#define BT_HCI_ERR_PARAM_OUT_OF_MANDATORY_RANGE 0x30 +#define BT_HCI_ERR_ROLE_SWITCH_PENDING 0x32 +#define BT_HCI_ERR_RESERVED_SLOT_VIOLATION 0x34 +#define BT_HCI_ERR_ROLE_SWITCH_FAILED 0x35 +#define BT_HCI_ERR_EXT_INQ_RESP_TOO_LARGE 0x36 +#define BT_HCI_ERR_SIMPLE_PAIR_NOT_SUPP_BY_HOST 0x37 +#define BT_HCI_ERR_HOST_BUSY_PAIRING 0x38 +#define BT_HCI_ERR_CONN_REJECTED_DUE_TO_NO_CHAN 0x39 +#define BT_HCI_ERR_CONTROLLER_BUSY 0x3a +#define BT_HCI_ERR_UNACCEPT_CONN_PARAM 0x3b +#define BT_HCI_ERR_ADV_TIMEOUT 0x3c +#define BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL 0x3d +#define BT_HCI_ERR_CONN_FAIL_TO_ESTAB 0x3e +#define BT_HCI_ERR_MAC_CONN_FAILED 0x3f +#define BT_HCI_ERR_CLOCK_ADJUST_REJECTED 0x40 +#define BT_HCI_ERR_SUBMAP_NOT_DEFINED 0x41 +#define BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER 0x42 +#define BT_HCI_ERR_LIMIT_REACHED 0x43 +#define BT_HCI_ERR_OP_CANCELLED_BY_HOST 0x44 +#define BT_HCI_ERR_PACKET_TOO_LONG 0x45 + +#define BT_HCI_ERR_AUTHENTICATION_FAIL __DEPRECATED_MACRO BT_HCI_ERR_AUTH_FAIL + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_BLUETOOTH_HCI_STATUS_H_ */ diff --git a/devices/ble_hci/common-hal/_bleio/hci_include/hci_raw.h b/devices/ble_hci/common-hal/_bleio/hci_include/hci_raw.h new file mode 100644 index 0000000000..030fb0ca3c --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/hci_include/hci_raw.h @@ -0,0 +1,152 @@ +/** @file + * @brief Bluetooth HCI RAW channel handling + */ + +/* + * Copyright (c) 2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_BLUETOOTH_HCI_RAW_H_ +#define ZEPHYR_INCLUDE_BLUETOOTH_HCI_RAW_H_ + +/** + * @brief HCI RAW channel + * @defgroup hci_raw HCI RAW channel + * @ingroup bluetooth + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(CONFIG_BT_CTLR_TX_BUFFER_SIZE) +#define BT_L2CAP_MTU (CONFIG_BT_CTLR_TX_BUFFER_SIZE - BT_L2CAP_HDR_SIZE) +#else +#define BT_L2CAP_MTU 65 /* 64-byte public key + opcode */ +#endif /* CONFIG_BT_CTLR */ + +/** Data size needed for ACL buffers */ +#define BT_BUF_ACL_SIZE BT_L2CAP_BUF_SIZE(BT_L2CAP_MTU) + +#if defined(CONFIG_BT_CTLR_TX_BUFFERS) +#define BT_HCI_ACL_COUNT CONFIG_BT_CTLR_TX_BUFFERS +#else +#define BT_HCI_ACL_COUNT 6 +#endif + +#define BT_BUF_TX_SIZE MAX(BT_BUF_RX_SIZE, BT_BUF_ACL_SIZE) + +/** @brief Send packet to the Bluetooth controller + * + * Send packet to the Bluetooth controller. Caller needs to + * implement netbuf pool. + * + * @param buf netbuf packet to be send + * + * @return Zero on success or (negative) error code otherwise. + */ +int bt_send(struct net_buf *buf); + +enum { + /** Passthrough mode + * + * While in this mode the buffers are passed as is between the stack + * and the driver. + */ + BT_HCI_RAW_MODE_PASSTHROUGH = 0x00, + + /** H:4 mode + * + * While in this mode H:4 headers will added into the buffers + * according to the buffer type when coming from the stack and will be + * removed and used to set the buffer type. + */ + BT_HCI_RAW_MODE_H4 = 0x01, +}; + +/** @brief Set Bluetooth RAW channel mode + * + * Set access mode of Bluetooth RAW channel. + * + * @param mode Access mode. + * + * @return Zero on success or (negative) error code otherwise. + */ +int bt_hci_raw_set_mode(uint8_t mode); + +/** @brief Get Bluetooth RAW channel mode + * + * Get access mode of Bluetooth RAW channel. + * + * @return Access mode. + */ +uint8_t bt_hci_raw_get_mode(void); + +#define BT_HCI_ERR_EXT_HANDLED 0xff + +/** Helper macro to define a command extension + * + * @param _op Opcode of the command. + * @param _min_len Minimal length of the command. + * @param _func Handler function to be called. + */ +#define BT_HCI_RAW_CMD_EXT(_op, _min_len, _func) \ + { \ + .op = _op, \ + .min_len = _min_len, \ + .func = _func, \ + } + +struct bt_hci_raw_cmd_ext { + /** Opcode of the command */ + uint16_t op; + + /** Minimal length of the command */ + size_t min_len; + + /** Handler function. + * + * Handler function to be called when a command is intercepted. + * + * @param buf Buffer containing the command. + * + * @return HCI Status code or BT_HCI_ERR_EXT_HANDLED if command has + * been handled already and a response has been sent as oppose to + * BT_HCI_ERR_SUCCESS which just indicates that the command can be + * sent to the controller to be processed. + */ + uint8_t (*func)(struct net_buf *buf); +}; + +/** @brief Register Bluetooth RAW command extension table + * + * Register Bluetooth RAW channel command extension table, opcodes in this + * table are intercepted to sent to the handler function. + * + * @param cmds Pointer to the command extension table. + * @param size Size of the command extension table. + */ +void bt_hci_raw_cmd_ext_register(struct bt_hci_raw_cmd_ext *cmds, size_t size); + +/** @brief Enable Bluetooth RAW channel: + * + * Enable Bluetooth RAW HCI channel. + * + * @param rx_queue netbuf queue where HCI packets received from the Bluetooth + * controller are to be queued. The queue is defined in the caller while + * the available buffers pools are handled in the stack. + * + * @return Zero on success or (negative) error code otherwise. + */ +int bt_enable_raw(struct k_fifo *rx_queue); + +#ifdef __cplusplus +} +#endif +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_BLUETOOTH_HCI_RAW_H_ */ diff --git a/devices/ble_hci/common-hal/_bleio/hci_include/hci_vs.h b/devices/ble_hci/common-hal/_bleio/hci_include/hci_vs.h new file mode 100644 index 0000000000..e4f94b6a83 --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/hci_include/hci_vs.h @@ -0,0 +1,379 @@ +/* hci_vs.h - Bluetooth Host Control Interface Vendor Specific definitions */ + +/* + * Copyright (c) 2017-2018 Nordic Semiconductor ASA + * Copyright (c) 2015-2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_BLUETOOTH_HCI_VS_H_ +#define ZEPHYR_INCLUDE_BLUETOOTH_HCI_VS_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define BT_VS_CMD_BIT_VERSION 0 +#define BT_VS_CMD_BIT_SUP_CMD 1 +#define BT_VS_CMD_BIT_SUP_FEAT 2 +#define BT_VS_CMD_BIT_SET_EVT_MASK 3 +#define BT_VS_CMD_BIT_RESET 4 +#define BT_VS_CMD_BIT_WRITE_BDADDR 5 +#define BT_VS_CMD_BIT_SET_TRACE_ENABLE 6 +#define BT_VS_CMD_BIT_READ_BUILD_INFO 7 +#define BT_VS_CMD_BIT_READ_STATIC_ADDRS 8 +#define BT_VS_CMD_BIT_READ_KEY_ROOTS 9 +#define BT_VS_CMD_BIT_READ_CHIP_TEMP 10 +#define BT_VS_CMD_BIT_READ_HOST_STACK_CMD 11 +#define BT_VS_CMD_BIT_SET_SCAN_REP_ENABLE 12 +#define BT_VS_CMD_BIT_WRITE_TX_POWER 13 +#define BT_VS_CMD_BIT_READ_TX_POWER 14 + +#define BT_VS_CMD_SUP_FEAT(cmd) BT_LE_FEAT_TEST(cmd, \ + BT_VS_CMD_BIT_SUP_FEAT) +#define BT_VS_CMD_READ_STATIC_ADDRS(cmd) BT_LE_FEAT_TEST(cmd, \ + BT_VS_CMD_BIT_READ_STATIC_ADDRS) +#define BT_VS_CMD_READ_KEY_ROOTS(cmd) BT_LE_FEAT_TEST(cmd, \ + BT_VS_CMD_BIT_READ_KEY_ROOTS) + +#define BT_HCI_VS_HW_PLAT_INTEL 0x0001 +#define BT_HCI_VS_HW_PLAT_NORDIC 0x0002 +#define BT_HCI_VS_HW_PLAT_NXP 0x0003 + +#define BT_HCI_VS_HW_VAR_NORDIC_NRF51X 0x0001 +#define BT_HCI_VS_HW_VAR_NORDIC_NRF52X 0x0002 +#define BT_HCI_VS_HW_VAR_NORDIC_NRF53X 0x0003 + +#define BT_HCI_VS_FW_VAR_STANDARD_CTLR 0x0001 +#define BT_HCI_VS_FW_VAR_VS_CTLR 0x0002 +#define BT_HCI_VS_FW_VAR_FW_LOADER 0x0003 +#define BT_HCI_VS_FW_VAR_RESCUE_IMG 0x0004 +#define BT_HCI_OP_VS_READ_VERSION_INFO BT_OP(BT_OGF_VS, 0x0001) +struct bt_hci_rp_vs_read_version_info { + uint8_t status; + uint16_t hw_platform; + uint16_t hw_variant; + uint8_t fw_variant; + uint8_t fw_version; + uint16_t fw_revision; + uint32_t fw_build; +} __packed; + +#define BT_HCI_OP_VS_READ_SUPPORTED_COMMANDS BT_OP(BT_OGF_VS, 0x0002) +struct bt_hci_rp_vs_read_supported_commands { + uint8_t status; + uint8_t commands[64]; +} __packed; + +#define BT_HCI_OP_VS_READ_SUPPORTED_FEATURES BT_OP(BT_OGF_VS, 0x0003) +struct bt_hci_rp_vs_read_supported_features { + uint8_t status; + uint8_t features[8]; +} __packed; + +#define BT_HCI_OP_VS_SET_EVENT_MASK BT_OP(BT_OGF_VS, 0x0004) +struct bt_hci_cp_vs_set_event_mask { + uint8_t event_mask[8]; +} __packed; + +#define BT_HCI_VS_RESET_SOFT 0x00 +#define BT_HCI_VS_RESET_HARD 0x01 +#define BT_HCI_OP_VS_RESET BT_OP(BT_OGF_VS, 0x0005) +struct bt_hci_cp_vs_reset { + uint8_t type; +} __packed; + +#define BT_HCI_OP_VS_WRITE_BD_ADDR BT_OP(BT_OGF_VS, 0x0006) +struct bt_hci_cp_vs_write_bd_addr { + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_VS_TRACE_DISABLED 0x00 +#define BT_HCI_VS_TRACE_ENABLED 0x01 + +#define BT_HCI_VS_TRACE_HCI_EVTS 0x00 +#define BT_HCI_VS_TRACE_VDC 0x01 +#define BT_HCI_OP_VS_SET_TRACE_ENABLE BT_OP(BT_OGF_VS, 0x0007) +struct bt_hci_cp_vs_set_trace_enable { + uint8_t enable; + uint8_t type; +} __packed; + +#define BT_HCI_OP_VS_READ_BUILD_INFO BT_OP(BT_OGF_VS, 0x0008) +struct bt_hci_rp_vs_read_build_info { + uint8_t status; + uint8_t info[0]; +} __packed; + +struct bt_hci_vs_static_addr { + bt_addr_t bdaddr; + uint8_t ir[16]; +} __packed; + +#define BT_HCI_OP_VS_READ_STATIC_ADDRS BT_OP(BT_OGF_VS, 0x0009) +struct bt_hci_rp_vs_read_static_addrs { + uint8_t status; + uint8_t num_addrs; + struct bt_hci_vs_static_addr a[0]; +} __packed; + +#define BT_HCI_OP_VS_READ_KEY_HIERARCHY_ROOTS BT_OP(BT_OGF_VS, 0x000a) +struct bt_hci_rp_vs_read_key_hierarchy_roots { + uint8_t status; + uint8_t ir[16]; + uint8_t er[16]; +} __packed; + +#define BT_HCI_OP_VS_READ_CHIP_TEMP BT_OP(BT_OGF_VS, 0x000b) +struct bt_hci_rp_vs_read_chip_temp { + uint8_t status; + int8_t temps; +} __packed; + +struct bt_hci_vs_cmd { + uint16_t vendor_id; + uint16_t opcode_base; +} __packed; + +#define BT_HCI_VS_VID_ANDROID 0x0001 +#define BT_HCI_VS_VID_MICROSOFT 0x0002 +#define BT_HCI_OP_VS_READ_HOST_STACK_CMDS BT_OP(BT_OGF_VS, 0x000c) +struct bt_hci_rp_vs_read_host_stack_cmds { + uint8_t status; + uint8_t num_cmds; + struct bt_hci_vs_cmd c[0]; +} __packed; + +#define BT_HCI_VS_SCAN_REQ_REPORTS_DISABLED 0x00 +#define BT_HCI_VS_SCAN_REQ_REPORTS_ENABLED 0x01 +#define BT_HCI_OP_VS_SET_SCAN_REQ_REPORTS BT_OP(BT_OGF_VS, 0x000d) +struct bt_hci_cp_vs_set_scan_req_reports { + uint8_t enable; +} __packed; + +#define BT_HCI_VS_LL_HANDLE_TYPE_ADV 0x00 +#define BT_HCI_VS_LL_HANDLE_TYPE_SCAN 0x01 +#define BT_HCI_VS_LL_HANDLE_TYPE_CONN 0x02 +#define BT_HCI_VS_LL_TX_POWER_LEVEL_NO_PREF 0x7F +#define BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL BT_OP(BT_OGF_VS, 0x000e) +struct bt_hci_cp_vs_write_tx_power_level { + uint8_t handle_type; + uint16_t handle; + int8_t tx_power_level; +} __packed; + +struct bt_hci_rp_vs_write_tx_power_level { + uint8_t status; + uint8_t handle_type; + uint16_t handle; + int8_t selected_tx_power; +} __packed; + +#define BT_HCI_OP_VS_READ_TX_POWER_LEVEL BT_OP(BT_OGF_VS, 0x000f) +struct bt_hci_cp_vs_read_tx_power_level { + uint8_t handle_type; + uint16_t handle; +} __packed; + +struct bt_hci_rp_vs_read_tx_power_level { + uint8_t status; + uint8_t handle_type; + uint16_t handle; + int8_t tx_power_level; +} __packed; + +#define BT_HCI_OP_VS_READ_USB_TRANSPORT_MODE BT_OP(BT_OGF_VS, 0x0010) + +struct bt_hci_rp_vs_read_usb_transport_mode { + uint8_t status; + uint8_t num_supported_modes; + uint8_t supported_mode[0]; +} __packed; + +#define BT_HCI_VS_USB_H2_MODE 0x00 +#define BT_HCI_VS_USB_H4_MODE 0x01 + +#define BT_HCI_OP_VS_SET_USB_TRANSPORT_MODE BT_OP(BT_OGF_VS, 0x0011) + +struct bt_hci_cp_vs_set_usb_transport_mode { + uint8_t mode; +} __packed; + +/* Events */ + +struct bt_hci_evt_vs { + uint8_t subevent; +} __packed; + +#define BT_HCI_EVT_VS_FATAL_ERROR 0x02 +struct bt_hci_evt_vs_fatal_error { + uint64_t pc; + uint8_t err_info[0]; +} __packed; + +#define BT_HCI_VS_TRACE_LMP_TX 0x01 +#define BT_HCI_VS_TRACE_LMP_RX 0x02 +#define BT_HCI_VS_TRACE_LLCP_TX 0x03 +#define BT_HCI_VS_TRACE_LLCP_RX 0x04 +#define BT_HCI_VS_TRACE_LE_CONN_IND 0x05 +#define BT_HCI_EVT_VS_TRACE_INFO 0x03 +struct bt_hci_evt_vs_trace_info { + uint8_t type; + uint8_t data[0]; +} __packed; + +#define BT_HCI_EVT_VS_SCAN_REQ_RX 0x04 +struct bt_hci_evt_vs_scan_req_rx { + bt_addr_le_t addr; + int8_t rssi; +} __packed; + +/* Event mask bits */ + +#define BT_EVT_MASK_VS_FATAL_ERROR BT_EVT_BIT(1) +#define BT_EVT_MASK_VS_TRACE_INFO BT_EVT_BIT(2) +#define BT_EVT_MASK_VS_SCAN_REQ_RX BT_EVT_BIT(3) + +/* Mesh HCI commands */ +#define BT_HCI_MESH_REVISION 0x01 + +#define BT_HCI_OP_VS_MESH BT_OP(BT_OGF_VS, 0x0042) +#define BT_HCI_MESH_EVT_PREFIX 0xF0 + +struct bt_hci_cp_mesh { + uint8_t opcode; +} __packed; + +#define BT_HCI_OC_MESH_GET_OPTS 0x00 +struct bt_hci_rp_mesh_get_opts { + uint8_t status; + uint8_t opcode; + uint8_t revision; + uint8_t ch_map; + int8_t min_tx_power; + int8_t max_tx_power; + uint8_t max_scan_filter; + uint8_t max_filter_pattern; + uint8_t max_adv_slot; + uint8_t max_tx_window; + uint8_t evt_prefix_len; + uint8_t evt_prefix; +} __packed; + +#define BT_HCI_MESH_PATTERN_LEN_MAX 0x0f + +#define BT_HCI_OC_MESH_SET_SCAN_FILTER 0x01 +struct bt_hci_mesh_pattern { + uint8_t pattern_len; + uint8_t pattern[0]; +} __packed; + +struct bt_hci_cp_mesh_set_scan_filter { + uint8_t scan_filter; + uint8_t filter_dup; + uint8_t num_patterns; + struct bt_hci_mesh_pattern patterns[0]; +} __packed; +struct bt_hci_rp_mesh_set_scan_filter { + uint8_t status; + uint8_t opcode; + uint8_t scan_filter; +} __packed; + +#define BT_HCI_OC_MESH_ADVERTISE 0x02 +struct bt_hci_cp_mesh_advertise { + uint8_t adv_slot; + uint8_t own_addr_type; + bt_addr_t random_addr; + uint8_t ch_map; + int8_t tx_power; + uint8_t min_tx_delay; + uint8_t max_tx_delay; + uint8_t retx_count; + uint8_t retx_interval; + uint8_t scan_delay; + uint16_t scan_duration; + uint8_t scan_filter; + uint8_t data_len; + uint8_t data[31]; +} __packed; +struct bt_hci_rp_mesh_advertise { + uint8_t status; + uint8_t opcode; + uint8_t adv_slot; +} __packed; + +#define BT_HCI_OC_MESH_ADVERTISE_TIMED 0x03 +struct bt_hci_cp_mesh_advertise_timed { + uint8_t adv_slot; + uint8_t own_addr_type; + bt_addr_t random_addr; + uint8_t ch_map; + int8_t tx_power; + uint8_t retx_count; + uint8_t retx_interval; + uint32_t instant; + uint16_t tx_delay; + uint16_t tx_window; + uint8_t data_len; + uint8_t data[31]; +} __packed; +struct bt_hci_rp_mesh_advertise_timed { + uint8_t status; + uint8_t opcode; + uint8_t adv_slot; +} __packed; + +#define BT_HCI_OC_MESH_ADVERTISE_CANCEL 0x04 +struct bt_hci_cp_mesh_advertise_cancel { + uint8_t adv_slot; +} __packed; +struct bt_hci_rp_mesh_advertise_cancel { + uint8_t status; + uint8_t opcode; + uint8_t adv_slot; +} __packed; + +#define BT_HCI_OC_MESH_SET_SCANNING 0x05 +struct bt_hci_cp_mesh_set_scanning { + uint8_t enable; + uint8_t ch_map; + uint8_t scan_filter; +} __packed; +struct bt_hci_rp_mesh_set_scanning { + uint8_t status; + uint8_t opcode; +} __packed; + +/* Events */ +struct bt_hci_evt_mesh { + uint8_t prefix; + uint8_t subevent; +} __packed; + +#define BT_HCI_EVT_MESH_ADV_COMPLETE 0x00 +struct bt_hci_evt_mesh_adv_complete { + uint8_t adv_slot; +} __packed; + +#define BT_HCI_EVT_MESH_SCANNING_REPORT 0x01 +struct bt_hci_evt_mesh_scan_report { + bt_addr_le_t addr; + uint8_t chan; + int8_t rssi; + uint32_t instant; + uint8_t data_len; + uint8_t data[0]; +} __packed; +struct bt_hci_evt_mesh_scanning_report { + uint8_t num_reports; + struct bt_hci_evt_mesh_scan_report reports[0]; +} __packed; + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_BLUETOOTH_HCI_VS_H_ */ diff --git a/devices/ble_hci/common-hal/_bleio/hci_include/l2cap_internal.h b/devices/ble_hci/common-hal/_bleio/hci_include/l2cap_internal.h new file mode 100644 index 0000000000..bed311cf3c --- /dev/null +++ b/devices/ble_hci/common-hal/_bleio/hci_include/l2cap_internal.h @@ -0,0 +1,230 @@ +// CircuitPython: Adapted from Zephyr include file. + +/** @file + * @brief Internal APIs for Bluetooth L2CAP handling. + */ + +/* + * Copyright (c) 2015-2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +// for __packed +#include + +enum l2cap_conn_list_action { + BT_L2CAP_CHAN_LOOKUP, + BT_L2CAP_CHAN_DETACH, +}; + +#define BT_L2CAP_CID_BR_SIG 0x0001 +#define BT_L2CAP_CID_ATT 0x0004 +#define BT_L2CAP_CID_LE_SIG 0x0005 +#define BT_L2CAP_CID_SMP 0x0006 +#define BT_L2CAP_CID_BR_SMP 0x0007 + +#define BT_L2CAP_PSM_RFCOMM 0x0003 + +struct bt_l2cap_hdr { + uint16_t len; + uint16_t cid; +} __packed; + +struct bt_l2cap_sig_hdr { + uint8_t code; + uint8_t ident; + uint16_t len; +} __packed; + +#define BT_L2CAP_REJ_NOT_UNDERSTOOD 0x0000 +#define BT_L2CAP_REJ_MTU_EXCEEDED 0x0001 +#define BT_L2CAP_REJ_INVALID_CID 0x0002 + +#define BT_L2CAP_CMD_REJECT 0x01 +struct bt_l2cap_cmd_reject { + uint16_t reason; + uint8_t data[0]; +} __packed; + +struct bt_l2cap_cmd_reject_cid_data { + uint16_t scid; + uint16_t dcid; +} __packed; + +#define BT_L2CAP_CONN_REQ 0x02 +struct bt_l2cap_conn_req { + uint16_t psm; + uint16_t scid; +} __packed; + +/* command statuses in reposnse */ +#define BT_L2CAP_CS_NO_INFO 0x0000 +#define BT_L2CAP_CS_AUTHEN_PEND 0x0001 + +/* valid results in conn response on BR/EDR */ +#define BT_L2CAP_BR_SUCCESS 0x0000 +#define BT_L2CAP_BR_PENDING 0x0001 +#define BT_L2CAP_BR_ERR_PSM_NOT_SUPP 0x0002 +#define BT_L2CAP_BR_ERR_SEC_BLOCK 0x0003 +#define BT_L2CAP_BR_ERR_NO_RESOURCES 0x0004 +#define BT_L2CAP_BR_ERR_INVALID_SCID 0x0006 +#define BT_L2CAP_BR_ERR_SCID_IN_USE 0x0007 + +#define BT_L2CAP_CONN_RSP 0x03 +struct bt_l2cap_conn_rsp { + uint16_t dcid; + uint16_t scid; + uint16_t result; + uint16_t status; +} __packed; + +#define BT_L2CAP_CONF_SUCCESS 0x0000 +#define BT_L2CAP_CONF_UNACCEPT 0x0001 +#define BT_L2CAP_CONF_REJECT 0x0002 + +#define BT_L2CAP_CONF_REQ 0x04 +struct bt_l2cap_conf_req { + uint16_t dcid; + uint16_t flags; + uint8_t data[0]; +} __packed; + +#define BT_L2CAP_CONF_RSP 0x05 +struct bt_l2cap_conf_rsp { + uint16_t scid; + uint16_t flags; + uint16_t result; + uint8_t data[0]; +} __packed; + +/* Option type used by MTU config request data */ +#define BT_L2CAP_CONF_OPT_MTU 0x01 +/* Options bits selecting most significant bit (hint) in type field */ +#define BT_L2CAP_CONF_HINT 0x80 +#define BT_L2CAP_CONF_MASK 0x7f + +struct bt_l2cap_conf_opt { + uint8_t type; + uint8_t len; + uint8_t data[0]; +} __packed; + +#define BT_L2CAP_DISCONN_REQ 0x06 +struct bt_l2cap_disconn_req { + uint16_t dcid; + uint16_t scid; +} __packed; + +#define BT_L2CAP_DISCONN_RSP 0x07 +struct bt_l2cap_disconn_rsp { + uint16_t dcid; + uint16_t scid; +} __packed; + +#define BT_L2CAP_INFO_FEAT_MASK 0x0002 +#define BT_L2CAP_INFO_FIXED_CHAN 0x0003 + +#define BT_L2CAP_INFO_REQ 0x0a +struct bt_l2cap_info_req { + uint16_t type; +} __packed; + +/* info result */ +#define BT_L2CAP_INFO_SUCCESS 0x0000 +#define BT_L2CAP_INFO_NOTSUPP 0x0001 + +#define BT_L2CAP_INFO_RSP 0x0b +struct bt_l2cap_info_rsp { + uint16_t type; + uint16_t result; + uint8_t data[0]; +} __packed; + +#define BT_L2CAP_CONN_PARAM_REQ 0x12 +struct bt_l2cap_conn_param_req { + uint16_t min_interval; + uint16_t max_interval; + uint16_t latency; + uint16_t timeout; +} __packed; + +#define BT_L2CAP_CONN_PARAM_ACCEPTED 0x0000 +#define BT_L2CAP_CONN_PARAM_REJECTED 0x0001 + +#define BT_L2CAP_CONN_PARAM_RSP 0x13 +struct bt_l2cap_conn_param_rsp { + uint16_t result; +} __packed; + +#define BT_L2CAP_LE_CONN_REQ 0x14 +struct bt_l2cap_le_conn_req { + uint16_t psm; + uint16_t scid; + uint16_t mtu; + uint16_t mps; + uint16_t credits; +} __packed; + +/* valid results in conn response on LE */ +#define BT_L2CAP_LE_SUCCESS 0x0000 +#define BT_L2CAP_LE_ERR_PSM_NOT_SUPP 0x0002 +#define BT_L2CAP_LE_ERR_NO_RESOURCES 0x0004 +#define BT_L2CAP_LE_ERR_AUTHENTICATION 0x0005 +#define BT_L2CAP_LE_ERR_AUTHORIZATION 0x0006 +#define BT_L2CAP_LE_ERR_KEY_SIZE 0x0007 +#define BT_L2CAP_LE_ERR_ENCRYPTION 0x0008 +#define BT_L2CAP_LE_ERR_INVALID_SCID 0x0009 +#define BT_L2CAP_LE_ERR_SCID_IN_USE 0x000A +#define BT_L2CAP_LE_ERR_UNACCEPT_PARAMS 0x000B +#define BT_L2CAP_LE_ERR_INVALID_PARAMS 0x000C + +#define BT_L2CAP_LE_CONN_RSP 0x15 +struct bt_l2cap_le_conn_rsp { + uint16_t dcid; + uint16_t mtu; + uint16_t mps; + uint16_t credits; + uint16_t result; +} __packed; + +#define BT_L2CAP_LE_CREDITS 0x16 +struct bt_l2cap_le_credits { + uint16_t cid; + uint16_t credits; +} __packed; + +#define BT_L2CAP_ECRED_CONN_REQ 0x17 +struct bt_l2cap_ecred_conn_req { + uint16_t psm; + uint16_t mtu; + uint16_t mps; + uint16_t credits; + uint16_t scid[0]; +} __packed; + +#define BT_L2CAP_ECRED_CONN_RSP 0x18 +struct bt_l2cap_ecred_conn_rsp { + uint16_t mtu; + uint16_t mps; + uint16_t credits; + uint16_t result; + uint16_t dcid[0]; +} __packed; + +#define BT_L2CAP_ECRED_RECONF_REQ 0x19 +struct bt_l2cap_ecred_reconf_req { + uint16_t mtu; + uint16_t mps; + uint16_t scid[0]; +} __packed; + +#define BT_L2CAP_RECONF_SUCCESS 0x0000 +#define BT_L2CAP_RECONF_INVALID_MTU 0x0001 +#define BT_L2CAP_RECONF_INVALID_MPS 0x0002 + +#define BT_L2CAP_ECRED_RECONF_RSP 0x1a +struct bt_l2cap_ecred_reconf_rsp { + uint16_t result; +} __packed; diff --git a/devices/ble_hci/supervisor/bluetooth.c b/devices/ble_hci/supervisor/bluetooth.c new file mode 100644 index 0000000000..83a46728e5 --- /dev/null +++ b/devices/ble_hci/supervisor/bluetooth.c @@ -0,0 +1,29 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if CIRCUITPY_BLE_FILE_SERVICE +#error CIRCUITPY_BLE_FILE_SERVICE not implemented for CIRCUITPY_BLEIO_HCI +#endif diff --git a/devices/ble_hci/supervisor/bluetooth.h b/devices/ble_hci/supervisor/bluetooth.h new file mode 100644 index 0000000000..03645829b1 --- /dev/null +++ b/devices/ble_hci/supervisor/bluetooth.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_DEVICE_BLE_HCI_SUPERVISOR_BLUETOOTH_H +#define MICROPY_INCLUDED_DEVICE_BLE_HCI_SUPERVISOR_BLUETOOTH_H + +void supervisor_start_bluetooth(void); +bool supervisor_bluetooth_hook(ble_evt_t *ble_evt); +void supervisor_bluetooth_background(void); + +#endif // MICROPY_INCLUDED_DEVICE_BLE_HCI_SUPERVISOR_BLUETOOTH_H diff --git a/docs/porting.rst b/docs/porting.rst index db4ae76262..6cd59fefb1 100644 --- a/docs/porting.rst +++ b/docs/porting.rst @@ -51,10 +51,15 @@ as a natural "TODO" list. An example minimal build list is shown below: .. code-block:: makefile # These modules are implemented in ports//common-hal: - CIRCUITPY_MICROCONTROLLER = 0 # Typically the first module to create - CIRCUITPY_DIGITALIO = 0 # Typically the second module to create + + # Typically the first module to create + CIRCUITPY_MICROCONTROLLER = 0 + # Typically the second module to create + CIRCUITPY_DIGITALIO = 0 + # Other modules: CIRCUITPY_ANALOGIO = 0 CIRCUITPY_BUSIO = 0 + CIRCUITPY_COUNTIO = 0 CIRCUITPY_NEOPIXEL_WRITE = 0 CIRCUITPY_PULSEIO = 0 CIRCUITPY_OS = 0 @@ -63,22 +68,34 @@ as a natural "TODO" list. An example minimal build list is shown below: CIRCUITPY_AUDIOIO = 0 CIRCUITPY_ROTARYIO = 0 CIRCUITPY_RTC = 0 + CIRCUITPY_SDCARDIO = 0 + CIRCUITPY_FRAMEBUFFERIO = 0 CIRCUITPY_FREQUENCYIO = 0 CIRCUITPY_I2CPERIPHERAL = 0 - CIRCUITPY_DISPLAYIO = 0 # Requires SPI, PulseIO (stub ok) + # Requires SPI, PulseIO (stub ok): + CIRCUITPY_DISPLAYIO = 0 # These modules are implemented in shared-module/ - they can be included in # any port once their prerequisites in common-hal are complete. - CIRCUITPY_BITBANGIO = 0 # Requires DigitalIO - CIRCUITPY_GAMEPAD = 0 # Requires DigitalIO - CIRCUITPY_PIXELBUF = 0 # Requires neopixel_write or SPI (dotstar) - CIRCUITPY_RANDOM = 0 # Requires OS - CIRCUITPY_STORAGE = 0 # Requires OS, filesystem - CIRCUITPY_TOUCHIO = 0 # Requires Microcontroller - CIRCUITPY_USB_HID = 0 # Requires USB - CIRCUITPY_USB_MIDI = 0 # Requires USB - CIRCUITPY_REQUIRE_I2C_PULLUPS = 0 # Does nothing without I2C - CIRCUITPY_ULAB = 0 # No requirements, but takes extra flash + # Requires DigitalIO: + CIRCUITPY_BITBANGIO = 0 + # Requires DigitalIO + CIRCUITPY_GAMEPAD = 0 + # Requires neopixel_write or SPI (dotstar) + CIRCUITPY_PIXELBUF = 0 + # Requires OS + CIRCUITPY_RANDOM = 0 + # Requires OS, filesystem + CIRCUITPY_STORAGE = 0 + # Requires Microcontroller + CIRCUITPY_TOUCHIO = 0 + # Requires USB + CIRCUITPY_USB_HID = 0 + CIRCUITPY_USB_MIDI = 0 + # Does nothing without I2C + CIRCUITPY_REQUIRE_I2C_PULLUPS = 0 + # No requirements, but takes extra flash + CIRCUITPY_ULAB = 0 Step 2: Init -------------- diff --git a/docs/shared_bindings_matrix.py b/docs/shared_bindings_matrix.py index 7b96c14f29..f38c0b64a0 100644 --- a/docs/shared_bindings_matrix.py +++ b/docs/shared_bindings_matrix.py @@ -28,6 +28,7 @@ import re import subprocess import sys +from concurrent.futures import ThreadPoolExecutor SUPPORTED_PORTS = ['atmel-samd', 'esp32s2', 'litex', 'mimxrt10xx', 'nrf', 'stm'] @@ -43,7 +44,7 @@ def get_shared_bindings(): """ Get a list of modules in shared-bindings based on folder names """ shared_bindings_dir = get_circuitpython_root_dir() / "shared-bindings" - return [item.name for item in shared_bindings_dir.iterdir()] + return [item.name for item in shared_bindings_dir.iterdir()] + ["ulab"] def read_mpconfig(): @@ -131,38 +132,46 @@ def lookup_setting(settings, key, default=''): key = value[2:-1] return value +def all_ports_all_boards(ports=SUPPORTED_PORTS): + for port in ports: + + port_dir = get_circuitpython_root_dir() / "ports" / port + for entry in (port_dir / "boards").iterdir(): + if not entry.is_dir(): + continue + yield (port, entry) + def support_matrix_by_board(use_branded_name=True): """ Compiles a list of the available core modules available for each board. """ base = build_module_map() - boards = dict() - for port in SUPPORTED_PORTS: - + def support_matrix(arg): + port, entry = arg port_dir = get_circuitpython_root_dir() / "ports" / port - for entry in (port_dir / "boards").iterdir(): - if not entry.is_dir(): - continue - board_modules = [] + settings = get_settings_from_makefile(str(port_dir), entry.name) + + if use_branded_name: + with open(entry / "mpconfigboard.h") as get_name: + board_contents = get_name.read() + board_name_re = re.search(r"(?<=MICROPY_HW_BOARD_NAME)\s+(.+)", + board_contents) + if board_name_re: + board_name = board_name_re.group(1).strip('"') + else: board_name = entry.name - settings = get_settings_from_makefile(str(port_dir), entry.name) + board_modules = [] + for module in base: + key = f'CIRCUITPY_{module.upper()}' + if int(lookup_setting(settings, key, '0')): + board_modules.append(base[module]['name']) - if use_branded_name: - with open(entry / "mpconfigboard.h") as get_name: - board_contents = get_name.read() - board_name_re = re.search(r"(?<=MICROPY_HW_BOARD_NAME)\s+(.+)", - board_contents) - if board_name_re: - board_name = board_name_re.group(1).strip('"') + return (board_name, sorted(board_modules)) - board_modules = [] - for module in base: - key = f'CIRCUITPY_{module.upper()}' - if int(lookup_setting(settings, key, '0')): - board_modules.append(base[module]['name']) - boards[board_name] = sorted(board_modules) + executor = ThreadPoolExecutor(max_workers=os.cpu_count()) + boards = dict(sorted(executor.map(support_matrix, all_ports_all_boards()))) #print(json.dumps(boards, indent=2)) return boards diff --git a/lib/protomatter b/lib/protomatter index 761d6437e8..2a1ba8fa47 160000 --- a/lib/protomatter +++ b/lib/protomatter @@ -1 +1 @@ -Subproject commit 761d6437e8cd6a131d51de96974337121a9c7164 +Subproject commit 2a1ba8fa4753b2bcb158c9b17351cf18eade0d2b diff --git a/lib/utils/pyexec.c b/lib/utils/pyexec.c index 8e99bc2099..378fb6267d 100755 --- a/lib/utils/pyexec.c +++ b/lib/utils/pyexec.c @@ -113,6 +113,8 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input start = mp_hal_ticks_ms(); mp_call_function_0(module_fun); mp_hal_set_interrupt_char(-1); // disable interrupt + // Handle any ctrl-c interrupt that arrived just in time + mp_handle_pending(); nlr_pop(); ret = 0; if (exec_flags & EXEC_FLAG_PRINT_EOF) { diff --git a/locale/ID.po b/locale/ID.po index ec5b6f6e86..dd41b740f1 100644 --- a/locale/ID.po +++ b/locale/ID.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-08-18 11:19-0400\n" +"POT-Creation-Date: 2020-08-30 14:38-0400\n" "PO-Revision-Date: 2020-07-06 18:10+0000\n" "Last-Translator: oon arfiandwi \n" "Language-Team: LANGUAGE \n" @@ -308,7 +308,7 @@ msgstr "Semua channel event sedang digunakan" msgid "All sync event channels in use" msgstr "Semua channel event yang disinkronisasi sedang digunakan" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "All timers for this pin are in use" msgstr "Semua timer untuk pin ini sedang digunakan" @@ -320,7 +320,7 @@ msgstr "Semua timer untuk pin ini sedang digunakan" #: ports/cxd56/common-hal/pulseio/PulseOut.c #: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c -#: ports/stm/peripherals/timers.c shared-bindings/pulseio/PWMOut.c +#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c msgid "All timers in use" msgstr "Semua timer sedang digunakan" @@ -498,6 +498,10 @@ msgstr "Panggil super().__init__() sebelum mengakses objek asli." msgid "Can't set CCCD on local Characteristic" msgstr "Tidak dapat mengatur CCCD pada Karakteristik lokal" +#: shared-bindings/_bleio/Adapter.c +msgid "Cannot create a new Adapter; use _bleio.adapter;" +msgstr "" + #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c @@ -566,7 +570,7 @@ msgstr "Tidak dapat transfer tanpa pin MOSI dan MISO." msgid "Cannot unambiguously get sizeof scalar" msgstr "tidak dapat mendapatkan ukuran scalar secara tidak ambigu" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Cannot vary frequency on a timer that is already in use" msgstr "" "Tidak dapat membuat variasi frekuensi pada penghitung waktu yang sudah " @@ -640,23 +644,23 @@ msgstr "" msgid "Could not initialize UART" msgstr "Tidak dapat menginisialisasi UART" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize channel" msgstr "Tidak dapat menginisialisasi kanal" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize timer" msgstr "Tidak dapat menginisialisasi timer" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init channel" msgstr "Tidak dapat menginisialisasi ulang kanal" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init timer" msgstr "Tidak dapat menginisialisasi ulang timer" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not restart PWM" msgstr "Tidak dapat memulai ulang PWM" @@ -664,7 +668,7 @@ msgstr "Tidak dapat memulai ulang PWM" msgid "Could not set address" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not start PWM" msgstr "Tidak dapat memulai PWM" @@ -762,8 +766,8 @@ msgstr "Channel EXTINT sedang digunakan" msgid "Error in regex" msgstr "Error pada regex" -#: shared-bindings/aesio/aes.c shared-bindings/busio/SPI.c -#: shared-bindings/microcontroller/Pin.c +#: shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c +#: shared-bindings/busio/SPI.c shared-bindings/microcontroller/Pin.c #: shared-bindings/neopixel_write/__init__.c #: shared-bindings/terminalio/Terminal.c msgid "Expected a %q" @@ -774,10 +778,18 @@ msgstr "Diharapkan %q" msgid "Expected a Characteristic" msgstr "Diharapkan sebuah Karakteristik" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a DigitalInOut" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "Diharapkan sebuah Layanan" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a UART" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c #: shared-bindings/_bleio/Service.c msgid "Expected a UUID" @@ -857,7 +869,7 @@ msgid "Frequency captured is above capability. Capture Paused." msgstr "" "Frekuensi yang ditangkap berada di atas kemampuan. Penangkapan Ditunda." -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Frequency must match existing PWMOut using this timer" msgstr "Frekuensi harus cocok dengan PWMOut yang ada menggunakan timer ini" @@ -961,9 +973,9 @@ msgstr "File BMP tidak valid" msgid "Invalid DAC pin supplied" msgstr "Pin DAC yang diberikan tidak valid" -#: ports/atmel-samd/common-hal/pulseio/PWMOut.c -#: ports/cxd56/common-hal/pulseio/PWMOut.c -#: ports/nrf/common-hal/pulseio/PWMOut.c shared-bindings/pulseio/PWMOut.c +#: ports/atmel-samd/common-hal/pwmio/PWMOut.c +#: ports/cxd56/common-hal/pwmio/PWMOut.c ports/nrf/common-hal/pwmio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "Invalid PWM frequency" msgstr "Frekuensi PWM tidak valid" @@ -1003,7 +1015,7 @@ msgstr "File tidak valid" msgid "Invalid format chunk size" msgstr "Ukuran potongan format tidak valid" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid frequency supplied" msgstr "Frekuensi yang diberikan tidak valid" @@ -1021,8 +1033,8 @@ msgid "Invalid phase" msgstr "Fase tidak valid" #: ports/atmel-samd/common-hal/audioio/AudioOut.c -#: ports/atmel-samd/common-hal/touchio/TouchIn.c -#: shared-bindings/pulseio/PWMOut.c shared-module/rgbmatrix/RGBMatrix.c +#: ports/atmel-samd/common-hal/touchio/TouchIn.c shared-bindings/pwmio/PWMOut.c +#: shared-module/rgbmatrix/RGBMatrix.c msgid "Invalid pin" msgstr "Pin tidak valid" @@ -1046,7 +1058,7 @@ msgstr "Pin untuk channel kanan tidak valid" msgid "Invalid pins" msgstr "Pin-pin tidak valid" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid pins for PWMOut" msgstr "Pin untuk PWMOut tidak valid" @@ -1228,7 +1240,7 @@ msgstr "" msgid "No long integer support" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "No more timers available on this pin." msgstr "" @@ -1267,6 +1279,10 @@ msgstr "" msgid "Not running saved code.\n" msgstr "" +#: shared-bindings/_bleio/__init__.c +msgid "Not settable" +msgstr "" + #: shared-bindings/util.c msgid "" "Object has been deinitialized and can no longer be used. Create a new object." @@ -1297,12 +1313,12 @@ msgstr "" msgid "Oversample must be multiple of 8." msgstr "" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM duty_cycle must be between 0 and 65535 inclusive (16 bit resolution)" msgstr "" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM frequency not writable when variable_frequency is False on construction." msgstr "" @@ -1357,8 +1373,8 @@ msgstr "" #: ports/nrf/common-hal/pulseio/PulseOut.c #: ports/stm/common-hal/pulseio/PulseOut.c msgid "" -"Port does not accept pins or frequency. " -"Construct and pass a PWMOut Carrier instead" +"Port does not accept pins or frequency. Construct and pass a PWMOut Carrier " +"instead" msgstr "" #: shared-bindings/_bleio/Adapter.c @@ -1375,10 +1391,6 @@ msgstr "" msgid "Pull not used when direction is output." msgstr "" -#: ports/stm/ref/pulseout-pre-timeralloc.c -msgid "PulseOut not supported on this chip" -msgstr "" - #: ports/stm/common-hal/os/__init__.c msgid "RNG DeInit Error" msgstr "" @@ -1591,7 +1603,7 @@ msgstr "" msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "" "Timer was reserved for internal use - declare PWM pins earlier in the program" msgstr "" @@ -2488,6 +2500,10 @@ msgstr "" msgid "initial values must be iterable" msgstr "" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "initial_value length is wrong" +msgstr "" + #: py/compile.c msgid "inline assembler must be a function" msgstr "inline assembler harus sebuah fungsi" @@ -2680,6 +2696,10 @@ msgstr "" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "max_length must be > 0" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "" @@ -2915,6 +2935,14 @@ msgstr "" msgid "ord() expected a character, but string of length %d found" msgstr "" +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of source" +msgstr "" + +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of target" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "" @@ -3092,6 +3120,10 @@ msgstr "" msgid "sosfilt requires iterable arguments" msgstr "" +#: shared-bindings/displayio/Bitmap.c +msgid "source palette too large" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "" diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 108bcb381c..aeea5f5e92 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-08-27 11:21-0400\n" +"POT-Creation-Date: 2020-08-30 14:38-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -490,6 +490,10 @@ msgstr "" msgid "Can't set CCCD on local Characteristic" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Cannot create a new Adapter; use _bleio.adapter;" +msgstr "" + #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c @@ -742,8 +746,8 @@ msgstr "" msgid "Error in regex" msgstr "" -#: shared-bindings/aesio/aes.c shared-bindings/busio/SPI.c -#: shared-bindings/microcontroller/Pin.c +#: shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c +#: shared-bindings/busio/SPI.c shared-bindings/microcontroller/Pin.c #: shared-bindings/neopixel_write/__init__.c #: shared-bindings/terminalio/Terminal.c msgid "Expected a %q" @@ -754,10 +758,18 @@ msgstr "" msgid "Expected a Characteristic" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a DigitalInOut" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a UART" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c #: shared-bindings/_bleio/Service.c msgid "Expected a UUID" @@ -1243,6 +1255,10 @@ msgstr "" msgid "Not running saved code.\n" msgstr "" +#: shared-bindings/_bleio/__init__.c +msgid "Not settable" +msgstr "" + #: shared-bindings/util.c msgid "" "Object has been deinitialized and can no longer be used. Create a new object." @@ -1349,10 +1365,6 @@ msgstr "" msgid "Pull not used when direction is output." msgstr "" -#: ports/stm/ref/pulseout-pre-timeralloc.c -msgid "PulseOut not supported on this chip" -msgstr "" - #: ports/stm/common-hal/os/__init__.c msgid "RNG DeInit Error" msgstr "" @@ -2453,6 +2465,10 @@ msgstr "" msgid "initial values must be iterable" msgstr "" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "initial_value length is wrong" +msgstr "" + #: py/compile.c msgid "inline assembler must be a function" msgstr "" @@ -2645,6 +2661,10 @@ msgstr "" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "max_length must be > 0" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "" diff --git a/locale/cs.po b/locale/cs.po index b353f46306..cd81c258fe 100644 --- a/locale/cs.po +++ b/locale/cs.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-08-18 11:19-0400\n" +"POT-Creation-Date: 2020-08-30 14:38-0400\n" "PO-Revision-Date: 2020-05-24 03:22+0000\n" "Last-Translator: dronecz \n" "Language-Team: LANGUAGE \n" @@ -308,7 +308,7 @@ msgstr "" msgid "All sync event channels in use" msgstr "" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "All timers for this pin are in use" msgstr "" @@ -320,7 +320,7 @@ msgstr "" #: ports/cxd56/common-hal/pulseio/PulseOut.c #: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c -#: ports/stm/peripherals/timers.c shared-bindings/pulseio/PWMOut.c +#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c msgid "All timers in use" msgstr "" @@ -496,6 +496,10 @@ msgstr "" msgid "Can't set CCCD on local Characteristic" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Cannot create a new Adapter; use _bleio.adapter;" +msgstr "" + #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c @@ -558,7 +562,7 @@ msgstr "" msgid "Cannot unambiguously get sizeof scalar" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Cannot vary frequency on a timer that is already in use" msgstr "" @@ -627,23 +631,23 @@ msgstr "" msgid "Could not initialize UART" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize channel" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize timer" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init channel" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init timer" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not restart PWM" msgstr "" @@ -651,7 +655,7 @@ msgstr "" msgid "Could not set address" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not start PWM" msgstr "" @@ -748,8 +752,8 @@ msgstr "" msgid "Error in regex" msgstr "" -#: shared-bindings/aesio/aes.c shared-bindings/busio/SPI.c -#: shared-bindings/microcontroller/Pin.c +#: shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c +#: shared-bindings/busio/SPI.c shared-bindings/microcontroller/Pin.c #: shared-bindings/neopixel_write/__init__.c #: shared-bindings/terminalio/Terminal.c msgid "Expected a %q" @@ -760,10 +764,18 @@ msgstr "" msgid "Expected a Characteristic" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a DigitalInOut" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a UART" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c #: shared-bindings/_bleio/Service.c msgid "Expected a UUID" @@ -842,7 +854,7 @@ msgstr "" msgid "Frequency captured is above capability. Capture Paused." msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Frequency must match existing PWMOut using this timer" msgstr "" @@ -944,9 +956,9 @@ msgstr "" msgid "Invalid DAC pin supplied" msgstr "" -#: ports/atmel-samd/common-hal/pulseio/PWMOut.c -#: ports/cxd56/common-hal/pulseio/PWMOut.c -#: ports/nrf/common-hal/pulseio/PWMOut.c shared-bindings/pulseio/PWMOut.c +#: ports/atmel-samd/common-hal/pwmio/PWMOut.c +#: ports/cxd56/common-hal/pwmio/PWMOut.c ports/nrf/common-hal/pwmio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "Invalid PWM frequency" msgstr "" @@ -986,7 +998,7 @@ msgstr "" msgid "Invalid format chunk size" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid frequency supplied" msgstr "" @@ -1004,8 +1016,8 @@ msgid "Invalid phase" msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c -#: ports/atmel-samd/common-hal/touchio/TouchIn.c -#: shared-bindings/pulseio/PWMOut.c shared-module/rgbmatrix/RGBMatrix.c +#: ports/atmel-samd/common-hal/touchio/TouchIn.c shared-bindings/pwmio/PWMOut.c +#: shared-module/rgbmatrix/RGBMatrix.c msgid "Invalid pin" msgstr "" @@ -1029,7 +1041,7 @@ msgstr "" msgid "Invalid pins" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid pins for PWMOut" msgstr "" @@ -1211,7 +1223,7 @@ msgstr "" msgid "No long integer support" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "No more timers available on this pin." msgstr "" @@ -1249,6 +1261,10 @@ msgstr "" msgid "Not running saved code.\n" msgstr "" +#: shared-bindings/_bleio/__init__.c +msgid "Not settable" +msgstr "" + #: shared-bindings/util.c msgid "" "Object has been deinitialized and can no longer be used. Create a new object." @@ -1279,12 +1295,12 @@ msgstr "" msgid "Oversample must be multiple of 8." msgstr "" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM duty_cycle must be between 0 and 65535 inclusive (16 bit resolution)" msgstr "" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM frequency not writable when variable_frequency is False on construction." msgstr "" @@ -1339,8 +1355,8 @@ msgstr "" #: ports/nrf/common-hal/pulseio/PulseOut.c #: ports/stm/common-hal/pulseio/PulseOut.c msgid "" -"Port does not accept pins or frequency. " -"Construct and pass a PWMOut Carrier instead" +"Port does not accept pins or frequency. Construct and pass a PWMOut Carrier " +"instead" msgstr "" #: shared-bindings/_bleio/Adapter.c @@ -1355,10 +1371,6 @@ msgstr "" msgid "Pull not used when direction is output." msgstr "" -#: ports/stm/ref/pulseout-pre-timeralloc.c -msgid "PulseOut not supported on this chip" -msgstr "" - #: ports/stm/common-hal/os/__init__.c msgid "RNG DeInit Error" msgstr "" @@ -1570,7 +1582,7 @@ msgstr "" msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "" "Timer was reserved for internal use - declare PWM pins earlier in the program" msgstr "" @@ -2459,6 +2471,10 @@ msgstr "" msgid "initial values must be iterable" msgstr "" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "initial_value length is wrong" +msgstr "" + #: py/compile.c msgid "inline assembler must be a function" msgstr "" @@ -2651,6 +2667,10 @@ msgstr "" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "max_length must be > 0" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "" @@ -2885,6 +2905,14 @@ msgstr "" msgid "ord() expected a character, but string of length %d found" msgstr "" +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of source" +msgstr "" + +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of target" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "" @@ -3062,6 +3090,10 @@ msgstr "" msgid "sosfilt requires iterable arguments" msgstr "" +#: shared-bindings/displayio/Bitmap.c +msgid "source palette too large" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "" diff --git a/locale/de_DE.po b/locale/de_DE.po index 87cca4a77f..3debbcb621 100644 --- a/locale/de_DE.po +++ b/locale/de_DE.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-08-18 11:19-0400\n" +"POT-Creation-Date: 2020-08-30 14:38-0400\n" "PO-Revision-Date: 2020-06-16 18:24+0000\n" "Last-Translator: Andreas Buchen \n" "Language: de_DE\n" @@ -307,7 +307,7 @@ msgstr "Alle event Kanäle werden benutzt" msgid "All sync event channels in use" msgstr "Alle sync event Kanäle werden benutzt" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "All timers for this pin are in use" msgstr "Alle timer für diesen Pin werden bereits benutzt" @@ -319,7 +319,7 @@ msgstr "Alle timer für diesen Pin werden bereits benutzt" #: ports/cxd56/common-hal/pulseio/PulseOut.c #: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c -#: ports/stm/peripherals/timers.c shared-bindings/pulseio/PWMOut.c +#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c msgid "All timers in use" msgstr "Alle timer werden benutzt" @@ -499,6 +499,10 @@ msgstr "Rufe super().__init__() vor dem Zugriff auf ein natives Objekt auf." msgid "Can't set CCCD on local Characteristic" msgstr "CCCD kann nicht auf lokales Merkmal eingestellt werden" +#: shared-bindings/_bleio/Adapter.c +msgid "Cannot create a new Adapter; use _bleio.adapter;" +msgstr "" + #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c @@ -562,7 +566,7 @@ msgstr "Übertragung ohne MOSI- und MISO-Pins nicht möglich." msgid "Cannot unambiguously get sizeof scalar" msgstr "sizeof scalar kann nicht eindeutig bestimmt werden" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Cannot vary frequency on a timer that is already in use" msgstr "" "Die Frequenz eines bereits verwendeten Timers kann nicht variiert werden" @@ -637,23 +641,23 @@ msgstr "" msgid "Could not initialize UART" msgstr "Konnte UART nicht initialisieren" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize channel" msgstr "Kanal konnte nicht initialisiert werden" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize timer" msgstr "Timer konnte nicht initialisiert werden" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init channel" msgstr "Kanal konnte nicht neu initiiert werden" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init timer" msgstr "Timer konnte nicht neu gestartet werden" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not restart PWM" msgstr "PWM konnte nicht neu gestartet werden" @@ -661,7 +665,7 @@ msgstr "PWM konnte nicht neu gestartet werden" msgid "Could not set address" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not start PWM" msgstr "PWM konnte nicht gestartet werden" @@ -758,8 +762,8 @@ msgstr "EXTINT Kanal ist schon in Benutzung" msgid "Error in regex" msgstr "Fehler in regex" -#: shared-bindings/aesio/aes.c shared-bindings/busio/SPI.c -#: shared-bindings/microcontroller/Pin.c +#: shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c +#: shared-bindings/busio/SPI.c shared-bindings/microcontroller/Pin.c #: shared-bindings/neopixel_write/__init__.c #: shared-bindings/terminalio/Terminal.c msgid "Expected a %q" @@ -770,10 +774,18 @@ msgstr "Erwartet ein(e) %q" msgid "Expected a Characteristic" msgstr "Characteristic wird erwartet" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a DigitalInOut" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "Ein Service wird erwartet" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a UART" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c #: shared-bindings/_bleio/Service.c msgid "Expected a UUID" @@ -855,7 +867,7 @@ msgstr "" "Die aufgezeichnete Frequenz liegt über der Leistungsgrenze. Aufnahme " "angehalten." -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Frequency must match existing PWMOut using this timer" msgstr "" "Die Frequenz muss mit dem vorhandenen PWMOut unter Verwendung dieses Timers " @@ -961,9 +973,9 @@ msgstr "Ungültige BMP-Datei" msgid "Invalid DAC pin supplied" msgstr "Ungültiger DAC-Pin angegeben" -#: ports/atmel-samd/common-hal/pulseio/PWMOut.c -#: ports/cxd56/common-hal/pulseio/PWMOut.c -#: ports/nrf/common-hal/pulseio/PWMOut.c shared-bindings/pulseio/PWMOut.c +#: ports/atmel-samd/common-hal/pwmio/PWMOut.c +#: ports/cxd56/common-hal/pwmio/PWMOut.c ports/nrf/common-hal/pwmio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "Invalid PWM frequency" msgstr "Ungültige PWM Frequenz" @@ -1003,7 +1015,7 @@ msgstr "Ungültige Datei" msgid "Invalid format chunk size" msgstr "Ungültige format chunk size" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid frequency supplied" msgstr "Ungültige Frequenz geliefert" @@ -1021,8 +1033,8 @@ msgid "Invalid phase" msgstr "Ungültige Phase" #: ports/atmel-samd/common-hal/audioio/AudioOut.c -#: ports/atmel-samd/common-hal/touchio/TouchIn.c -#: shared-bindings/pulseio/PWMOut.c shared-module/rgbmatrix/RGBMatrix.c +#: ports/atmel-samd/common-hal/touchio/TouchIn.c shared-bindings/pwmio/PWMOut.c +#: shared-module/rgbmatrix/RGBMatrix.c msgid "Invalid pin" msgstr "Ungültiger Pin" @@ -1046,7 +1058,7 @@ msgstr "Ungültiger Pin für rechten Kanal" msgid "Invalid pins" msgstr "Ungültige Pins" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid pins for PWMOut" msgstr "Ungültige Pins für PWMOut" @@ -1230,7 +1242,7 @@ msgstr "Es wurde kein Schlüssel angegeben" msgid "No long integer support" msgstr "Keine langen Integer (long) unterstützt" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "No more timers available on this pin." msgstr "An diesem Pin sind keine Timer mehr verfügbar." @@ -1268,6 +1280,10 @@ msgstr "Spielt nicht ab" msgid "Not running saved code.\n" msgstr "" +#: shared-bindings/_bleio/__init__.c +msgid "Not settable" +msgstr "" + #: shared-bindings/util.c msgid "" "Object has been deinitialized and can no longer be used. Create a new object." @@ -1304,12 +1320,12 @@ msgstr "" msgid "Oversample must be multiple of 8." msgstr "Oversample muss ein Vielfaches von 8 sein." -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM duty_cycle must be between 0 and 65535 inclusive (16 bit resolution)" msgstr "PWM duty_cycle muss zwischen 0 und 65535 (16 Bit Auflösung) liegen" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM frequency not writable when variable_frequency is False on construction." msgstr "Die PWM-Frequenz ist nicht schreibbar wenn variable_Frequenz = False." @@ -1367,8 +1383,8 @@ msgstr "Polygone brauchen mindestens 3 Punkte" #: ports/nrf/common-hal/pulseio/PulseOut.c #: ports/stm/common-hal/pulseio/PulseOut.c msgid "" -"Port does not accept pins or frequency. " -"Construct and pass a PWMOut Carrier instead" +"Port does not accept pins or frequency. Construct and pass a PWMOut Carrier " +"instead" msgstr "" #: shared-bindings/_bleio/Adapter.c @@ -1385,10 +1401,6 @@ msgstr "" msgid "Pull not used when direction is output." msgstr "Pull wird nicht verwendet, wenn die Richtung output ist." -#: ports/stm/ref/pulseout-pre-timeralloc.c -msgid "PulseOut not supported on this chip" -msgstr "PulseOut wird auf diesem Chip nicht unterstützt" - #: ports/stm/common-hal/os/__init__.c msgid "RNG DeInit Error" msgstr "RNG DeInit-Fehler" @@ -1612,7 +1624,7 @@ msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "" "Zeitbeschränkung ist zu groß: Maximale Zeitbeschränkung ist %d Sekunden" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "" "Timer was reserved for internal use - declare PWM pins earlier in the program" msgstr "" @@ -2530,6 +2542,10 @@ msgstr "Indizes müssen Integer, Slices oder Boolesche Listen sein" msgid "initial values must be iterable" msgstr "" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "initial_value length is wrong" +msgstr "" + #: py/compile.c msgid "inline assembler must be a function" msgstr "inline assembler muss eine function sein" @@ -2728,6 +2744,10 @@ msgstr "Matrix ist nicht positiv definitiv" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "max_length muss 0-%d sein, wenn fixed_length %s ist" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "max_length must be > 0" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "maximale Rekursionstiefe überschritten" @@ -2966,6 +2986,14 @@ msgstr "" "ord() erwartet einen Buchstaben(char) aber es wurde ein String mit Länge %d " "gefunden" +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of source" +msgstr "" + +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of target" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "Überlauf beim konvertieren von long int zu machine word" @@ -3145,6 +3173,10 @@ msgstr "" msgid "sosfilt requires iterable arguments" msgstr "" +#: shared-bindings/displayio/Bitmap.c +msgid "source palette too large" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "start/end Indizes" @@ -3446,6 +3478,9 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "PulseOut not supported on this chip" +#~ msgstr "PulseOut wird auf diesem Chip nicht unterstützt" + #~ msgid "tuple/list required on RHS" #~ msgstr "Tupel / Liste auf RHS erforderlich" diff --git a/locale/es.po b/locale/es.po index 882904f640..15b4fe7806 100644 --- a/locale/es.po +++ b/locale/es.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-08-18 11:19-0400\n" +"POT-Creation-Date: 2020-08-30 14:38-0400\n" "PO-Revision-Date: 2020-08-17 21:11+0000\n" "Last-Translator: Alvaro Figueroa \n" "Language-Team: \n" @@ -313,7 +313,7 @@ msgstr "" "Todos los canales de eventos de sincronización (sync event channels) están " "siendo utilizados" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "All timers for this pin are in use" msgstr "Todos los timers para este pin están siendo utilizados" @@ -325,7 +325,7 @@ msgstr "Todos los timers para este pin están siendo utilizados" #: ports/cxd56/common-hal/pulseio/PulseOut.c #: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c -#: ports/stm/peripherals/timers.c shared-bindings/pulseio/PWMOut.c +#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c msgid "All timers in use" msgstr "Todos los timers en uso" @@ -505,6 +505,10 @@ msgstr "Llame a super().__ init __() antes de acceder al objeto nativo." msgid "Can't set CCCD on local Characteristic" msgstr "No se puede configurar CCCD en la característica local" +#: shared-bindings/_bleio/Adapter.c +msgid "Cannot create a new Adapter; use _bleio.adapter;" +msgstr "" + #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c @@ -569,7 +573,7 @@ msgstr "No se puede transmitir sin pines MOSI y MISO." msgid "Cannot unambiguously get sizeof scalar" msgstr "No se puede obtener inequívocamente sizeof escalar" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Cannot vary frequency on a timer that is already in use" msgstr "No puede variar la frecuencia en un temporizador que ya está en uso" @@ -642,23 +646,23 @@ msgstr "No se pudo inicializar SDCard" msgid "Could not initialize UART" msgstr "No se puede inicializar la UART" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize channel" msgstr "No se pudo inicializar el canal" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize timer" msgstr "No se pudo inicializar el temporizador" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init channel" msgstr "No se pudo reiniciar el canal" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init timer" msgstr "No se pudo reiniciar el temporizador" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not restart PWM" msgstr "No se pudo reiniciar el PWM" @@ -666,7 +670,7 @@ msgstr "No se pudo reiniciar el PWM" msgid "Could not set address" msgstr "No se puede definir la dirección" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not start PWM" msgstr "No se pudo iniciar el PWM" @@ -763,8 +767,8 @@ msgstr "El canal EXTINT ya está siendo utilizado" msgid "Error in regex" msgstr "Error en regex" -#: shared-bindings/aesio/aes.c shared-bindings/busio/SPI.c -#: shared-bindings/microcontroller/Pin.c +#: shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c +#: shared-bindings/busio/SPI.c shared-bindings/microcontroller/Pin.c #: shared-bindings/neopixel_write/__init__.c #: shared-bindings/terminalio/Terminal.c msgid "Expected a %q" @@ -775,10 +779,18 @@ msgstr "Se espera un %q" msgid "Expected a Characteristic" msgstr "Se esperaba una Característica" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a DigitalInOut" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "Se esperaba un servicio" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a UART" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c #: shared-bindings/_bleio/Service.c msgid "Expected a UUID" @@ -857,7 +869,7 @@ msgstr "Framebuffer requiere %d bytes" msgid "Frequency captured is above capability. Capture Paused." msgstr "Frecuencia capturada por encima de la capacidad. Captura en pausa." -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Frequency must match existing PWMOut using this timer" msgstr "" "La frecuencia debe coincidir con PWMOut existente usando este temporizador" @@ -962,9 +974,9 @@ msgstr "Archivo BMP inválido" msgid "Invalid DAC pin supplied" msgstr "Pin suministrado inválido para DAC" -#: ports/atmel-samd/common-hal/pulseio/PWMOut.c -#: ports/cxd56/common-hal/pulseio/PWMOut.c -#: ports/nrf/common-hal/pulseio/PWMOut.c shared-bindings/pulseio/PWMOut.c +#: ports/atmel-samd/common-hal/pwmio/PWMOut.c +#: ports/cxd56/common-hal/pwmio/PWMOut.c ports/nrf/common-hal/pwmio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "Invalid PWM frequency" msgstr "Frecuencia PWM inválida" @@ -1004,7 +1016,7 @@ msgstr "Archivo inválido" msgid "Invalid format chunk size" msgstr "Formato de fragmento de formato no válido" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid frequency supplied" msgstr "Frecuencia suministrada no válida" @@ -1022,8 +1034,8 @@ msgid "Invalid phase" msgstr "Fase inválida" #: ports/atmel-samd/common-hal/audioio/AudioOut.c -#: ports/atmel-samd/common-hal/touchio/TouchIn.c -#: shared-bindings/pulseio/PWMOut.c shared-module/rgbmatrix/RGBMatrix.c +#: ports/atmel-samd/common-hal/touchio/TouchIn.c shared-bindings/pwmio/PWMOut.c +#: shared-module/rgbmatrix/RGBMatrix.c msgid "Invalid pin" msgstr "Pin inválido" @@ -1047,7 +1059,7 @@ msgstr "Pin inválido para canal derecho" msgid "Invalid pins" msgstr "pines inválidos" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid pins for PWMOut" msgstr "Pines inválidos para PWMOut" @@ -1229,7 +1241,7 @@ msgstr "No se especificó ninguna llave" msgid "No long integer support" msgstr "No hay soporte de entero largo" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "No more timers available on this pin." msgstr "No hay más temporizadores disponibles en este pin." @@ -1267,6 +1279,10 @@ msgstr "No reproduciendo" msgid "Not running saved code.\n" msgstr "No ejecutando el código almacenado.\n" +#: shared-bindings/_bleio/__init__.c +msgid "Not settable" +msgstr "" + #: shared-bindings/util.c msgid "" "Object has been deinitialized and can no longer be used. Create a new object." @@ -1303,12 +1319,12 @@ msgstr "" msgid "Oversample must be multiple of 8." msgstr "El sobremuestreo debe ser un múltiplo de 8." -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM duty_cycle must be between 0 and 65535 inclusive (16 bit resolution)" msgstr "PWM duty_cycle debe ser entre 0 y 65535 inclusivo (16 bit resolution)" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM frequency not writable when variable_frequency is False on construction." msgstr "" @@ -1367,8 +1383,8 @@ msgstr "El polígono necesita al menos 3 puntos" #: ports/nrf/common-hal/pulseio/PulseOut.c #: ports/stm/common-hal/pulseio/PulseOut.c msgid "" -"Port does not accept pins or frequency. " -"Construct and pass a PWMOut Carrier instead" +"Port does not accept pins or frequency. Construct and pass a PWMOut Carrier " +"instead" msgstr "" #: shared-bindings/_bleio/Adapter.c @@ -1384,10 +1400,6 @@ msgstr "" msgid "Pull not used when direction is output." msgstr "Pull no se usa cuando la dirección es output." -#: ports/stm/ref/pulseout-pre-timeralloc.c -msgid "PulseOut not supported on this chip" -msgstr "PulseOut no es compatible con este chip" - #: ports/stm/common-hal/os/__init__.c msgid "RNG DeInit Error" msgstr "Error de desinicializado del RNG" @@ -1610,7 +1622,7 @@ msgstr "" "Tiempo de espera demasiado largo: El tiempo máximo de espera es de %d " "segundos" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "" "Timer was reserved for internal use - declare PWM pins earlier in the program" msgstr "" @@ -2520,6 +2532,10 @@ msgstr "los índices deben ser enteros, particiones o listas de booleanos" msgid "initial values must be iterable" msgstr "los valores iniciales deben permitir iteración" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "initial_value length is wrong" +msgstr "" + #: py/compile.c msgid "inline assembler must be a function" msgstr "ensamblador en línea debe ser una función" @@ -2715,6 +2731,10 @@ msgstr "matrix no es definida positiva" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "max_length debe ser 0-%d cuando fixed_length es %s" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "max_length must be > 0" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "profundidad máxima de recursión excedida" @@ -2952,6 +2972,14 @@ msgstr "ord espera un carácter" msgid "ord() expected a character, but string of length %d found" msgstr "ord() espera un carácter, pero encontró un string de longitud %d" +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of source" +msgstr "" + +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of target" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "desbordamiento convirtiendo long int a palabra de máquina" @@ -3131,6 +3159,10 @@ msgstr "sos[:, 3] deberían ser todos unos" msgid "sosfilt requires iterable arguments" msgstr "sosfilt requiere argumentos iterables" +#: shared-bindings/displayio/Bitmap.c +msgid "source palette too large" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "índices inicio/final" @@ -3428,6 +3460,9 @@ msgstr "zi debe ser de tipo flotante" msgid "zi must be of shape (n_section, 2)" msgstr "zi debe ser una forma (n_section,2)" +#~ msgid "PulseOut not supported on this chip" +#~ msgstr "PulseOut no es compatible con este chip" + #~ msgid "tuple/list required on RHS" #~ msgstr "tuple/lista se require en RHS" diff --git a/locale/fil.po b/locale/fil.po index ec4f9f6856..5bb696c83b 100644 --- a/locale/fil.po +++ b/locale/fil.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-08-18 11:19-0400\n" +"POT-Creation-Date: 2020-08-30 14:38-0400\n" "PO-Revision-Date: 2018-12-20 22:15-0800\n" "Last-Translator: Timothy \n" "Language-Team: fil\n" @@ -304,7 +304,7 @@ msgstr "Lahat ng event channels ginagamit" msgid "All sync event channels in use" msgstr "Lahat ng sync event channels ay ginagamit" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "All timers for this pin are in use" msgstr "Lahat ng timers para sa pin na ito ay ginagamit" @@ -316,7 +316,7 @@ msgstr "Lahat ng timers para sa pin na ito ay ginagamit" #: ports/cxd56/common-hal/pulseio/PulseOut.c #: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c -#: ports/stm/peripherals/timers.c shared-bindings/pulseio/PWMOut.c +#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c msgid "All timers in use" msgstr "Lahat ng timer ginagamit" @@ -495,6 +495,10 @@ msgstr "" msgid "Can't set CCCD on local Characteristic" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Cannot create a new Adapter; use _bleio.adapter;" +msgstr "" + #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c @@ -558,7 +562,7 @@ msgstr "Hindi maaaring ilipat kapag walang MOSI at MISO pin." msgid "Cannot unambiguously get sizeof scalar" msgstr "Hindi puedeng hindi sigurado ang get sizeof scalar" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Cannot vary frequency on a timer that is already in use" msgstr "" @@ -628,23 +632,23 @@ msgstr "" msgid "Could not initialize UART" msgstr "Hindi ma-initialize ang UART" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize channel" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize timer" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init channel" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init timer" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not restart PWM" msgstr "" @@ -652,7 +656,7 @@ msgstr "" msgid "Could not set address" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not start PWM" msgstr "" @@ -752,8 +756,8 @@ msgstr "Ginagamit na ang EXTINT channel" msgid "Error in regex" msgstr "May pagkakamali sa REGEX" -#: shared-bindings/aesio/aes.c shared-bindings/busio/SPI.c -#: shared-bindings/microcontroller/Pin.c +#: shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c +#: shared-bindings/busio/SPI.c shared-bindings/microcontroller/Pin.c #: shared-bindings/neopixel_write/__init__.c #: shared-bindings/terminalio/Terminal.c msgid "Expected a %q" @@ -765,10 +769,18 @@ msgstr "Umasa ng %q" msgid "Expected a Characteristic" msgstr "Hindi mabasa and Characteristic." +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a DigitalInOut" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a UART" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c #: shared-bindings/_bleio/Service.c #, fuzzy @@ -848,7 +860,7 @@ msgstr "" msgid "Frequency captured is above capability. Capture Paused." msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Frequency must match existing PWMOut using this timer" msgstr "" @@ -952,9 +964,9 @@ msgstr "Mali ang BMP file" msgid "Invalid DAC pin supplied" msgstr "" -#: ports/atmel-samd/common-hal/pulseio/PWMOut.c -#: ports/cxd56/common-hal/pulseio/PWMOut.c -#: ports/nrf/common-hal/pulseio/PWMOut.c shared-bindings/pulseio/PWMOut.c +#: ports/atmel-samd/common-hal/pwmio/PWMOut.c +#: ports/cxd56/common-hal/pwmio/PWMOut.c ports/nrf/common-hal/pwmio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "Invalid PWM frequency" msgstr "Mali ang PWM frequency" @@ -994,7 +1006,7 @@ msgstr "Mali ang file" msgid "Invalid format chunk size" msgstr "Mali ang format ng chunk size" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid frequency supplied" msgstr "" @@ -1012,8 +1024,8 @@ msgid "Invalid phase" msgstr "Mali ang phase" #: ports/atmel-samd/common-hal/audioio/AudioOut.c -#: ports/atmel-samd/common-hal/touchio/TouchIn.c -#: shared-bindings/pulseio/PWMOut.c shared-module/rgbmatrix/RGBMatrix.c +#: ports/atmel-samd/common-hal/touchio/TouchIn.c shared-bindings/pwmio/PWMOut.c +#: shared-module/rgbmatrix/RGBMatrix.c msgid "Invalid pin" msgstr "Mali ang pin" @@ -1037,7 +1049,7 @@ msgstr "Mali ang pin para sa kanang channel" msgid "Invalid pins" msgstr "Mali ang pins" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid pins for PWMOut" msgstr "" @@ -1219,7 +1231,7 @@ msgstr "" msgid "No long integer support" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "No more timers available on this pin." msgstr "" @@ -1258,6 +1270,10 @@ msgstr "Hindi playing" msgid "Not running saved code.\n" msgstr "" +#: shared-bindings/_bleio/__init__.c +msgid "Not settable" +msgstr "" + #: shared-bindings/util.c msgid "" "Object has been deinitialized and can no longer be used. Create a new object." @@ -1290,12 +1306,12 @@ msgstr "" msgid "Oversample must be multiple of 8." msgstr "Oversample ay dapat multiple ng 8." -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM duty_cycle must be between 0 and 65535 inclusive (16 bit resolution)" msgstr "PWM duty_cycle ay dapat sa loob ng 0 at 65535 (16 bit resolution)" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM frequency not writable when variable_frequency is False on construction." msgstr "" @@ -1351,8 +1367,8 @@ msgstr "" #: ports/nrf/common-hal/pulseio/PulseOut.c #: ports/stm/common-hal/pulseio/PulseOut.c msgid "" -"Port does not accept pins or frequency. " -"Construct and pass a PWMOut Carrier instead" +"Port does not accept pins or frequency. Construct and pass a PWMOut Carrier " +"instead" msgstr "" #: shared-bindings/_bleio/Adapter.c @@ -1369,10 +1385,6 @@ msgstr "" msgid "Pull not used when direction is output." msgstr "Pull hindi ginagamit kapag ang direksyon ay output." -#: ports/stm/ref/pulseout-pre-timeralloc.c -msgid "PulseOut not supported on this chip" -msgstr "" - #: ports/stm/common-hal/os/__init__.c msgid "RNG DeInit Error" msgstr "" @@ -1585,7 +1597,7 @@ msgstr "" msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "" "Timer was reserved for internal use - declare PWM pins earlier in the program" msgstr "" @@ -2497,6 +2509,10 @@ msgstr "" msgid "initial values must be iterable" msgstr "" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "initial_value length is wrong" +msgstr "" + #: py/compile.c msgid "inline assembler must be a function" msgstr "inline assembler ay dapat na function" @@ -2693,6 +2709,10 @@ msgstr "" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "max_length must be > 0" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "lumagpas ang maximum recursion depth" @@ -2928,6 +2948,14 @@ msgstr "ord umaasa ng character" msgid "ord() expected a character, but string of length %d found" msgstr "ord() umaasa ng character pero string ng %d haba ang nakita" +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of source" +msgstr "" + +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of target" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "overflow nagcoconvert ng long int sa machine word" @@ -3108,6 +3136,10 @@ msgstr "" msgid "sosfilt requires iterable arguments" msgstr "" +#: shared-bindings/displayio/Bitmap.c +msgid "source palette too large" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "start/end indeks" diff --git a/locale/fr.po b/locale/fr.po index 0562053f15..3ab4858020 100644 --- a/locale/fr.po +++ b/locale/fr.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-08-18 11:19-0400\n" +"POT-Creation-Date: 2020-08-30 14:38-0400\n" "PO-Revision-Date: 2020-07-27 21:27+0000\n" "Last-Translator: Nathan \n" "Language: fr\n" @@ -312,7 +312,7 @@ msgstr "Tous les canaux d'événements sont utilisés" msgid "All sync event channels in use" msgstr "Tous les canaux d'événements de synchro sont utilisés" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "All timers for this pin are in use" msgstr "Tous les timers pour cette broche sont utilisés" @@ -324,7 +324,7 @@ msgstr "Tous les timers pour cette broche sont utilisés" #: ports/cxd56/common-hal/pulseio/PulseOut.c #: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c -#: ports/stm/peripherals/timers.c shared-bindings/pulseio/PWMOut.c +#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c msgid "All timers in use" msgstr "Tous les timers sont utilisés" @@ -505,6 +505,10 @@ msgstr "Appelez super () .__ init __ () avant d'accéder à l'objet natif." msgid "Can't set CCCD on local Characteristic" msgstr "Impossible de définir CCCD sur une caractéristique locale" +#: shared-bindings/_bleio/Adapter.c +msgid "Cannot create a new Adapter; use _bleio.adapter;" +msgstr "" + #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c @@ -570,7 +574,7 @@ msgstr "Pas de transfert sans broches MOSI et MISO." msgid "Cannot unambiguously get sizeof scalar" msgstr "Impossible d'obtenir la taille du scalaire sans ambigüité" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Cannot vary frequency on a timer that is already in use" msgstr "" "Impossible de faire varier la fréquence sur une minuterie déjà utilisée" @@ -645,23 +649,23 @@ msgstr "Impossible d'initialiser la carte SD" msgid "Could not initialize UART" msgstr "L'UART n'a pu être initialisé" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize channel" msgstr "Impossible d'initialiser la chaîne" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize timer" msgstr "Impossible d'initialiser la minuterie" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init channel" msgstr "Impossible de réinitialiser la chaîne" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init timer" msgstr "Impossible de réinitialiser le minuteur" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not restart PWM" msgstr "Impossible de redémarrer PWM" @@ -669,7 +673,7 @@ msgstr "Impossible de redémarrer PWM" msgid "Could not set address" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not start PWM" msgstr "Impossible de démarrer PWM" @@ -766,8 +770,8 @@ msgstr "Canal EXTINT déjà utilisé" msgid "Error in regex" msgstr "Erreur dans l'expression régulière" -#: shared-bindings/aesio/aes.c shared-bindings/busio/SPI.c -#: shared-bindings/microcontroller/Pin.c +#: shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c +#: shared-bindings/busio/SPI.c shared-bindings/microcontroller/Pin.c #: shared-bindings/neopixel_write/__init__.c #: shared-bindings/terminalio/Terminal.c msgid "Expected a %q" @@ -778,10 +782,18 @@ msgstr "Attendu un %q" msgid "Expected a Characteristic" msgstr "Une 'Characteristic' est attendue" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a DigitalInOut" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "Attendu un service" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a UART" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c #: shared-bindings/_bleio/Service.c msgid "Expected a UUID" @@ -861,7 +873,7 @@ msgstr "" msgid "Frequency captured is above capability. Capture Paused." msgstr "La fréquence capturée est au delà des capacités. Capture en pause." -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Frequency must match existing PWMOut using this timer" msgstr "" "La fréquence doit correspondre à PWMOut existant à l'aide de cette minuterie" @@ -966,9 +978,9 @@ msgstr "Fichier BMP invalide" msgid "Invalid DAC pin supplied" msgstr "Broche DAC non valide fournie" -#: ports/atmel-samd/common-hal/pulseio/PWMOut.c -#: ports/cxd56/common-hal/pulseio/PWMOut.c -#: ports/nrf/common-hal/pulseio/PWMOut.c shared-bindings/pulseio/PWMOut.c +#: ports/atmel-samd/common-hal/pwmio/PWMOut.c +#: ports/cxd56/common-hal/pwmio/PWMOut.c ports/nrf/common-hal/pwmio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "Invalid PWM frequency" msgstr "Fréquence de PWM invalide" @@ -1008,7 +1020,7 @@ msgstr "Fichier invalide" msgid "Invalid format chunk size" msgstr "Taille de bloc de formatage invalide" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid frequency supplied" msgstr "Fréquence invalide fournie" @@ -1026,8 +1038,8 @@ msgid "Invalid phase" msgstr "Phase invalide" #: ports/atmel-samd/common-hal/audioio/AudioOut.c -#: ports/atmel-samd/common-hal/touchio/TouchIn.c -#: shared-bindings/pulseio/PWMOut.c shared-module/rgbmatrix/RGBMatrix.c +#: ports/atmel-samd/common-hal/touchio/TouchIn.c shared-bindings/pwmio/PWMOut.c +#: shared-module/rgbmatrix/RGBMatrix.c msgid "Invalid pin" msgstr "Broche invalide" @@ -1051,7 +1063,7 @@ msgstr "Broche invalide pour le canal droit" msgid "Invalid pins" msgstr "Broches invalides" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid pins for PWMOut" msgstr "Broches non valides pour PWMOut" @@ -1233,7 +1245,7 @@ msgstr "Aucune clé n'a été spécifiée" msgid "No long integer support" msgstr "Pas de support entier long" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "No more timers available on this pin." msgstr "Plus de minuteurs disponibles sur cette broche." @@ -1271,6 +1283,10 @@ msgstr "Ne joue pas" msgid "Not running saved code.\n" msgstr "" +#: shared-bindings/_bleio/__init__.c +msgid "Not settable" +msgstr "" + #: shared-bindings/util.c msgid "" "Object has been deinitialized and can no longer be used. Create a new object." @@ -1307,14 +1323,14 @@ msgstr "" msgid "Oversample must be multiple of 8." msgstr "Le sur-échantillonage doit être un multiple de 8." -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM duty_cycle must be between 0 and 65535 inclusive (16 bit resolution)" msgstr "" "La valeur de cycle PWM doit être entre 0 et 65535 inclus (résolution de 16 " "bits)" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM frequency not writable when variable_frequency is False on construction." msgstr "" @@ -1374,8 +1390,8 @@ msgstr "Polygone a besoin d’au moins 3 points" #: ports/nrf/common-hal/pulseio/PulseOut.c #: ports/stm/common-hal/pulseio/PulseOut.c msgid "" -"Port does not accept pins or frequency. " -"Construct and pass a PWMOut Carrier instead" +"Port does not accept pins or frequency. Construct and pass a PWMOut Carrier " +"instead" msgstr "" #: shared-bindings/_bleio/Adapter.c @@ -1390,10 +1406,6 @@ msgstr "Appuyez sur une touche pour entrer sur REPL ou CTRL-D pour recharger." msgid "Pull not used when direction is output." msgstr "Le tirage 'pull' n'est pas utilisé quand la direction est 'output'." -#: ports/stm/ref/pulseout-pre-timeralloc.c -msgid "PulseOut not supported on this chip" -msgstr "PulseOut non pris en charge sur cette puce" - #: ports/stm/common-hal/os/__init__.c msgid "RNG DeInit Error" msgstr "Erreur RNG DeInit" @@ -1614,7 +1626,7 @@ msgstr "La largeur de la tuile doit diviser exactement la largeur de l'image" msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "Le délai est trop long : le délai maximal est de %d secondes" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "" "Timer was reserved for internal use - declare PWM pins earlier in the program" msgstr "" @@ -2538,6 +2550,10 @@ msgstr "" msgid "initial values must be iterable" msgstr "les valeurs initiales doivent être itérables" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "initial_value length is wrong" +msgstr "" + #: py/compile.c msgid "inline assembler must be a function" msgstr "l'assembleur doit être une fonction" @@ -2734,6 +2750,10 @@ msgstr "la matrice n'est pas définie positive" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "max_length doit être 0-%d lorsque fixed_length est %s" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "max_length must be > 0" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "profondeur maximale de récursivité dépassée" @@ -2972,6 +2992,14 @@ msgstr "" "ord() attend un caractère mais une chaîne de caractère de longueur %d a été " "trouvée" +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of source" +msgstr "" + +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of target" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "dépassement de capacité en convertissant un entier long en mot machine" @@ -3152,6 +3180,10 @@ msgstr "" msgid "sosfilt requires iterable arguments" msgstr "" +#: shared-bindings/displayio/Bitmap.c +msgid "source palette too large" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "indices de début/fin" @@ -3449,6 +3481,9 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "PulseOut not supported on this chip" +#~ msgstr "PulseOut non pris en charge sur cette puce" + #~ msgid "tuple/list required on RHS" #~ msgstr "tuple ou liste requis en partie droite" diff --git a/locale/hi.po b/locale/hi.po index 50a1887f67..3803348aa4 100644 --- a/locale/hi.po +++ b/locale/hi.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-08-18 11:19-0400\n" +"POT-Creation-Date: 2020-08-30 14:38-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" @@ -301,7 +301,7 @@ msgstr "" msgid "All sync event channels in use" msgstr "" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "All timers for this pin are in use" msgstr "" @@ -313,7 +313,7 @@ msgstr "" #: ports/cxd56/common-hal/pulseio/PulseOut.c #: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c -#: ports/stm/peripherals/timers.c shared-bindings/pulseio/PWMOut.c +#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c msgid "All timers in use" msgstr "" @@ -489,6 +489,10 @@ msgstr "" msgid "Can't set CCCD on local Characteristic" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Cannot create a new Adapter; use _bleio.adapter;" +msgstr "" + #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c @@ -551,7 +555,7 @@ msgstr "" msgid "Cannot unambiguously get sizeof scalar" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Cannot vary frequency on a timer that is already in use" msgstr "" @@ -620,23 +624,23 @@ msgstr "" msgid "Could not initialize UART" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize channel" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize timer" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init channel" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init timer" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not restart PWM" msgstr "" @@ -644,7 +648,7 @@ msgstr "" msgid "Could not set address" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not start PWM" msgstr "" @@ -741,8 +745,8 @@ msgstr "" msgid "Error in regex" msgstr "" -#: shared-bindings/aesio/aes.c shared-bindings/busio/SPI.c -#: shared-bindings/microcontroller/Pin.c +#: shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c +#: shared-bindings/busio/SPI.c shared-bindings/microcontroller/Pin.c #: shared-bindings/neopixel_write/__init__.c #: shared-bindings/terminalio/Terminal.c msgid "Expected a %q" @@ -753,10 +757,18 @@ msgstr "" msgid "Expected a Characteristic" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a DigitalInOut" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a UART" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c #: shared-bindings/_bleio/Service.c msgid "Expected a UUID" @@ -835,7 +847,7 @@ msgstr "" msgid "Frequency captured is above capability. Capture Paused." msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Frequency must match existing PWMOut using this timer" msgstr "" @@ -937,9 +949,9 @@ msgstr "" msgid "Invalid DAC pin supplied" msgstr "" -#: ports/atmel-samd/common-hal/pulseio/PWMOut.c -#: ports/cxd56/common-hal/pulseio/PWMOut.c -#: ports/nrf/common-hal/pulseio/PWMOut.c shared-bindings/pulseio/PWMOut.c +#: ports/atmel-samd/common-hal/pwmio/PWMOut.c +#: ports/cxd56/common-hal/pwmio/PWMOut.c ports/nrf/common-hal/pwmio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "Invalid PWM frequency" msgstr "" @@ -979,7 +991,7 @@ msgstr "" msgid "Invalid format chunk size" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid frequency supplied" msgstr "" @@ -997,8 +1009,8 @@ msgid "Invalid phase" msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c -#: ports/atmel-samd/common-hal/touchio/TouchIn.c -#: shared-bindings/pulseio/PWMOut.c shared-module/rgbmatrix/RGBMatrix.c +#: ports/atmel-samd/common-hal/touchio/TouchIn.c shared-bindings/pwmio/PWMOut.c +#: shared-module/rgbmatrix/RGBMatrix.c msgid "Invalid pin" msgstr "" @@ -1022,7 +1034,7 @@ msgstr "" msgid "Invalid pins" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid pins for PWMOut" msgstr "" @@ -1204,7 +1216,7 @@ msgstr "" msgid "No long integer support" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "No more timers available on this pin." msgstr "" @@ -1242,6 +1254,10 @@ msgstr "" msgid "Not running saved code.\n" msgstr "" +#: shared-bindings/_bleio/__init__.c +msgid "Not settable" +msgstr "" + #: shared-bindings/util.c msgid "" "Object has been deinitialized and can no longer be used. Create a new object." @@ -1272,12 +1288,12 @@ msgstr "" msgid "Oversample must be multiple of 8." msgstr "" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM duty_cycle must be between 0 and 65535 inclusive (16 bit resolution)" msgstr "" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM frequency not writable when variable_frequency is False on construction." msgstr "" @@ -1332,8 +1348,8 @@ msgstr "" #: ports/nrf/common-hal/pulseio/PulseOut.c #: ports/stm/common-hal/pulseio/PulseOut.c msgid "" -"Port does not accept pins or frequency. " -"Construct and pass a PWMOut Carrier instead" +"Port does not accept pins or frequency. Construct and pass a PWMOut Carrier " +"instead" msgstr "" #: shared-bindings/_bleio/Adapter.c @@ -1348,10 +1364,6 @@ msgstr "" msgid "Pull not used when direction is output." msgstr "" -#: ports/stm/ref/pulseout-pre-timeralloc.c -msgid "PulseOut not supported on this chip" -msgstr "" - #: ports/stm/common-hal/os/__init__.c msgid "RNG DeInit Error" msgstr "" @@ -1563,7 +1575,7 @@ msgstr "" msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "" "Timer was reserved for internal use - declare PWM pins earlier in the program" msgstr "" @@ -2452,6 +2464,10 @@ msgstr "" msgid "initial values must be iterable" msgstr "" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "initial_value length is wrong" +msgstr "" + #: py/compile.c msgid "inline assembler must be a function" msgstr "" @@ -2644,6 +2660,10 @@ msgstr "" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "max_length must be > 0" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "" @@ -2878,6 +2898,14 @@ msgstr "" msgid "ord() expected a character, but string of length %d found" msgstr "" +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of source" +msgstr "" + +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of target" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "" @@ -3055,6 +3083,10 @@ msgstr "" msgid "sosfilt requires iterable arguments" msgstr "" +#: shared-bindings/displayio/Bitmap.c +msgid "source palette too large" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "" diff --git a/locale/it_IT.po b/locale/it_IT.po index 9635220af3..e9dfc0474d 100644 --- a/locale/it_IT.po +++ b/locale/it_IT.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-08-18 11:19-0400\n" +"POT-Creation-Date: 2020-08-30 14:38-0400\n" "PO-Revision-Date: 2018-10-02 16:27+0200\n" "Last-Translator: Enrico Paganin \n" "Language-Team: \n" @@ -303,7 +303,7 @@ msgstr "Tutti i canali eventi utilizati" msgid "All sync event channels in use" msgstr "Tutti i canali di eventi sincronizzati in uso" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "All timers for this pin are in use" msgstr "Tutti i timer per questo pin sono in uso" @@ -315,7 +315,7 @@ msgstr "Tutti i timer per questo pin sono in uso" #: ports/cxd56/common-hal/pulseio/PulseOut.c #: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c -#: ports/stm/peripherals/timers.c shared-bindings/pulseio/PWMOut.c +#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c msgid "All timers in use" msgstr "Tutti i timer utilizzati" @@ -495,6 +495,10 @@ msgstr "" msgid "Can't set CCCD on local Characteristic" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Cannot create a new Adapter; use _bleio.adapter;" +msgstr "" + #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c @@ -559,7 +563,7 @@ msgstr "Impossibile trasferire senza i pin MOSI e MISO." msgid "Cannot unambiguously get sizeof scalar" msgstr "Impossibile ricavare la grandezza scalare di sizeof inequivocabilmente" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Cannot vary frequency on a timer that is already in use" msgstr "" @@ -629,23 +633,23 @@ msgstr "" msgid "Could not initialize UART" msgstr "Impossibile inizializzare l'UART" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize channel" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize timer" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init channel" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init timer" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not restart PWM" msgstr "" @@ -653,7 +657,7 @@ msgstr "" msgid "Could not set address" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not start PWM" msgstr "" @@ -752,8 +756,8 @@ msgstr "Canale EXTINT già in uso" msgid "Error in regex" msgstr "Errore nella regex" -#: shared-bindings/aesio/aes.c shared-bindings/busio/SPI.c -#: shared-bindings/microcontroller/Pin.c +#: shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c +#: shared-bindings/busio/SPI.c shared-bindings/microcontroller/Pin.c #: shared-bindings/neopixel_write/__init__.c #: shared-bindings/terminalio/Terminal.c msgid "Expected a %q" @@ -765,10 +769,18 @@ msgstr "Atteso un %q" msgid "Expected a Characteristic" msgstr "Non è possibile aggiungere Characteristic." +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a DigitalInOut" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a UART" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c #: shared-bindings/_bleio/Service.c #, fuzzy @@ -848,7 +860,7 @@ msgstr "" msgid "Frequency captured is above capability. Capture Paused." msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Frequency must match existing PWMOut using this timer" msgstr "" @@ -952,9 +964,9 @@ msgstr "File BMP non valido" msgid "Invalid DAC pin supplied" msgstr "" -#: ports/atmel-samd/common-hal/pulseio/PWMOut.c -#: ports/cxd56/common-hal/pulseio/PWMOut.c -#: ports/nrf/common-hal/pulseio/PWMOut.c shared-bindings/pulseio/PWMOut.c +#: ports/atmel-samd/common-hal/pwmio/PWMOut.c +#: ports/cxd56/common-hal/pwmio/PWMOut.c ports/nrf/common-hal/pwmio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "Invalid PWM frequency" msgstr "Frequenza PWM non valida" @@ -996,7 +1008,7 @@ msgstr "File non valido" msgid "Invalid format chunk size" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid frequency supplied" msgstr "" @@ -1014,8 +1026,8 @@ msgid "Invalid phase" msgstr "Fase non valida" #: ports/atmel-samd/common-hal/audioio/AudioOut.c -#: ports/atmel-samd/common-hal/touchio/TouchIn.c -#: shared-bindings/pulseio/PWMOut.c shared-module/rgbmatrix/RGBMatrix.c +#: ports/atmel-samd/common-hal/touchio/TouchIn.c shared-bindings/pwmio/PWMOut.c +#: shared-module/rgbmatrix/RGBMatrix.c msgid "Invalid pin" msgstr "Pin non valido" @@ -1039,7 +1051,7 @@ msgstr "Pin non valido per il canale destro" msgid "Invalid pins" msgstr "Pin non validi" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid pins for PWMOut" msgstr "" @@ -1223,7 +1235,7 @@ msgstr "" msgid "No long integer support" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "No more timers available on this pin." msgstr "" @@ -1262,6 +1274,10 @@ msgstr "In pausa" msgid "Not running saved code.\n" msgstr "" +#: shared-bindings/_bleio/__init__.c +msgid "Not settable" +msgstr "" + #: shared-bindings/util.c msgid "" "Object has been deinitialized and can no longer be used. Create a new object." @@ -1295,14 +1311,14 @@ msgstr "" msgid "Oversample must be multiple of 8." msgstr "L'oversampling deve essere multiplo di 8." -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM duty_cycle must be between 0 and 65535 inclusive (16 bit resolution)" msgstr "" "duty_cycle del PWM deve essere compresa tra 0 e 65535 inclusiva (risoluzione " "a 16 bit)" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c #, fuzzy msgid "" "PWM frequency not writable when variable_frequency is False on construction." @@ -1361,8 +1377,8 @@ msgstr "" #: ports/nrf/common-hal/pulseio/PulseOut.c #: ports/stm/common-hal/pulseio/PulseOut.c msgid "" -"Port does not accept pins or frequency. " -"Construct and pass a PWMOut Carrier instead" +"Port does not accept pins or frequency. Construct and pass a PWMOut Carrier " +"instead" msgstr "" #: shared-bindings/_bleio/Adapter.c @@ -1378,10 +1394,6 @@ msgstr "" msgid "Pull not used when direction is output." msgstr "" -#: ports/stm/ref/pulseout-pre-timeralloc.c -msgid "PulseOut not supported on this chip" -msgstr "" - #: ports/stm/common-hal/os/__init__.c msgid "RNG DeInit Error" msgstr "" @@ -1596,7 +1608,7 @@ msgstr "" msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "" "Timer was reserved for internal use - declare PWM pins earlier in the program" msgstr "" @@ -2498,6 +2510,10 @@ msgstr "" msgid "initial values must be iterable" msgstr "" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "initial_value length is wrong" +msgstr "" + #: py/compile.c msgid "inline assembler must be a function" msgstr "inline assembler deve essere una funzione" @@ -2695,6 +2711,10 @@ msgstr "" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "max_length must be > 0" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "profondità massima di ricorsione superata" @@ -2934,6 +2954,14 @@ msgid "ord() expected a character, but string of length %d found" msgstr "" "ord() aspettava un carattere, ma ha ricevuto una stringa di lunghezza %d" +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of source" +msgstr "" + +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of target" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "overflow convertendo long int in parola" @@ -3115,6 +3143,10 @@ msgstr "" msgid "sosfilt requires iterable arguments" msgstr "" +#: shared-bindings/displayio/Bitmap.c +msgid "source palette too large" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "" diff --git a/locale/ja.po b/locale/ja.po index 7c3b42580a..b9fb7ce7a5 100644 --- a/locale/ja.po +++ b/locale/ja.po @@ -7,16 +7,16 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-08-18 11:19-0400\n" -"PO-Revision-Date: 2020-08-16 13:25+0000\n" -"Last-Translator: Taku Fukada \n" +"POT-Creation-Date: 2020-08-27 11:21-0400\n" +"PO-Revision-Date: 2020-09-01 18:44+0000\n" +"Last-Translator: Jeff Epler \n" "Language-Team: none\n" "Language: ja\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.2-dev\n" +"X-Generator: Weblate 4.2.1-dev\n" #: main.c msgid "" @@ -42,7 +42,7 @@ msgid "" "To exit, please reset the board without " msgstr "" "\n" -"終了するには、次の操作なしにリセットしてください: " +"終了するには、次の操作をせずにリセットしてください: " #: py/obj.c msgid " File \"%q\"" @@ -84,7 +84,7 @@ msgstr "%q インデックスは範囲外" #: py/obj.c msgid "%q indices must be integers, not %q" -msgstr "%qインデクスは、%qでなく整数が必要です" +msgstr "%qインデクスは、%qでなく整数が必要" #: shared-bindings/vectorio/Polygon.c msgid "%q list must be a list" @@ -121,7 +121,7 @@ msgstr "%q()は%d個の位置引数を受け取りますが、%d個しか与え #: py/argcheck.c msgid "'%q' argument required" -msgstr "引数'%q'が必要" +msgstr "引数 '%q' が必要" #: py/runtime.c msgid "'%q' object cannot assign attribute '%q'" @@ -177,7 +177,7 @@ msgstr "" #: py/emitinlinethumb.c #, c-format msgid "'%s' expects an FPU register" -msgstr "" +msgstr "'%s'にはFPUレジスタが必要" #: py/emitinlinethumb.c #, c-format @@ -227,15 +227,15 @@ msgstr "関数外でのawait" #: py/compile.c msgid "'await', 'async for' or 'async with' outside async function" -msgstr "async関数外でのawait, async for, async with" +msgstr "async関数外での await, async for, async with" #: py/compile.c msgid "'break' outside loop" -msgstr "ループ外での 'break'" +msgstr "ループ外でのbreak" #: py/compile.c msgid "'continue' outside loop" -msgstr "ループ外での 'continue'" +msgstr "ループ外でのcontinue" #: py/objgenerator.c msgid "'coroutine' object is not an iterator" @@ -243,11 +243,11 @@ msgstr "'coroutine' オブジェクトはイテレータではありません" #: py/compile.c msgid "'data' requires at least 2 arguments" -msgstr "" +msgstr "'data'には少なくとも2つの引数が必要" #: py/compile.c msgid "'data' requires integer arguments" -msgstr "" +msgstr "'data'には整数の引数が必要" #: py/compile.c msgid "'label' requires 1 argument" @@ -255,11 +255,11 @@ msgstr "" #: py/compile.c msgid "'return' outside function" -msgstr "関数外での 'return'" +msgstr "関数外でのreturn" #: py/compile.c msgid "'yield' outside function" -msgstr "関数外での 'yield'" +msgstr "関数外でのyield" #: py/compile.c msgid "*x must be assignment target" @@ -285,7 +285,7 @@ msgstr "ハードウェア割り込みチャネルは使用中" #: shared-bindings/_bleio/Address.c #, c-format msgid "Address must be %d bytes long" -msgstr "アドレスの長さは %d バイトでなければなりません" +msgstr "アドレスは、%dバイト長でなければなりません" #: shared-bindings/_bleio/Address.c msgid "Address type out of range" @@ -311,7 +311,7 @@ msgstr "全てのイベントチャネルが使用中" msgid "All sync event channels in use" msgstr "全ての同期イベントチャネルが使用中" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "All timers for this pin are in use" msgstr "このピン用の全てのタイマが使用中" @@ -323,7 +323,7 @@ msgstr "このピン用の全てのタイマが使用中" #: ports/cxd56/common-hal/pulseio/PulseOut.c #: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c -#: ports/stm/peripherals/timers.c shared-bindings/pulseio/PWMOut.c +#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c msgid "All timers in use" msgstr "全てのタイマーが使用中" @@ -369,16 +369,16 @@ msgstr "Arrayの各値は1バイトでなければなりません" #: shared-bindings/microcontroller/Pin.c msgid "At most %d %q may be specified (not %d)" -msgstr "最大で %d 個の %q が指定できます(%d個でなく)" +msgstr "最大で %d個の %q が指定できます(%d個でなく)" #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" -msgstr "%d 個のブロックの確保を試みました" +msgstr "%d個のブロックの確保を試みました" #: supervisor/shared/safe_mode.c msgid "Attempted heap allocation when MicroPython VM not running." -msgstr "MicroPython VMの非実行時にヒープの確保を試みました" +msgstr "MicroPython VM 非実行時にヒープの確保を試みました" #: main.c msgid "Auto-reload is off.\n" @@ -407,7 +407,7 @@ msgstr "ビット深度は8の倍数でなければなりません" #: ports/mimxrt10xx/common-hal/busio/UART.c msgid "Both RX and TX required for flow control" -msgstr "フロー制御のためにRXとTXの両方が必要" +msgstr "フロー制御のためRXとTXの両方が必要" #: ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c msgid "Both pins must support hardware interrupts" @@ -417,7 +417,7 @@ msgstr "両方のピンにハードウェア割り込み対応が必要" #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-bindings/rgbmatrix/RGBMatrix.c msgid "Brightness must be 0-1.0" -msgstr "Brightnessは0から1.0まででなければなりません" +msgstr "brightnessは0から1.0まででなければなりません" #: shared-bindings/supervisor/__init__.c msgid "Brightness must be between 0 and 255" @@ -529,7 +529,7 @@ msgstr "同じピン上の両チャネルに出力できません" #: shared-module/bitbangio/SPI.c msgid "Cannot read without MISO pin." -msgstr "MISOピンなしで読み込みはできません" +msgstr "MISOピンなしで読み込めません" #: shared-bindings/audiobusio/PDMIn.c msgid "Cannot record to a file" @@ -537,13 +537,13 @@ msgstr "ファイルへ記録できません" #: shared-module/storage/__init__.c msgid "Cannot remount '/' when USB is active." -msgstr "USBがアクティブな時に '/' を再マウントできません" +msgstr "USBがアクティブの時に'/'を再マウントできません" #: ports/atmel-samd/common-hal/microcontroller/__init__.c #: ports/cxd56/common-hal/microcontroller/__init__.c #: ports/mimxrt10xx/common-hal/microcontroller/__init__.c msgid "Cannot reset into bootloader because no bootloader is present." -msgstr "ブートローダが存在しないためブートローダへとリセットできません" +msgstr "ブートローダが存在しないため、ブートローダへとリセットできません" #: shared-bindings/digitalio/DigitalInOut.c msgid "Cannot set value when direction is input." @@ -565,13 +565,13 @@ msgstr "MOSIピンとMISOピンなしに転送できません" msgid "Cannot unambiguously get sizeof scalar" msgstr "スカラのサイズを曖昧さなしに取得できません" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Cannot vary frequency on a timer that is already in use" -msgstr "使用中のタイマー上で周波数を変えられません" +msgstr "使用中のタイマー上では周波数を変えられません" #: shared-module/bitbangio/SPI.c msgid "Cannot write without MOSI pin." -msgstr "MOSIピンなしに書き込みできません" +msgstr "MOSIピンなしで書き込みできません" #: shared-bindings/_bleio/CharacteristicBuffer.c msgid "CharacteristicBuffer writing not provided" @@ -622,7 +622,7 @@ msgstr "破損した .mpy ファイル" #: py/emitglue.c msgid "Corrupt raw code" -msgstr "破損した raw code" +msgstr "破損したraw code" #: ports/cxd56/common-hal/gnss/GNSS.c msgid "Could not initialize GNSS" @@ -636,31 +636,31 @@ msgstr "SDカードを初期化できません" msgid "Could not initialize UART" msgstr "UARTを初期化できません" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize channel" msgstr "チャネルを初期化できません" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize timer" msgstr "タイマーを初期化できません" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init channel" msgstr "チャネルを再初期化できません" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init timer" msgstr "タイマーを再初期化できません" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not restart PWM" msgstr "PWMを再スタートできません" #: shared-bindings/_bleio/Adapter.c msgid "Could not set address" -msgstr "" +msgstr "アドレスをセットできません" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not start PWM" msgstr "PWMをスタートできません" @@ -762,7 +762,7 @@ msgstr "正規表現にエラーがあります" #: shared-bindings/neopixel_write/__init__.c #: shared-bindings/terminalio/Terminal.c msgid "Expected a %q" -msgstr "" +msgstr "%qが必要" #: shared-bindings/_bleio/CharacteristicBuffer.c #: shared-bindings/_bleio/Descriptor.c shared-bindings/_bleio/PacketBuffer.c @@ -776,7 +776,7 @@ msgstr "" #: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c #: shared-bindings/_bleio/Service.c msgid "Expected a UUID" -msgstr "" +msgstr "UUIDが必要" #: shared-bindings/_bleio/Adapter.c msgid "Expected an Address" @@ -793,7 +793,7 @@ msgstr "" #: extmod/ulab/code/fft/fft.c msgid "FFT is defined for ndarrays only" -msgstr "FFTは ndarray に対してのみ定義されています" +msgstr "FFTはndarrayでのみ使えます" #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." @@ -815,7 +815,7 @@ msgstr "RXバッファの確保に失敗" #: ports/stm/common-hal/pulseio/PulseIn.c #, c-format msgid "Failed to allocate RX buffer of %d bytes" -msgstr "%d バイトのRXバッファの確保に失敗" +msgstr "%dバイトのRXバッファの確保に失敗" #: ports/nrf/common-hal/_bleio/Adapter.c msgid "Failed to connect: internal error" @@ -849,11 +849,11 @@ msgstr "" #: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c msgid "Frequency captured is above capability. Capture Paused." -msgstr "" +msgstr "キャプチャした周波数は能力を超えています。キャプチャ停止" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Frequency must match existing PWMOut using this timer" -msgstr "このタイマーを使う既存のPWMOutと周波数を一致させてください" +msgstr "このタイマーを使う既存のPWMOutと周波数を一致させる必要があります" #: shared-bindings/bitbangio/I2C.c shared-bindings/bitbangio/SPI.c #: shared-bindings/busio/I2C.c shared-bindings/busio/SPI.c @@ -877,11 +877,11 @@ msgstr "ハードウェアビジー。代替のピンを試してください" #: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "Hardware in use, try alternative pins" -msgstr "ハードウェア使用中。代替のピンを試してください" +msgstr "ハードウェア使用中。代わりのピンを試してください" #: extmod/vfs_posix_file.c py/objstringio.c msgid "I/O operation on closed file" -msgstr "閉じられたファイルに対するI/O操作" +msgstr "閉じられたファイルへのI/O操作" #: ports/stm/common-hal/busio/I2C.c msgid "I2C Init Error" @@ -894,15 +894,13 @@ msgstr "I2SOutが利用できません" #: shared-bindings/aesio/aes.c #, c-format msgid "IV must be %d bytes long" -msgstr "IV の長さは %d バイトでなければなりません" +msgstr "IVは%dバイト長でなければなりません" #: py/persistentcode.c msgid "" "Incompatible .mpy file. Please update all .mpy files. See http://adafru.it/" "mpy-update for more info." -msgstr "" -"非互換の.mpyファイルです。全ての.mpyファイルをアップデートしてください。詳細" -"は http://adafru.it/mpy-update を参照" +msgstr "非互換の.mpyファイルです。全ての.mpyファイルを更新してください。詳細は http://adafru.it/mpy-update を参照" #: shared-bindings/_pew/PewPew.c msgid "Incorrect buffer size" @@ -941,7 +939,7 @@ msgstr "不正な%qピン" #: ports/stm/common-hal/busio/I2C.c ports/stm/common-hal/busio/SPI.c #: ports/stm/common-hal/busio/UART.c ports/stm/common-hal/sdioio/SDCard.c msgid "Invalid %q pin selection" -msgstr "" +msgstr "不正な%qピン選択" #: ports/stm/common-hal/analogio/AnalogIn.c msgid "Invalid ADC Unit value" @@ -953,11 +951,11 @@ msgstr "不正なBMPファイル" #: ports/stm/common-hal/analogio/AnalogOut.c msgid "Invalid DAC pin supplied" -msgstr "無効なDACピンが与えられました" +msgstr "不正なDACピンが与えられました" -#: ports/atmel-samd/common-hal/pulseio/PWMOut.c -#: ports/cxd56/common-hal/pulseio/PWMOut.c -#: ports/nrf/common-hal/pulseio/PWMOut.c shared-bindings/pulseio/PWMOut.c +#: ports/atmel-samd/common-hal/pwmio/PWMOut.c +#: ports/cxd56/common-hal/pwmio/PWMOut.c ports/nrf/common-hal/pwmio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "Invalid PWM frequency" msgstr "無効なPWM周波数" @@ -967,7 +965,7 @@ msgstr "不正な引数" #: shared-module/displayio/Bitmap.c msgid "Invalid bits per value" -msgstr "値ごとのビット数が不正" +msgstr "不正なbits per value" #: ports/nrf/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "Invalid buffer size" @@ -979,7 +977,7 @@ msgstr "不正なバイトオーダー文字列" #: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c msgid "Invalid capture period. Valid range: 1 - 500" -msgstr "不正なキャプチャ周期。有効な周期は1 - 500" +msgstr "不正なキャプチャ周期。有効な周期は1-500" #: shared-bindings/audiomixer/Mixer.c msgid "Invalid channel count" @@ -987,7 +985,7 @@ msgstr "不正なチャンネル数" #: shared-bindings/digitalio/DigitalInOut.c msgid "Invalid direction." -msgstr "不正な方向" +msgstr "不正な入出力方向" #: shared-module/audiocore/WaveFile.c msgid "Invalid file" @@ -997,7 +995,7 @@ msgstr "不正なファイル" msgid "Invalid format chunk size" msgstr "フォーマットチャンクのサイズが不正" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid frequency supplied" msgstr "不正な周波数が与えられました" @@ -1012,11 +1010,11 @@ msgstr "不正なビット数" #: shared-bindings/bitbangio/SPI.c shared-bindings/busio/SPI.c #: shared-bindings/displayio/FourWire.c msgid "Invalid phase" -msgstr "" +msgstr "不正なphase" #: ports/atmel-samd/common-hal/audioio/AudioOut.c -#: ports/atmel-samd/common-hal/touchio/TouchIn.c -#: shared-bindings/pulseio/PWMOut.c shared-module/rgbmatrix/RGBMatrix.c +#: ports/atmel-samd/common-hal/touchio/TouchIn.c shared-bindings/pwmio/PWMOut.c +#: shared-module/rgbmatrix/RGBMatrix.c msgid "Invalid pin" msgstr "不正なピン" @@ -1040,7 +1038,7 @@ msgstr "右チャネルのピンが不正" msgid "Invalid pins" msgstr "ピンが不正" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid pins for PWMOut" msgstr "PWMOutのピンが不正" @@ -1055,11 +1053,11 @@ msgstr "不正なプロパティ" #: shared-bindings/microcontroller/__init__.c msgid "Invalid run mode." -msgstr "不正な Run Mode" +msgstr "不正なRun Mode" #: shared-module/_bleio/Attribute.c msgid "Invalid security_mode" -msgstr "不正な security_mode" +msgstr "不正なsecurity_mode" #: shared-bindings/audiomixer/Mixer.c msgid "Invalid voice" @@ -1071,7 +1069,7 @@ msgstr "不正なボイス数" #: shared-module/audiocore/WaveFile.c msgid "Invalid wave file" -msgstr "不正なWaveファイル" +msgstr "不正なwaveファイル" #: ports/stm/common-hal/busio/UART.c msgid "Invalid word/bit length" @@ -1167,7 +1165,7 @@ msgstr "DMAチャネルが見つかりません" #: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/SPI.c msgid "No MISO Pin" -msgstr "MISOピンがありません" +msgstr "MISOピンなし" #: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/SPI.c msgid "No MOSI Pin" @@ -1203,7 +1201,7 @@ msgstr "使われていないGCLKがありません" #: shared-bindings/os/__init__.c msgid "No hardware random available" -msgstr "ハードウェア乱数が利用できません" +msgstr "利用可能なハードウェア乱数なし" #: ports/atmel-samd/common-hal/ps2io/Ps2.c msgid "No hardware support on clk pin" @@ -1222,7 +1220,7 @@ msgstr "キーが指定されていません" msgid "No long integer support" msgstr "long integerサポートがありません" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "No more timers available on this pin." msgstr "このピンに利用可能なタイマーがもうありません" @@ -1254,7 +1252,7 @@ msgstr "接続されていません" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c #: shared-bindings/audiopwmio/PWMAudioOut.c msgid "Not playing" -msgstr "再生中していません" +msgstr "再生していません" #: main.c msgid "Not running saved code.\n" @@ -1290,15 +1288,14 @@ msgstr "" #: shared-bindings/audiobusio/PDMIn.c msgid "Oversample must be multiple of 8." -msgstr "オーバーサンプルは8の倍数でなければなりません" +msgstr "オーバーサンプルは8の倍数が必要" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM duty_cycle must be between 0 and 65535 inclusive (16 bit resolution)" -msgstr "" -"PWMの duty_cycle 値は 0 から 65535 の間でなければなりません(16ビット解像度)" +msgstr "PWMのduty_cycle値は0から65535の間でなければなりません(16ビット解像度)" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM frequency not writable when variable_frequency is False on construction." msgstr "PWM周波数は、生成時のvariable_frequencyがFalseのとき書き換え不可" @@ -1353,8 +1350,8 @@ msgstr "ポリゴンには少なくとも3つの点が必要" #: ports/nrf/common-hal/pulseio/PulseOut.c #: ports/stm/common-hal/pulseio/PulseOut.c msgid "" -"Port does not accept pins or frequency. " -"Construct and pass a PWMOut Carrier instead" +"Port does not accept pins or frequency. Construct and pass a PWMOut Carrier " +"instead" msgstr "" #: shared-bindings/_bleio/Adapter.c @@ -1364,7 +1361,7 @@ msgstr "Prefixバッファはヒープ上になければなりません" #: main.c #, fuzzy msgid "Press any key to enter the REPL. Use CTRL-D to reload." -msgstr "何らかのキーを押すとREPLに入ります。CTRL-Dでリロードします" +msgstr "いずれかのキーを押すとREPLに入ります。リロードはCTRL-D" #: shared-bindings/digitalio/DigitalInOut.c msgid "Pull not used when direction is output." @@ -1372,11 +1369,11 @@ msgstr "方向がoutputのときpullは使われません" #: ports/stm/ref/pulseout-pre-timeralloc.c msgid "PulseOut not supported on this chip" -msgstr "" +msgstr "PulseOutはこのチップでサポートされていません" #: ports/stm/common-hal/os/__init__.c msgid "RNG DeInit Error" -msgstr "乱数生成器の解体エラー" +msgstr "RNG解体エラー" #: ports/stm/common-hal/os/__init__.c msgid "RNG Init Error" @@ -1427,7 +1424,7 @@ msgstr "要求のAESモードは非サポート" #: ports/atmel-samd/common-hal/audioio/AudioOut.c msgid "Right channel unsupported" -msgstr "右チャネルは非サポート" +msgstr "右チャネルはサポートされていません" #: shared-bindings/_pew/PewPew.c msgid "Row entry must be digitalio.DigitalInOut" @@ -1454,7 +1451,7 @@ msgstr "" #: ports/stm/common-hal/sdioio/SDCard.c #, c-format msgid "SDIO Init Error %d" -msgstr "" +msgstr "SDIO初期化エラー %d" #: ports/stm/common-hal/busio/SPI.c msgid "SPI Init Error" @@ -1466,7 +1463,7 @@ msgstr "SPI再初期化エラー" #: shared-bindings/audiomixer/Mixer.c msgid "Sample rate must be positive" -msgstr "サンプルレートは正数でなければなりません" +msgstr "サンプルレートには正の数が必要" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #, c-format @@ -1479,7 +1476,7 @@ msgstr "スキャンはすでに進行中。stop_scanで停止してください #: ports/mimxrt10xx/common-hal/busio/UART.c msgid "Selected CTS pin not valid" -msgstr "選択されたCTSピンが不正です" +msgstr "選択されたCTSピンが不正" #: ports/mimxrt10xx/common-hal/busio/UART.c msgid "Selected RTS pin not valid" @@ -1515,7 +1512,7 @@ msgstr "スタックサイズは少なくとも256以上が必要" #: shared-bindings/multiterminal/__init__.c msgid "Stream missing readinto() or write() method." -msgstr "" +msgstr "streamにreadinto()またはwrite()メソッドがありません" #: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "Supply at least one UART pin" @@ -1534,8 +1531,8 @@ msgid "" "The CircuitPython heap was corrupted because the stack was too small.\n" "Please increase the stack size if you know how, or if not:" msgstr "" -"スタックが小さすぎたことによりCircuitPythonのヒープが破損しました。\n" -"スタックサイズを上げるか、その方法が分からなければ:" +"スタックが小さすぎたためCircuitPythonのヒープが壊れました。\n" +"スタックサイズを上げるか、その方法が分からなければ:" #: supervisor/shared/safe_mode.c msgid "" @@ -1566,11 +1563,11 @@ msgstr "" #: shared-module/audiomixer/MixerVoice.c msgid "The sample's sample rate does not match the mixer's" -msgstr "" +msgstr "サンプルレートがサンプルとミキサーで一致しません" #: shared-module/audiomixer/MixerVoice.c msgid "The sample's signedness does not match the mixer's" -msgstr "サンプルの符号有無がミキサーと一致しません" +msgstr "符号の有無がサンプルとミキサーで一致しません" #: shared-bindings/displayio/TileGrid.c msgid "Tile height must exactly divide bitmap height" @@ -1582,7 +1579,7 @@ msgstr "タイルのインデクスが範囲外" #: shared-bindings/displayio/TileGrid.c msgid "Tile value out of bounds" -msgstr "タイルの値が範囲外" +msgstr "タイル値が範囲外" #: shared-bindings/displayio/TileGrid.c msgid "Tile width must exactly divide bitmap width" @@ -1591,9 +1588,9 @@ msgstr "タイルの幅はビットマップの幅を割り切れる値でなけ #: ports/nrf/common-hal/_bleio/Adapter.c #, c-format msgid "Timeout is too long: Maximum timeout length is %d seconds" -msgstr "タイムアウトが長すぎ。最大のタイムアウト長は%d秒" +msgstr "タイムアウトが長すぎです。最大のタイムアウト長は%d秒" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "" "Timer was reserved for internal use - declare PWM pins earlier in the program" msgstr "" @@ -1616,7 +1613,7 @@ msgstr "" #: py/obj.c msgid "Traceback (most recent call last):\n" -msgstr "" +msgstr "トレースバック(最新の呼び出しが末尾):\n" #: shared-bindings/time/__init__.c msgid "Tuple or struct_time argument required" @@ -1672,7 +1669,7 @@ msgstr "" #: shared-module/displayio/I2CDisplay.c #, c-format msgid "Unable to find I2C Display at %x" -msgstr "" +msgstr "I2Cディスプレイを %x に見つけられません" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c @@ -1685,7 +1682,7 @@ msgstr "パーザを初期化できません" #: shared-module/displayio/OnDiskBitmap.c msgid "Unable to read color palette data" -msgstr "カラーパレットのデータを読み込めません" +msgstr "カラーパレットデータを読み込めません" #: shared-bindings/nvm/ByteArray.c msgid "Unable to write to nvm." @@ -1728,7 +1725,7 @@ msgstr "" #: ports/atmel-samd/common-hal/busio/I2C.c ports/cxd56/common-hal/busio/I2C.c #: ports/stm/common-hal/busio/I2C.c msgid "Unsupported baudrate" -msgstr "" +msgstr "非サポートのbaudrate" #: shared-module/displayio/display_core.c msgid "Unsupported display bus type" @@ -1736,11 +1733,11 @@ msgstr "" #: shared-module/audiocore/WaveFile.c msgid "Unsupported format" -msgstr "" +msgstr "サポートされていないフォーマット" #: py/moduerrno.c msgid "Unsupported operation" -msgstr "" +msgstr "サポートされていない操作" #: shared-bindings/digitalio/DigitalInOut.c msgid "Unsupported pull value." @@ -1762,7 +1759,7 @@ msgstr "" #: ports/stm/common-hal/microcontroller/Processor.c msgid "Voltage read timed out" -msgstr "" +msgstr "電圧読み取りがタイムアウト" #: main.c msgid "WARNING: Your code filename has two extensions\n" @@ -1824,11 +1821,11 @@ msgstr "" #: extmod/modubinascii.c extmod/moduhashlib.c py/objarray.c msgid "a bytes-like object is required" -msgstr "" +msgstr "bytes-likeオブジェクトが必要" #: lib/embed/abort_.c msgid "abort() called" -msgstr "" +msgstr "abort()が呼ばれました" #: extmod/machine_mem.c #, c-format @@ -1837,7 +1834,7 @@ msgstr "" #: shared-bindings/i2cperipheral/I2CPeripheral.c msgid "address out of bounds" -msgstr "" +msgstr "アドレスが範囲外" #: shared-bindings/i2cperipheral/I2CPeripheral.c msgid "addresses is empty" @@ -1870,7 +1867,7 @@ msgstr "" #: py/runtime.c msgid "argument should be a '%q' not a '%q'" -msgstr "" +msgstr "引数には '%q' が必要('%q' ではなく)" #: extmod/ulab/code/linalg/linalg.c msgid "arguments must be ndarrays" @@ -1878,7 +1875,7 @@ msgstr "" #: py/objarray.c shared-bindings/nvm/ByteArray.c msgid "array/bytes required on right side" -msgstr "" +msgstr "右辺にはarray/bytesが必要" #: extmod/ulab/code/numerical/numerical.c msgid "attempt to get argmin/argmax of an empty sequence" @@ -1886,7 +1883,7 @@ msgstr "" #: py/objstr.c msgid "attributes not supported yet" -msgstr "" +msgstr "属性はまだサポートされていません" #: extmod/ulab/code/numerical/numerical.c msgid "axis must be -1, 0, None, or 1" @@ -1898,7 +1895,7 @@ msgstr "axisは -1, 0, 1 のいずれかでなければなりません" #: extmod/ulab/code/numerical/numerical.c msgid "axis must be None, 0, or 1" -msgstr "axisは None, 0, 1 のいずれかが必要です" +msgstr "axisは None, 0, 1 のいずれか" #: py/builtinevex.c msgid "bad compile mode" @@ -1910,11 +1907,11 @@ msgstr "" #: py/objstr.c msgid "bad format string" -msgstr "" +msgstr "不正な書式化文字列" #: py/binary.c msgid "bad typecode" -msgstr "typecodeが不正" +msgstr "不正なtypecode" #: py/emitnative.c msgid "binary op %q not implemented" @@ -1922,7 +1919,7 @@ msgstr "" #: shared-bindings/busio/UART.c msgid "bits must be 7, 8 or 9" -msgstr "" +msgstr "bitsは7, 8, 9のいずれかが必要" #: shared-bindings/audiomixer/Mixer.c msgid "bits_per_sample must be 8 or 16" @@ -1959,7 +1956,7 @@ msgstr "" #: shared-bindings/_pixelbuf/PixelBuf.c msgid "byteorder is not a string" -msgstr "" +msgstr "byteorderが文字列ではありません" #: ports/atmel-samd/common-hal/busio/UART.c msgid "bytes > 8 bits not supported" @@ -1967,15 +1964,15 @@ msgstr "" #: py/objstr.c msgid "bytes value out of range" -msgstr "" +msgstr "範囲外のバイト値" #: ports/atmel-samd/bindings/samd/Clock.c ports/atmel-samd/common-hal/rtc/RTC.c msgid "calibration is out of range" -msgstr "" +msgstr "キャリブレーションが範囲外" #: ports/atmel-samd/bindings/samd/Clock.c msgid "calibration is read only" -msgstr "" +msgstr "calibrationは読み込み専用" #: ports/atmel-samd/common-hal/rtc/RTC.c msgid "calibration value out of range +/-127" @@ -1995,24 +1992,24 @@ msgstr "" #: py/objtype.c msgid "can't add special method to already-subclassed class" -msgstr "" +msgstr "サブクラス化済みのクラスに特殊メソッドを追加できません" #: py/compile.c msgid "can't assign to expression" -msgstr "" +msgstr "式には代入できません" #: py/obj.c py/objint.c shared-bindings/i2cperipheral/I2CPeripheral.c #: shared-module/_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" -msgstr "" +msgstr "%qを%qに変換できません" #: py/objstr.c msgid "can't convert '%q' object to %q implicitly" -msgstr "" +msgstr "オブジェクト '%q' を %q に暗黙に変換できません" #: py/obj.c msgid "can't convert to %q" -msgstr "" +msgstr "%q に変換できません" #: py/objstr.c msgid "can't convert to str implicitly" @@ -2020,7 +2017,7 @@ msgstr "" #: py/compile.c msgid "can't declare nonlocal in outer code" -msgstr "" +msgstr "外側のコードでnonlocalは使えません" #: py/compile.c msgid "can't delete expression" @@ -2032,15 +2029,15 @@ msgstr "" #: py/objcomplex.c msgid "can't do truncated division of a complex number" -msgstr "" +msgstr "複素数の切り捨て除算はできません" #: py/compile.c msgid "can't have multiple **x" -msgstr "" +msgstr "複数の **x は持てません" #: py/compile.c msgid "can't have multiple *x" -msgstr "" +msgstr "複数の *x は持てません" #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" @@ -2090,7 +2087,7 @@ msgstr "" #: py/objstr.c msgid "" "can't switch from manual field specification to automatic field numbering" -msgstr "" +msgstr "手動と自動のフィールド指定は混在できません" #: py/objtype.c msgid "cannot create '%q' instances" @@ -2106,11 +2103,11 @@ msgstr "" #: py/builtinimport.c msgid "cannot perform relative import" -msgstr "" +msgstr "相対インポートはできません" #: extmod/ulab/code/ndarray.c msgid "cannot reshape array (incompatible input/output shape)" -msgstr "" +msgstr "入力/出力シェイプが互換でなくreshapeできません" #: py/emitnative.c msgid "casting" @@ -2138,7 +2135,7 @@ msgstr "" #: shared-bindings/displayio/Palette.c msgid "color buffer must be a buffer, tuple, list, or int" -msgstr "" +msgstr "カラーバッファはbuffer, tuple, list, int のいずれかです" #: shared-bindings/displayio/Palette.c msgid "color buffer must be a bytearray or array of type 'b' or 'B'" @@ -2146,7 +2143,7 @@ msgstr "" #: shared-bindings/displayio/Palette.c msgid "color must be between 0x000000 and 0xffffff" -msgstr "" +msgstr "色は0x000000から0xffffffでなければなりません" #: shared-bindings/displayio/ColorConverter.c msgid "color should be an int" @@ -2154,7 +2151,7 @@ msgstr "" #: py/objcomplex.c msgid "complex division by zero" -msgstr "" +msgstr "複素数ゼロ除算" #: py/objfloat.c py/parsenum.c msgid "complex values not supported" @@ -2162,7 +2159,7 @@ msgstr "" #: extmod/moduzlib.c msgid "compression header" -msgstr "" +msgstr "圧縮ヘッダー" #: py/parse.c msgid "constant must be an integer" @@ -2174,11 +2171,11 @@ msgstr "" #: extmod/ulab/code/filter/filter.c msgid "convolve arguments must be linear arrays" -msgstr "" +msgstr "convolve引数には1次元arrayが必要" #: extmod/ulab/code/filter/filter.c msgid "convolve arguments must be ndarrays" -msgstr "" +msgstr "convolve引数にはndarrayが必要" #: extmod/ulab/code/filter/filter.c msgid "convolve arguments must not be empty" @@ -2190,7 +2187,7 @@ msgstr "" #: extmod/ulab/code/poly/poly.c msgid "could not invert Vandermonde matrix" -msgstr "" +msgstr "ヴァンデルモンド行列の逆行列を求められません" #: shared-module/sdcardio/SDCard.c msgid "couldn't determine SD card version" @@ -2214,7 +2211,7 @@ msgstr "" #: py/compile.c msgid "default 'except' must be last" -msgstr "" +msgstr "デフォルトのexceptは最後に置く必要があります" #: shared-bindings/audiobusio/PDMIn.c msgid "" @@ -2223,11 +2220,11 @@ msgstr "" #: shared-bindings/audiobusio/PDMIn.c msgid "destination buffer must be an array of type 'H' for bit_depth = 16" -msgstr "" +msgstr "bit_depath = 16 用のバッファにはタイプ'H'のarrayが必要" #: shared-bindings/audiobusio/PDMIn.c msgid "destination_length must be an int >= 0" -msgstr "" +msgstr "desitination_lengthには正の整数が必要" #: py/objdict.c msgid "dict update sequence has wrong length" @@ -2235,7 +2232,7 @@ msgstr "" #: extmod/ulab/code/numerical/numerical.c msgid "diff argument must be an ndarray" -msgstr "" +msgstr "引数にはndarrayが必要" #: py/modmath.c py/objfloat.c py/objint_longlong.c py/objint_mpz.c py/runtime.c #: shared-bindings/math/__init__.c @@ -2325,7 +2322,7 @@ msgstr "f-string: '}'が必要" #: py/parse.c msgid "f-string: single '}' is not allowed" -msgstr "f-string: 1つだけの '}' は許されません" +msgstr "f-string: 1つだけの'}'は許されません" #: shared-bindings/audiocore/WaveFile.c shared-bindings/audiomp3/MP3Decoder.c #: shared-bindings/displayio/OnDiskBitmap.c @@ -2334,7 +2331,7 @@ msgstr "fileにはバイトモードで開かれたファイルが必要" #: shared-bindings/storage/__init__.c msgid "filesystem must provide mount method" -msgstr "" +msgstr "filesystemにはmountメソッドが必要" #: extmod/ulab/code/vector/vectorise.c msgid "first argument must be a callable" @@ -2374,7 +2371,7 @@ msgstr "" #: py/objstr.c msgid "format requires a dict" -msgstr "" +msgstr "formatにはdictが必要" #: py/objdeque.c msgid "full" @@ -2399,7 +2396,7 @@ msgstr "" #: extmod/ulab/code/compare/compare.c msgid "function is implemented for scalars and ndarrays only" -msgstr "" +msgstr "スカラ値およびndarrayのみを受け取ります" #: py/argcheck.c #, c-format @@ -2427,7 +2424,7 @@ msgstr "" #: shared-bindings/time/__init__.c msgid "function takes exactly 9 arguments" -msgstr "この関数はちょうど9個の引数をとります" +msgstr "関数はちょうど9個の引数をとります" #: py/objgenerator.c msgid "generator already executing" @@ -2443,7 +2440,7 @@ msgstr "" #: extmod/moduheapq.c msgid "heap must be a list" -msgstr "" +msgstr "heapにはリストが必要" #: py/compile.c msgid "identifier redefined as global" @@ -2488,7 +2485,7 @@ msgstr "" #: py/compile.c msgid "inline assembler must be a function" -msgstr "" +msgstr "インラインアセンブラは関数でなければなりません" #: extmod/ulab/code/ulab_create.c msgid "input argument must be an integer or a 2-tuple" @@ -2496,7 +2493,7 @@ msgstr "" #: extmod/ulab/code/fft/fft.c msgid "input array length must be power of 2" -msgstr "入力 array の長さは2の累乗でなければなりません" +msgstr "入力array長は2の累乗でなければなりません" #: extmod/ulab/code/poly/poly.c msgid "input data must be an iterable" @@ -2508,7 +2505,7 @@ msgstr "入力行列が非対称" #: extmod/ulab/code/linalg/linalg.c msgid "input matrix is singular" -msgstr "" +msgstr "入力が非正則行列" #: extmod/ulab/code/linalg/linalg.c msgid "input must be square matrix" @@ -2516,7 +2513,7 @@ msgstr "" #: extmod/ulab/code/numerical/numerical.c msgid "input must be tuple, list, range, or ndarray" -msgstr "" +msgstr "入力はtuple, list, range, ndarrayでなければなりません" #: extmod/ulab/code/poly/poly.c msgid "input vectors must be of equal length" @@ -2524,7 +2521,7 @@ msgstr "" #: py/parsenum.c msgid "int() arg 2 must be >= 2 and <= 36" -msgstr "int() の2番目の引数は 2 以上 36 以下でなければなりません" +msgstr "int()の第2引数は2以上36以下でなければなりません" #: py/objstr.c msgid "integer required" @@ -2537,7 +2534,7 @@ msgstr "" #: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" -msgstr "" +msgstr "intervalは%s-%sの範囲でなければなりません" #: lib/netutils/netutils.c msgid "invalid arguments" @@ -2565,7 +2562,7 @@ msgstr "不正な鍵" #: py/compile.c msgid "invalid micropython decorator" -msgstr "" +msgstr "不正なmicropythonデコレータ" #: shared-bindings/random/__init__.c msgid "invalid step" @@ -2590,7 +2587,7 @@ msgstr "数字として不正な構文" #: py/objtype.c msgid "issubclass() arg 1 must be a class" -msgstr "issubclass()の1つ目の引数はクラスです" +msgstr "issubclass()の第1引数はクラスが必要" #: py/objtype.c msgid "issubclass() arg 2 must be a class or a tuple of classes" @@ -2598,19 +2595,19 @@ msgstr "" #: extmod/ulab/code/ndarray.c msgid "iterables are not of the same length" -msgstr "イテレート可能なオブジェクトが同じ長さではありません" +msgstr "iterableが同じ長さではありません" #: extmod/ulab/code/linalg/linalg.c msgid "iterations did not converge" -msgstr "" +msgstr "収束しません" #: py/objstr.c msgid "join expects a list of str/bytes objects consistent with self object" -msgstr "" +msgstr "joinには、str/bytes(のうち自身と一致した型の)リストが必要" #: py/argcheck.c msgid "keyword argument(s) not yet implemented - use normal args instead" -msgstr "" +msgstr "キーワード引数はまだ実装されていません。通常の引数を使ってください。" #: py/bc.c msgid "keywords must be strings" @@ -2618,7 +2615,7 @@ msgstr "キーワードは文字列でなければなりません" #: py/emitinlinethumb.c py/emitinlinextensa.c msgid "label '%q' not defined" -msgstr "" +msgstr "ラベル'%q'は定義されていません" #: py/compile.c msgid "label redefined" @@ -2721,11 +2718,11 @@ msgstr "" #: extmod/ulab/code/numerical/numerical.c msgid "n must be between 0, and 9" -msgstr "nは0から9までです" +msgstr "nは0から9まで" #: py/runtime.c msgid "name '%q' is not defined" -msgstr "名前'%q'は定義されていません" +msgstr "名前 '%q' は定義されていません" #: py/runtime.c msgid "name not defined" @@ -2733,7 +2730,7 @@ msgstr "名前が定義されていません" #: py/compile.c msgid "name reused for argument" -msgstr "名前が引数で再利用されています" +msgstr "引数で名前が再利用されています" #: py/emitnative.c msgid "native yield" @@ -2742,7 +2739,7 @@ msgstr "" #: py/runtime.c #, c-format msgid "need more than %d values to unpack" -msgstr "" +msgstr "アンパックする値は%d個では足りません" #: py/objint_longlong.c py/objint_mpz.c py/runtime.c msgid "negative power with no float support" @@ -2766,7 +2763,7 @@ msgstr "利用可能なNICがありません" #: py/compile.c msgid "no binding for nonlocal found" -msgstr "" +msgstr "nonlocalの対象が見つかりません" #: py/builtinimport.c msgid "no module named '%q'" @@ -2783,7 +2780,7 @@ msgstr "SDカードからの応答がありません" #: py/runtime.c msgid "no such attribute" -msgstr "そのような属性はありません" +msgstr "指定の属性はありません" #: ports/nrf/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" @@ -2791,7 +2788,7 @@ msgstr "" #: py/compile.c msgid "non-default argument follows default argument" -msgstr "" +msgstr "デフォルト引数の後に通常の引数は置けません" #: extmod/modubinascii.c msgid "non-hex digit found" @@ -2815,11 +2812,11 @@ msgstr "" #: py/objstr.c msgid "not enough arguments for format string" -msgstr "" +msgstr "書式化文字列への引数が足りません" #: extmod/ulab/code/poly/poly.c msgid "number of arguments must be 2, or 3" -msgstr "引数の数は2個または3個でなければなりません" +msgstr "引数は2個または3個でなければなりません" #: extmod/ulab/code/ulab_create.c msgid "number of points must be at least 2" @@ -2847,7 +2844,7 @@ msgstr "オブジェクトは要素の取得をサポートしていません" #: py/runtime.c msgid "object not an iterator" -msgstr "オブジェクトはイテレータではありません" +msgstr "オブジェクトがイテレータではありません" #: py/objtype.c py/runtime.c msgid "object not callable" @@ -2863,7 +2860,7 @@ msgstr "オブジェクトはイテレートできません" #: py/obj.c msgid "object of type '%q' has no len()" -msgstr "" +msgstr "オブジェクト(型 '%q')はlen()を持ちません" #: py/obj.c msgid "object with buffer protocol required" @@ -2879,7 +2876,7 @@ msgstr "" #: ports/nrf/common-hal/audiobusio/PDMIn.c msgid "only bit_depth=16 is supported" -msgstr "" +msgstr "bit_depth=16のみサポートしています" #: ports/nrf/common-hal/audiobusio/PDMIn.c msgid "only sample_rate=16000 is supported" @@ -2912,9 +2909,17 @@ msgstr "ord()は1文字を受け取ります" msgid "ord() expected a character, but string of length %d found" msgstr "ord()は1文字を要求しますが、長さ %d の文字列が与えられました" +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of source" +msgstr "ソースが範囲外" + +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of target" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" -msgstr "long int をマシンの word に変換する際にオーバーフローしました" +msgstr "long intをマシンのwordに変換する際にオーバーフローしました" #: shared-bindings/_stage/Layer.c shared-bindings/_stage/Text.c msgid "palette must be 32 bytes long" @@ -2922,7 +2927,7 @@ msgstr "パレットの長さは32バイトでなければなりません" #: shared-bindings/displayio/Palette.c msgid "palette_index should be an int" -msgstr "palette_indexは整数です" +msgstr "palette_indexには整数が必要" #: py/compile.c msgid "parameter annotation must be an identifier" @@ -2966,7 +2971,7 @@ msgstr "pow()の3つ目の引数は0にできません" #: py/objint_mpz.c msgid "pow() with 3 arguments requires integers" -msgstr "pow()の3番目の引数には整数が必要" +msgstr "pow()の第3引数には整数が必要" #: extmod/modutimeq.c msgid "queue overflow" @@ -2974,7 +2979,7 @@ msgstr "キューがオーバーフローしました" #: py/parse.c msgid "raw f-strings are not implemented" -msgstr "" +msgstr "raw f-文字列は実装されていません" #: extmod/ulab/code/fft/fft.c msgid "real and imaginary parts must be of equal length" @@ -2987,7 +2992,7 @@ msgstr "相対インポート" #: py/obj.c #, c-format msgid "requested length %d but object has length %d" -msgstr "長さ%dが必要。オブジェクトの長さは%d" +msgstr "必要な長さは%dですがオブジェクトの長さは%d" #: py/compile.c msgid "return annotation must be an identifier" @@ -3019,9 +3024,7 @@ msgstr "rsplit(None,n)" msgid "" "sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or " "'B'" -msgstr "" -"sample_source バッファは、bytearray または 'h', 'H', 'b', 'B'型のarrayでなけ" -"ればなりません" +msgstr "sample_source バッファには bytearray または 'h','H','b','B'型のarrayが必要" #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "sampling rate out of range" @@ -3037,7 +3040,7 @@ msgstr "スクリプトのコンパイルは非サポート" #: extmod/ulab/code/ndarray.c msgid "shape must be a 2-tuple" -msgstr "shapeは 2値のタプルでなければなりません" +msgstr "shapeは2値のタプルでなければなりません" #: py/objstr.c msgid "sign not allowed in string format specifier" @@ -3091,6 +3094,10 @@ msgstr "" msgid "sosfilt requires iterable arguments" msgstr "" +#: shared-bindings/displayio/Bitmap.c +msgid "source palette too large" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "" @@ -3101,11 +3108,11 @@ msgstr "" #: shared-bindings/random/__init__.c msgid "step must be non-zero" -msgstr "" +msgstr "stepは非ゼロ値が必要" #: shared-bindings/busio/UART.c msgid "stop must be 1 or 2" -msgstr "stopは1または2でなければなりません" +msgstr "stopは1または2のいずれか" #: shared-bindings/random/__init__.c msgid "stop not reachable from start" @@ -3117,11 +3124,11 @@ msgstr "ストリーム操作はサポートされていません" #: py/objstrunicode.c msgid "string indices must be integers, not %q" -msgstr "" +msgstr "文字列のインデクスには整数が必要(%qでなく)" #: py/stream.c msgid "string not supported; use bytes or bytearray" -msgstr "" +msgstr "文字列ではなくbytesまたはbytesarrayが必要" #: extmod/moductypes.c msgid "struct: cannot index" @@ -3137,7 +3144,7 @@ msgstr "部分文字列が見つかりません" #: py/compile.c msgid "super() can't find self" -msgstr "" +msgstr "super()がselfを見つけられません" #: extmod/modujson.c msgid "syntax error in JSON" @@ -3149,7 +3156,7 @@ msgstr "uctypedディスクリプタの構文エラー" #: shared-bindings/touchio/TouchIn.c msgid "threshold must be in the range 0-65536" -msgstr "threshouldは0から65536までです" +msgstr "threshouldは0から65536まで" #: shared-bindings/time/__init__.c msgid "time.struct_time() takes a 9-sequence" @@ -3157,7 +3164,7 @@ msgstr "time.struct_time()は9要素のシーケンスを受け取ります" #: ports/nrf/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" -msgstr "" +msgstr "タイムアウト長がサポートされる最大値を超えています" #: shared-bindings/busio/UART.c msgid "timeout must be 0.0-100.0 seconds" @@ -3177,11 +3184,11 @@ msgstr "v2カードの待機がタイムアウトしました" #: shared-bindings/time/__init__.c msgid "timestamp out of range for platform time_t" -msgstr "" +msgstr "timestampがプラットフォームのtime_tの範囲外" #: shared-module/struct/__init__.c msgid "too many arguments provided with the given format" -msgstr "" +msgstr "指定された書式に対して引数が多すぎます" #: extmod/ulab/code/ndarray.c msgid "too many indices" @@ -3190,11 +3197,11 @@ msgstr "インデクスが多すぎます" #: py/runtime.c #, c-format msgid "too many values to unpack (expected %d)" -msgstr "" +msgstr "アンパックする値が多すぎます (%d個を期待)" #: extmod/ulab/code/approx/approx.c msgid "trapz is defined for 1D arrays of equal length" -msgstr "" +msgstr "trapzは同じ長さの1次元arrayに対して定義されています" #: extmod/ulab/code/linalg/linalg.c msgid "tuple index out of range" @@ -3207,7 +3214,7 @@ msgstr "タプル/リストの長さが正しくありません" #: ports/atmel-samd/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c #: shared-bindings/busio/UART.c msgid "tx and rx cannot both be None" -msgstr "txとrxの両方をNoneにすることはできません" +msgstr "txとrxを両方ともNoneにできません" #: py/objtype.c msgid "type '%q' is not an acceptable base type" @@ -3223,7 +3230,7 @@ msgstr "" #: py/objtype.c msgid "type takes 1 or 3 arguments" -msgstr "typeは1つまたは3つの引数をとります" +msgstr "typeは1つか3つの引数をとります" #: py/objint_longlong.c msgid "ulonglong too large" @@ -3260,7 +3267,7 @@ msgstr "" #: py/objstr.c msgid "unknown format code '%c' for object of type '%q'" -msgstr "" +msgstr "型'%q'のオブジェクトに対する不明な書式コード'%c'" #: py/compile.c msgid "unknown type" @@ -3308,12 +3315,12 @@ msgstr "演算子がサポートしていない型" #: py/runtime.c msgid "unsupported types for %q: '%q', '%q'" -msgstr "" +msgstr "%qでサポートされない型: '%q', '%q'" #: py/objint.c #, c-format msgid "value must fit in %d byte(s)" -msgstr "値は %d バイトに収まらなければなりません" +msgstr "値は%dバイトに収まらなければなりません" #: shared-bindings/displayio/Bitmap.c msgid "value_count must be > 0" @@ -3333,11 +3340,11 @@ msgstr "" #: extmod/ulab/code/linalg/linalg.c msgid "wrong argument type" -msgstr "引数の型が正しくありません" +msgstr "引数の型が不正" #: extmod/ulab/code/ndarray.c msgid "wrong index type" -msgstr "インデクスの型が不正です" +msgstr "インデクスの型が不正" #: extmod/ulab/code/vector/vectorise.c msgid "wrong input type" @@ -3349,7 +3356,7 @@ msgstr "" #: py/runtime.c msgid "wrong number of values to unpack" -msgstr "" +msgstr "アンパックする値の個数が不正です" #: extmod/ulab/code/ndarray.c msgid "wrong operand type" @@ -3365,15 +3372,15 @@ msgstr "" #: shared-bindings/displayio/Shape.c msgid "y should be an int" -msgstr "yは整数でなければなりません" +msgstr "yは整数が必要" #: shared-module/displayio/Shape.c msgid "y value out of bounds" -msgstr "" +msgstr "yが範囲外" #: py/objrange.c msgid "zero step" -msgstr "" +msgstr "ステップが0" #: extmod/ulab/code/filter/filter.c msgid "zi must be an ndarray" @@ -3381,7 +3388,7 @@ msgstr "ziはndarrayでなければなりません" #: extmod/ulab/code/filter/filter.c msgid "zi must be of float type" -msgstr "ziはfloat値が必要です" +msgstr "ziはfloat値が必要" #: extmod/ulab/code/filter/filter.c msgid "zi must be of shape (n_section, 2)" diff --git a/locale/ko.po b/locale/ko.po index ecf539946f..a4e088bc40 100644 --- a/locale/ko.po +++ b/locale/ko.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-08-18 11:19-0400\n" +"POT-Creation-Date: 2020-08-30 14:38-0400\n" "PO-Revision-Date: 2019-05-06 14:22-0700\n" "Last-Translator: \n" "Language-Team: LANGUAGE \n" @@ -302,7 +302,7 @@ msgstr "" msgid "All sync event channels in use" msgstr "" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "All timers for this pin are in use" msgstr "핀의 모든 타이머가 사용 중입니다" @@ -314,7 +314,7 @@ msgstr "핀의 모든 타이머가 사용 중입니다" #: ports/cxd56/common-hal/pulseio/PulseOut.c #: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c -#: ports/stm/peripherals/timers.c shared-bindings/pulseio/PWMOut.c +#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c msgid "All timers in use" msgstr "모든 타이머가 사용 중입니다" @@ -492,6 +492,10 @@ msgstr "" msgid "Can't set CCCD on local Characteristic" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Cannot create a new Adapter; use _bleio.adapter;" +msgstr "" + #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c @@ -554,7 +558,7 @@ msgstr "" msgid "Cannot unambiguously get sizeof scalar" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Cannot vary frequency on a timer that is already in use" msgstr "" @@ -623,23 +627,23 @@ msgstr "" msgid "Could not initialize UART" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize channel" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize timer" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init channel" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init timer" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not restart PWM" msgstr "" @@ -647,7 +651,7 @@ msgstr "" msgid "Could not set address" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not start PWM" msgstr "" @@ -744,8 +748,8 @@ msgstr "" msgid "Error in regex" msgstr "Regex에 오류가 있습니다." -#: shared-bindings/aesio/aes.c shared-bindings/busio/SPI.c -#: shared-bindings/microcontroller/Pin.c +#: shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c +#: shared-bindings/busio/SPI.c shared-bindings/microcontroller/Pin.c #: shared-bindings/neopixel_write/__init__.c #: shared-bindings/terminalio/Terminal.c msgid "Expected a %q" @@ -756,10 +760,18 @@ msgstr "%q 이 예상되었습니다." msgid "Expected a Characteristic" msgstr "특성(Characteristic)이 예상되었습니다." +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a DigitalInOut" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a UART" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c #: shared-bindings/_bleio/Service.c msgid "Expected a UUID" @@ -838,7 +850,7 @@ msgstr "" msgid "Frequency captured is above capability. Capture Paused." msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Frequency must match existing PWMOut using this timer" msgstr "" @@ -940,9 +952,9 @@ msgstr "" msgid "Invalid DAC pin supplied" msgstr "" -#: ports/atmel-samd/common-hal/pulseio/PWMOut.c -#: ports/cxd56/common-hal/pulseio/PWMOut.c -#: ports/nrf/common-hal/pulseio/PWMOut.c shared-bindings/pulseio/PWMOut.c +#: ports/atmel-samd/common-hal/pwmio/PWMOut.c +#: ports/cxd56/common-hal/pwmio/PWMOut.c ports/nrf/common-hal/pwmio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "Invalid PWM frequency" msgstr "" @@ -982,7 +994,7 @@ msgstr "파일이 유효하지 않습니다" msgid "Invalid format chunk size" msgstr "형식 청크 크기가 잘못되었습니다" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid frequency supplied" msgstr "" @@ -1000,8 +1012,8 @@ msgid "Invalid phase" msgstr "단계가 잘못되었습니다" #: ports/atmel-samd/common-hal/audioio/AudioOut.c -#: ports/atmel-samd/common-hal/touchio/TouchIn.c -#: shared-bindings/pulseio/PWMOut.c shared-module/rgbmatrix/RGBMatrix.c +#: ports/atmel-samd/common-hal/touchio/TouchIn.c shared-bindings/pwmio/PWMOut.c +#: shared-module/rgbmatrix/RGBMatrix.c msgid "Invalid pin" msgstr "핀이 잘못되었습니다" @@ -1025,7 +1037,7 @@ msgstr "오른쪽 채널 핀이 잘못되었습니다" msgid "Invalid pins" msgstr "핀이 유효하지 않습니다" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid pins for PWMOut" msgstr "" @@ -1207,7 +1219,7 @@ msgstr "" msgid "No long integer support" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "No more timers available on this pin." msgstr "" @@ -1245,6 +1257,10 @@ msgstr "" msgid "Not running saved code.\n" msgstr "" +#: shared-bindings/_bleio/__init__.c +msgid "Not settable" +msgstr "" + #: shared-bindings/util.c msgid "" "Object has been deinitialized and can no longer be used. Create a new object." @@ -1275,12 +1291,12 @@ msgstr "" msgid "Oversample must be multiple of 8." msgstr "" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM duty_cycle must be between 0 and 65535 inclusive (16 bit resolution)" msgstr "" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM frequency not writable when variable_frequency is False on construction." msgstr "" @@ -1335,8 +1351,8 @@ msgstr "" #: ports/nrf/common-hal/pulseio/PulseOut.c #: ports/stm/common-hal/pulseio/PulseOut.c msgid "" -"Port does not accept pins or frequency. " -"Construct and pass a PWMOut Carrier instead" +"Port does not accept pins or frequency. Construct and pass a PWMOut Carrier " +"instead" msgstr "" #: shared-bindings/_bleio/Adapter.c @@ -1351,10 +1367,6 @@ msgstr "" msgid "Pull not used when direction is output." msgstr "" -#: ports/stm/ref/pulseout-pre-timeralloc.c -msgid "PulseOut not supported on this chip" -msgstr "" - #: ports/stm/common-hal/os/__init__.c msgid "RNG DeInit Error" msgstr "" @@ -1566,7 +1578,7 @@ msgstr "" msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "" "Timer was reserved for internal use - declare PWM pins earlier in the program" msgstr "" @@ -2456,6 +2468,10 @@ msgstr "" msgid "initial values must be iterable" msgstr "" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "initial_value length is wrong" +msgstr "" + #: py/compile.c msgid "inline assembler must be a function" msgstr "" @@ -2648,6 +2664,10 @@ msgstr "" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "max_length must be > 0" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "" @@ -2882,6 +2902,14 @@ msgstr "" msgid "ord() expected a character, but string of length %d found" msgstr "" +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of source" +msgstr "" + +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of target" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "" @@ -3059,6 +3087,10 @@ msgstr "" msgid "sosfilt requires iterable arguments" msgstr "" +#: shared-bindings/displayio/Bitmap.c +msgid "source palette too large" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "" diff --git a/locale/nl.po b/locale/nl.po index 3133596686..9cce2523ed 100644 --- a/locale/nl.po +++ b/locale/nl.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-08-18 11:19-0400\n" +"POT-Creation-Date: 2020-08-30 14:38-0400\n" "PO-Revision-Date: 2020-08-10 19:59+0000\n" "Last-Translator: _fonzlate \n" "Language-Team: none\n" @@ -308,7 +308,7 @@ msgstr "Alle event kanalen zijn in gebruik" msgid "All sync event channels in use" msgstr "Alle sync event kanalen zijn in gebruik" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "All timers for this pin are in use" msgstr "Alle timers voor deze pin zijn in gebruik" @@ -320,7 +320,7 @@ msgstr "Alle timers voor deze pin zijn in gebruik" #: ports/cxd56/common-hal/pulseio/PulseOut.c #: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c -#: ports/stm/peripherals/timers.c shared-bindings/pulseio/PWMOut.c +#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c msgid "All timers in use" msgstr "Alle timers zijn in gebruik" @@ -500,6 +500,10 @@ msgstr "Roep super().__init__() aan voor toegang native object." msgid "Can't set CCCD on local Characteristic" msgstr "Kan CCCD niet toewijzen aan lokaal Characteristic" +#: shared-bindings/_bleio/Adapter.c +msgid "Cannot create a new Adapter; use _bleio.adapter;" +msgstr "" + #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c @@ -564,7 +568,7 @@ msgstr "Kan niet overdragen zonder MOSI en MISO pinnen." msgid "Cannot unambiguously get sizeof scalar" msgstr "Kan niet ondubbelzinning sizeof scalar verkrijgen" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Cannot vary frequency on a timer that is already in use" msgstr "Kan de frequentie van een timer die al in gebruik is niet variëren" @@ -637,23 +641,23 @@ msgstr "Kan SDCard niet initialiseren" msgid "Could not initialize UART" msgstr "Kan UART niet initialiseren" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize channel" msgstr "Kan kanaal niet initialiseren" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize timer" msgstr "Kan timer niet initialiseren" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init channel" msgstr "Kan kanaal niet her-initialiseren" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init timer" msgstr "Kan timer niet her-initialiseren" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not restart PWM" msgstr "Kan PWM niet herstarten" @@ -663,7 +667,7 @@ msgstr "Kan PWM niet herstarten" msgid "Could not set address" msgstr "Kan PWM niet starten" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not start PWM" msgstr "Kan PWM niet starten" @@ -760,8 +764,8 @@ msgstr "EXTINT kanaal al in gebruik" msgid "Error in regex" msgstr "Fout in regex" -#: shared-bindings/aesio/aes.c shared-bindings/busio/SPI.c -#: shared-bindings/microcontroller/Pin.c +#: shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c +#: shared-bindings/busio/SPI.c shared-bindings/microcontroller/Pin.c #: shared-bindings/neopixel_write/__init__.c #: shared-bindings/terminalio/Terminal.c msgid "Expected a %q" @@ -772,10 +776,18 @@ msgstr "Verwacht een %q" msgid "Expected a Characteristic" msgstr "Verwachtte een Characteristic" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a DigitalInOut" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "Verwachtte een Service" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a UART" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c #: shared-bindings/_bleio/Service.c msgid "Expected a UUID" @@ -855,7 +867,7 @@ msgid "Frequency captured is above capability. Capture Paused." msgstr "" "De vastgelegde frequentie is boven de capaciteit. Vastleggen gepauzeerd." -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Frequency must match existing PWMOut using this timer" msgstr "" "Frequentie moet overeenkomen met bestaande PWMOut bij gebruik van deze timer" @@ -962,9 +974,9 @@ msgstr "Ongeldig BMP bestand" msgid "Invalid DAC pin supplied" msgstr "Ongeldige DAC pin opgegeven" -#: ports/atmel-samd/common-hal/pulseio/PWMOut.c -#: ports/cxd56/common-hal/pulseio/PWMOut.c -#: ports/nrf/common-hal/pulseio/PWMOut.c shared-bindings/pulseio/PWMOut.c +#: ports/atmel-samd/common-hal/pwmio/PWMOut.c +#: ports/cxd56/common-hal/pwmio/PWMOut.c ports/nrf/common-hal/pwmio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "Invalid PWM frequency" msgstr "Ongeldige PWM frequentie" @@ -1004,7 +1016,7 @@ msgstr "Ongeldig bestand" msgid "Invalid format chunk size" msgstr "Ongeldig formaat stuk grootte" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid frequency supplied" msgstr "Ongeldige frequentie opgegeven" @@ -1022,8 +1034,8 @@ msgid "Invalid phase" msgstr "Ongeldige fase" #: ports/atmel-samd/common-hal/audioio/AudioOut.c -#: ports/atmel-samd/common-hal/touchio/TouchIn.c -#: shared-bindings/pulseio/PWMOut.c shared-module/rgbmatrix/RGBMatrix.c +#: ports/atmel-samd/common-hal/touchio/TouchIn.c shared-bindings/pwmio/PWMOut.c +#: shared-module/rgbmatrix/RGBMatrix.c msgid "Invalid pin" msgstr "Ongeldige pin" @@ -1047,7 +1059,7 @@ msgstr "Ongeldige pin voor rechter kanaal" msgid "Invalid pins" msgstr "Ongeldige pinnen" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid pins for PWMOut" msgstr "Ongeldige pinnen voor PWMOut" @@ -1229,7 +1241,7 @@ msgstr "Een sleutel was niet gespecificeerd" msgid "No long integer support" msgstr "Geen lange integer ondersteuning" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "No more timers available on this pin." msgstr "Geen timers meer beschikbaar op deze pin." @@ -1267,6 +1279,10 @@ msgstr "Wordt niet afgespeeld" msgid "Not running saved code.\n" msgstr "Opgeslagen code wordt niet uitgevoerd.\n" +#: shared-bindings/_bleio/__init__.c +msgid "Not settable" +msgstr "" + #: shared-bindings/util.c msgid "" "Object has been deinitialized and can no longer be used. Create a new object." @@ -1303,13 +1319,13 @@ msgstr "" msgid "Oversample must be multiple of 8." msgstr "Oversample moet een meervoud van 8 zijn." -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM duty_cycle must be between 0 and 65535 inclusive (16 bit resolution)" msgstr "" "PWM duty_cycle moet tussen 0 en 65535 inclusief zijn (16 bit resolutie)" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM frequency not writable when variable_frequency is False on construction." msgstr "" @@ -1369,8 +1385,8 @@ msgstr "Polygon heeft op zijn minst 3 punten nodig" #: ports/nrf/common-hal/pulseio/PulseOut.c #: ports/stm/common-hal/pulseio/PulseOut.c msgid "" -"Port does not accept pins or frequency. " -"Construct and pass a PWMOut Carrier instead" +"Port does not accept pins or frequency. Construct and pass a PWMOut Carrier " +"instead" msgstr "" #: shared-bindings/_bleio/Adapter.c @@ -1387,10 +1403,6 @@ msgstr "" msgid "Pull not used when direction is output." msgstr "Pull niet gebruikt wanneer de richting output is." -#: ports/stm/ref/pulseout-pre-timeralloc.c -msgid "PulseOut not supported on this chip" -msgstr "PulseOut niet ondersteund door deze chip" - #: ports/stm/common-hal/os/__init__.c msgid "RNG DeInit Error" msgstr "RNG DeInit Fout" @@ -1611,7 +1623,7 @@ msgstr "Tile breedte moet exact de bitmap breedte verdelen" msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "Time-out is te lang. Maximale time-out lengte is %d seconden" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "" "Timer was reserved for internal use - declare PWM pins earlier in the program" msgstr "" @@ -2518,6 +2530,10 @@ msgstr "indices moeten integers, segmenten (slices) of Boolean lijsten zijn" msgid "initial values must be iterable" msgstr "oorspronkelijke waarden moeten itereerbaar zijn" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "initial_value length is wrong" +msgstr "" + #: py/compile.c msgid "inline assembler must be a function" msgstr "inline assembler moet een functie zijn" @@ -2713,6 +2729,10 @@ msgstr "matrix is niet positief-definiet" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "max_length moet 0-%d zijn als fixed_length %s is" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "max_length must be > 0" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "maximale recursiediepte overschreden" @@ -2947,6 +2967,14 @@ msgstr "ord verwacht een teken (char)" msgid "ord() expected a character, but string of length %d found" msgstr "ord() verwacht een teken (char) maar vond een string van lengte %d" +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of source" +msgstr "" + +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of target" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "overloop bij converteren van long int naar machine word" @@ -3127,6 +3155,10 @@ msgstr "sos[:, 3] moeten allemaal 1 zijn" msgid "sosfilt requires iterable arguments" msgstr "sosfilt vereist itereerbare argumenten" +#: shared-bindings/displayio/Bitmap.c +msgid "source palette too large" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "start/stop indices" @@ -3423,6 +3455,9 @@ msgstr "zi moet van type float zijn" msgid "zi must be of shape (n_section, 2)" msgstr "zi moet vorm (n_section, 2) hebben" +#~ msgid "PulseOut not supported on this chip" +#~ msgstr "PulseOut niet ondersteund door deze chip" + #~ msgid "tuple/list required on RHS" #~ msgstr "tuple of lijst vereist op RHS" diff --git a/locale/pl.po b/locale/pl.po index 6c52062d9a..b072629cd1 100644 --- a/locale/pl.po +++ b/locale/pl.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-08-18 11:19-0400\n" +"POT-Creation-Date: 2020-08-30 14:38-0400\n" "PO-Revision-Date: 2019-03-19 18:37-0700\n" "Last-Translator: Radomir Dopieralski \n" "Language-Team: pl\n" @@ -302,7 +302,7 @@ msgstr "Wszystkie kanały zdarzeń w użyciu" msgid "All sync event channels in use" msgstr "Wszystkie kanały zdarzeń synchronizacji w użyciu" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "All timers for this pin are in use" msgstr "Wszystkie timery tej nóżki w użyciu" @@ -314,7 +314,7 @@ msgstr "Wszystkie timery tej nóżki w użyciu" #: ports/cxd56/common-hal/pulseio/PulseOut.c #: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c -#: ports/stm/peripherals/timers.c shared-bindings/pulseio/PWMOut.c +#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c msgid "All timers in use" msgstr "Wszystkie timery w użyciu" @@ -492,6 +492,10 @@ msgstr "" msgid "Can't set CCCD on local Characteristic" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Cannot create a new Adapter; use _bleio.adapter;" +msgstr "" + #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c @@ -554,7 +558,7 @@ msgstr "Nie można przesyłać bez nóżek MOSI i MISO." msgid "Cannot unambiguously get sizeof scalar" msgstr "Wielkość skalara jest niejednoznaczna" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Cannot vary frequency on a timer that is already in use" msgstr "" @@ -623,23 +627,23 @@ msgstr "" msgid "Could not initialize UART" msgstr "Ustawienie UART nie powiodło się" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize channel" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize timer" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init channel" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init timer" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not restart PWM" msgstr "" @@ -647,7 +651,7 @@ msgstr "" msgid "Could not set address" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not start PWM" msgstr "" @@ -744,8 +748,8 @@ msgstr "Kanał EXTINT w użyciu" msgid "Error in regex" msgstr "Błąd w regex" -#: shared-bindings/aesio/aes.c shared-bindings/busio/SPI.c -#: shared-bindings/microcontroller/Pin.c +#: shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c +#: shared-bindings/busio/SPI.c shared-bindings/microcontroller/Pin.c #: shared-bindings/neopixel_write/__init__.c #: shared-bindings/terminalio/Terminal.c msgid "Expected a %q" @@ -756,10 +760,18 @@ msgstr "Oczekiwano %q" msgid "Expected a Characteristic" msgstr "Oczekiwano charakterystyki" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a DigitalInOut" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a UART" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c #: shared-bindings/_bleio/Service.c msgid "Expected a UUID" @@ -838,7 +850,7 @@ msgstr "" msgid "Frequency captured is above capability. Capture Paused." msgstr "Uzyskana częstotliwość jest niemożliwa. Spauzowano." -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Frequency must match existing PWMOut using this timer" msgstr "" @@ -942,9 +954,9 @@ msgstr "Zły BMP" msgid "Invalid DAC pin supplied" msgstr "" -#: ports/atmel-samd/common-hal/pulseio/PWMOut.c -#: ports/cxd56/common-hal/pulseio/PWMOut.c -#: ports/nrf/common-hal/pulseio/PWMOut.c shared-bindings/pulseio/PWMOut.c +#: ports/atmel-samd/common-hal/pwmio/PWMOut.c +#: ports/cxd56/common-hal/pwmio/PWMOut.c ports/nrf/common-hal/pwmio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "Invalid PWM frequency" msgstr "Zła częstotliwość PWM" @@ -984,7 +996,7 @@ msgstr "Zły plik" msgid "Invalid format chunk size" msgstr "Zła wielkość fragmentu formatu" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid frequency supplied" msgstr "" @@ -1002,8 +1014,8 @@ msgid "Invalid phase" msgstr "Zła faza" #: ports/atmel-samd/common-hal/audioio/AudioOut.c -#: ports/atmel-samd/common-hal/touchio/TouchIn.c -#: shared-bindings/pulseio/PWMOut.c shared-module/rgbmatrix/RGBMatrix.c +#: ports/atmel-samd/common-hal/touchio/TouchIn.c shared-bindings/pwmio/PWMOut.c +#: shared-module/rgbmatrix/RGBMatrix.c msgid "Invalid pin" msgstr "Zła nóżka" @@ -1027,7 +1039,7 @@ msgstr "Zła nóżka dla prawego kanału" msgid "Invalid pins" msgstr "Złe nóżki" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid pins for PWMOut" msgstr "" @@ -1209,7 +1221,7 @@ msgstr "" msgid "No long integer support" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "No more timers available on this pin." msgstr "" @@ -1247,6 +1259,10 @@ msgstr "Nic nie jest odtwarzane" msgid "Not running saved code.\n" msgstr "" +#: shared-bindings/_bleio/__init__.c +msgid "Not settable" +msgstr "" + #: shared-bindings/util.c msgid "" "Object has been deinitialized and can no longer be used. Create a new object." @@ -1277,12 +1293,12 @@ msgstr "" msgid "Oversample must be multiple of 8." msgstr "Nadpróbkowanie musi być wielokrotnością 8." -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM duty_cycle must be between 0 and 65535 inclusive (16 bit resolution)" msgstr "duty_cycle musi być pomiędzy 0 a 65535 włącznie (rozdzielczość 16 bit)" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM frequency not writable when variable_frequency is False on construction." msgstr "Nie można zmienić częstotliwości PWM gdy variable_frequency=False." @@ -1337,8 +1353,8 @@ msgstr "" #: ports/nrf/common-hal/pulseio/PulseOut.c #: ports/stm/common-hal/pulseio/PulseOut.c msgid "" -"Port does not accept pins or frequency. " -"Construct and pass a PWMOut Carrier instead" +"Port does not accept pins or frequency. Construct and pass a PWMOut Carrier " +"instead" msgstr "" #: shared-bindings/_bleio/Adapter.c @@ -1353,10 +1369,6 @@ msgstr "Dowolny klawisz aby uruchomić konsolę. CTRL-D aby przeładować." msgid "Pull not used when direction is output." msgstr "Podciągnięcie nieużywane w trybie wyjścia." -#: ports/stm/ref/pulseout-pre-timeralloc.c -msgid "PulseOut not supported on this chip" -msgstr "" - #: ports/stm/common-hal/os/__init__.c msgid "RNG DeInit Error" msgstr "" @@ -1568,7 +1580,7 @@ msgstr "Szerokość bitmapy musi być wielokrotnością szerokości kafelka" msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "" "Timer was reserved for internal use - declare PWM pins earlier in the program" msgstr "" @@ -2461,6 +2473,10 @@ msgstr "" msgid "initial values must be iterable" msgstr "" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "initial_value length is wrong" +msgstr "" + #: py/compile.c msgid "inline assembler must be a function" msgstr "wtrącony asembler musi być funkcją" @@ -2653,6 +2669,10 @@ msgstr "" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "max_length must be > 0" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "przekroczono dozwoloną głębokość rekurencji" @@ -2887,6 +2907,14 @@ msgstr "ord oczekuje znaku" msgid "ord() expected a character, but string of length %d found" msgstr "ord() oczekuje znaku, a jest łańcuch od długości %d" +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of source" +msgstr "" + +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of target" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "przepełnienie przy konwersji long in to słowa maszynowego" @@ -3066,6 +3094,10 @@ msgstr "" msgid "sosfilt requires iterable arguments" msgstr "" +#: shared-bindings/displayio/Bitmap.c +msgid "source palette too large" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "początkowe/końcowe indeksy" diff --git a/locale/pt_BR.po b/locale/pt_BR.po index 9fb4142c47..b40d33f80b 100644 --- a/locale/pt_BR.po +++ b/locale/pt_BR.po @@ -5,8 +5,8 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-08-18 11:19-0400\n" -"PO-Revision-Date: 2020-08-21 18:19+0000\n" +"POT-Creation-Date: 2020-08-30 14:38-0400\n" +"PO-Revision-Date: 2020-09-02 22:32+0000\n" "Last-Translator: Wellington Terumi Uemura \n" "Language-Team: \n" "Language: pt_BR\n" @@ -14,7 +14,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 4.2.1-dev\n" +"X-Generator: Weblate 4.3-dev\n" #: main.c msgid "" @@ -312,7 +312,7 @@ msgstr "Todos os canais de eventos em uso" msgid "All sync event channels in use" msgstr "Todos os canais dos eventos de sincronização em uso" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "All timers for this pin are in use" msgstr "Todos os temporizadores para este pino estão em uso" @@ -324,7 +324,7 @@ msgstr "Todos os temporizadores para este pino estão em uso" #: ports/cxd56/common-hal/pulseio/PulseOut.c #: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c -#: ports/stm/peripherals/timers.c shared-bindings/pulseio/PWMOut.c +#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c msgid "All timers in use" msgstr "Todos os temporizadores em uso" @@ -506,6 +506,10 @@ msgstr "Chame super().__init__() antes de acessar o objeto nativo." msgid "Can't set CCCD on local Characteristic" msgstr "Não é possível definir o CCCD com a característica local" +#: shared-bindings/_bleio/Adapter.c +msgid "Cannot create a new Adapter; use _bleio.adapter;" +msgstr "Não é possível criar um novo Adaptador; utilize _bleio.adapter;" + #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c @@ -571,7 +575,7 @@ msgstr "Não é possível transferir sem os pinos MOSI e MISO." msgid "Cannot unambiguously get sizeof scalar" msgstr "Não é possível obter inequivocamente o tamanho do escalar" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Cannot vary frequency on a timer that is already in use" msgstr "Não é possível variar a frequência em um timer que já esteja em uso" @@ -644,23 +648,23 @@ msgstr "Não foi possível inicializar o SDCard" msgid "Could not initialize UART" msgstr "Não foi possível inicializar o UART" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize channel" msgstr "Não foi possível inicializar o canal" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize timer" msgstr "Não foi possível inicializar o temporizador" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init channel" msgstr "Não foi possível reiniciar o canal" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init timer" msgstr "Não foi possível reiniciar o temporizador" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not restart PWM" msgstr "Não foi possível reiniciar o PWM" @@ -668,7 +672,7 @@ msgstr "Não foi possível reiniciar o PWM" msgid "Could not set address" msgstr "Não foi possível definir o endereço" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not start PWM" msgstr "Não foi possível iniciar o PWM" @@ -765,8 +769,8 @@ msgstr "Canal EXTINT em uso" msgid "Error in regex" msgstr "Erro no regex" -#: shared-bindings/aesio/aes.c shared-bindings/busio/SPI.c -#: shared-bindings/microcontroller/Pin.c +#: shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c +#: shared-bindings/busio/SPI.c shared-bindings/microcontroller/Pin.c #: shared-bindings/neopixel_write/__init__.c #: shared-bindings/terminalio/Terminal.c msgid "Expected a %q" @@ -777,10 +781,18 @@ msgstr "Esperado um" msgid "Expected a Characteristic" msgstr "Uma característica é necessária" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a DigitalInOut" +msgstr "Espera-se um DigitalInOut" + #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "Esperava um Serviço" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a UART" +msgstr "Espera-se uma UART" + #: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c #: shared-bindings/_bleio/Service.c msgid "Expected a UUID" @@ -860,7 +872,7 @@ msgid "Frequency captured is above capability. Capture Paused." msgstr "" "A frequência capturada está acima da capacidade. A captura está em pausa." -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Frequency must match existing PWMOut using this timer" msgstr "" "A frequência deve coincidir com o PWMOut existente usando este temporizador" @@ -965,9 +977,9 @@ msgstr "Arquivo BMP inválido" msgid "Invalid DAC pin supplied" msgstr "O pino DAC informado é inválido" -#: ports/atmel-samd/common-hal/pulseio/PWMOut.c -#: ports/cxd56/common-hal/pulseio/PWMOut.c -#: ports/nrf/common-hal/pulseio/PWMOut.c shared-bindings/pulseio/PWMOut.c +#: ports/atmel-samd/common-hal/pwmio/PWMOut.c +#: ports/cxd56/common-hal/pwmio/PWMOut.c ports/nrf/common-hal/pwmio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "Invalid PWM frequency" msgstr "Frequência PWM inválida" @@ -1007,7 +1019,7 @@ msgstr "Arquivo inválido" msgid "Invalid format chunk size" msgstr "Tamanho do pedaço de formato inválido" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid frequency supplied" msgstr "A frequência informada é inválida" @@ -1025,8 +1037,8 @@ msgid "Invalid phase" msgstr "Fase Inválida" #: ports/atmel-samd/common-hal/audioio/AudioOut.c -#: ports/atmel-samd/common-hal/touchio/TouchIn.c -#: shared-bindings/pulseio/PWMOut.c shared-module/rgbmatrix/RGBMatrix.c +#: ports/atmel-samd/common-hal/touchio/TouchIn.c shared-bindings/pwmio/PWMOut.c +#: shared-module/rgbmatrix/RGBMatrix.c msgid "Invalid pin" msgstr "Pino inválido" @@ -1050,7 +1062,7 @@ msgstr "Pino inválido para canal direito" msgid "Invalid pins" msgstr "Pinos inválidos" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid pins for PWMOut" msgstr "Os pinos para o PWMOut são inválidos" @@ -1232,7 +1244,7 @@ msgstr "Nenhuma chave foi definida" msgid "No long integer support" msgstr "Não há compatibilidade com inteiro longo" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "No more timers available on this pin." msgstr "Não há mais temporizadores disponíveis neste pino." @@ -1270,6 +1282,10 @@ msgstr "Não está jogando" msgid "Not running saved code.\n" msgstr "O código salvo não está em execução.\n" +#: shared-bindings/_bleio/__init__.c +msgid "Not settable" +msgstr "Não configurável" + #: shared-bindings/util.c msgid "" "Object has been deinitialized and can no longer be used. Create a new object." @@ -1305,14 +1321,14 @@ msgstr "" msgid "Oversample must be multiple of 8." msgstr "A superamostragem deve ser um múltiplo de 8." -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM duty_cycle must be between 0 and 65535 inclusive (16 bit resolution)" msgstr "" "O duty_cycle do PWM deve estar entre 0 e inclusive 65535 (com resolução de " "16 bits)" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM frequency not writable when variable_frequency is False on construction." msgstr "" @@ -1372,11 +1388,11 @@ msgstr "O Polígono precisa de pelo menos 3 pontos" #: ports/nrf/common-hal/pulseio/PulseOut.c #: ports/stm/common-hal/pulseio/PulseOut.c msgid "" -"Port does not accept pins or frequency. " -"Construct and pass a PWMOut Carrier instead" +"Port does not accept pins or frequency. Construct and pass a PWMOut Carrier " +"instead" msgstr "" -"A porta não aceita pinos ou frequência. " -"Em vez disso, Construa e encaminhe um PWMOut Carrier" +"A porta não aceita pinos ou frequência. Em vez disso, construa e passe um " +"PWMOut Carrier" #: shared-bindings/_bleio/Adapter.c msgid "Prefix buffer must be on the heap" @@ -1393,10 +1409,6 @@ msgstr "" msgid "Pull not used when direction is output." msgstr "O Pull não foi usado quando a direção for gerada." -#: ports/stm/ref/pulseout-pre-timeralloc.c -msgid "PulseOut not supported on this chip" -msgstr "O PulseOut não é compatível neste CI" - #: ports/stm/common-hal/os/__init__.c msgid "RNG DeInit Error" msgstr "Erro DeInit RNG" @@ -1619,7 +1631,7 @@ msgstr "" "O tempo limite é long demais: O comprimento máximo do tempo limite é de %d " "segundos" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "" "Timer was reserved for internal use - declare PWM pins earlier in the program" msgstr "" @@ -2533,6 +2545,10 @@ msgstr "os índices devem ser números inteiros, fatias ou listas booleanas" msgid "initial values must be iterable" msgstr "os valores iniciais devem ser iteráveis" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "initial_value length is wrong" +msgstr "O comprimento do initial_value está errado" + #: py/compile.c msgid "inline assembler must be a function" msgstr "o assembler em linha deve ser uma função" @@ -2728,6 +2744,10 @@ msgstr "a matriz não é definitiva positiva" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "o max_length deve ser 0-%d quando Fixed_length for %s" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "max_length must be > 0" +msgstr "max_length deve ser > 0" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "a recursão máxima da profundidade foi excedida" @@ -2967,6 +2987,14 @@ msgstr "" "o ord() esperava um caractere, porém a sequência do comprimento %d foi " "encontrada" +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of source" +msgstr "fora do alcance da fonte" + +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of target" +msgstr "fora do alcance do alvo" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "" @@ -3148,6 +3176,10 @@ msgstr "sos[:, 3] deve ser um em todos" msgid "sosfilt requires iterable arguments" msgstr "o sosfilt requer que os argumentos sejam iteráveis" +#: shared-bindings/displayio/Bitmap.c +msgid "source palette too large" +msgstr "a paleta de origem é muito grande" + #: py/objstr.c msgid "start/end indices" msgstr "os índices de início/fim" @@ -3444,6 +3476,18 @@ msgstr "zi deve ser de um tipo float" msgid "zi must be of shape (n_section, 2)" msgstr "zi deve estar na forma (n_section, 2)" +#~ msgid "PulseOut not supported on this chip" +#~ msgstr "O PulseOut não é compatível neste CI" + +#~ msgid "" +#~ "Port does not accept pins or " +#~ "frequency. Construct and pass a " +#~ "PWMOut Carrier instead" +#~ msgstr "" +#~ "A porta não aceita pinos ou " +#~ "frequência. Em vez disso, Construa e " +#~ "encaminhe um PWMOut Carrier" + #~ msgid "tuple/list required on RHS" #~ msgstr "a tupla/lista necessária no RHS" diff --git a/locale/sv.po b/locale/sv.po index df205b1095..eb131ef543 100644 --- a/locale/sv.po +++ b/locale/sv.po @@ -5,8 +5,8 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-08-18 11:19-0400\n" -"PO-Revision-Date: 2020-07-25 20:58+0000\n" +"POT-Creation-Date: 2020-08-30 14:38-0400\n" +"PO-Revision-Date: 2020-09-07 19:36+0000\n" "Last-Translator: Jonny Bergdahl \n" "Language-Team: LANGUAGE \n" "Language: sv\n" @@ -14,7 +14,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.2-dev\n" +"X-Generator: Weblate 4.3-dev\n" #: main.c msgid "" @@ -82,7 +82,7 @@ msgstr "Index %q ligger utanför intervallet" #: py/obj.c msgid "%q indices must be integers, not %q" -msgstr "" +msgstr "%q index måste vara heltal, inte %q" #: shared-bindings/vectorio/Polygon.c msgid "%q list must be a list" @@ -122,39 +122,39 @@ msgstr "'%q' argument krävs" #: py/runtime.c msgid "'%q' object cannot assign attribute '%q'" -msgstr "" +msgstr "Objektet '%q' kan inte tilldela attributet '%q'" #: py/proto.c msgid "'%q' object does not support '%q'" -msgstr "" +msgstr "Objektet '%q' stöder inte '%q'" #: py/obj.c msgid "'%q' object does not support item assignment" -msgstr "" +msgstr "Objektet '%q' stöder inte tilldelning" #: py/obj.c msgid "'%q' object does not support item deletion" -msgstr "" +msgstr "Objektet '%q' stöder inte borttagning av objekt" #: py/runtime.c msgid "'%q' object has no attribute '%q'" -msgstr "" +msgstr "Objektet '%q' har inget attribut '%q'" #: py/runtime.c msgid "'%q' object is not an iterator" -msgstr "" +msgstr "Objektet '%q' är inte en iterator" #: py/objtype.c py/runtime.c msgid "'%q' object is not callable" -msgstr "" +msgstr "Objektet '%q' kan inte anropas" #: py/runtime.c msgid "'%q' object is not iterable" -msgstr "" +msgstr "Objektet '%q' är inte itererbart" #: py/obj.c msgid "'%q' object is not subscriptable" -msgstr "" +msgstr "Objektet '%q' är inte indexbar" #: py/emitinlinethumb.c py/emitinlinextensa.c #, c-format @@ -224,7 +224,7 @@ msgstr "'await' utanför funktion" #: py/compile.c msgid "'await', 'async for' or 'async with' outside async function" -msgstr "" +msgstr "'await', 'async for' eller 'async with' utanför asynk-funktion" #: py/compile.c msgid "'break' outside loop" @@ -308,7 +308,7 @@ msgstr "Alla händelsekanaler används" msgid "All sync event channels in use" msgstr "Alla händelsekanaler används" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "All timers for this pin are in use" msgstr "Alla timers för denna pinne är i bruk" @@ -320,7 +320,7 @@ msgstr "Alla timers för denna pinne är i bruk" #: ports/cxd56/common-hal/pulseio/PulseOut.c #: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c -#: ports/stm/peripherals/timers.c shared-bindings/pulseio/PWMOut.c +#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c msgid "All timers in use" msgstr "Alla timers används" @@ -457,7 +457,7 @@ msgstr "Buffertlängd måste vara en multipel av 512" #: ports/stm/common-hal/sdioio/SDCard.c msgid "Buffer must be a multiple of 512 bytes" -msgstr "" +msgstr "Bufferten måste vara en multipel av 512 byte" #: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c msgid "Buffer must be at least length 1" @@ -498,6 +498,10 @@ msgstr "Anropa super().__init__() innan du använder det ursprungliga objektet." msgid "Can't set CCCD on local Characteristic" msgstr "Kan inte ställa in CCCD på lokal karaktäristik" +#: shared-bindings/_bleio/Adapter.c +msgid "Cannot create a new Adapter; use _bleio.adapter;" +msgstr "Det går inte att skapa en ny Adapter; använd _bleio.adapter;" + #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c @@ -562,7 +566,7 @@ msgstr "Kan inte överföra utan MOSI- och MISO-pinnar." msgid "Cannot unambiguously get sizeof scalar" msgstr "Kan inte entydigt få sizeof scalar" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Cannot vary frequency on a timer that is already in use" msgstr "Det går inte att ändra frekvensen på en timer som redan används" @@ -635,31 +639,31 @@ msgstr "Kan inte initiera SD-kort" msgid "Could not initialize UART" msgstr "Det gick inte att initiera UART" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize channel" msgstr "Det gick inte att initiera kanalen" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize timer" msgstr "Det gick inte att initialisera timern" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init channel" msgstr "Det gick inte att återinitiera kanalen" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init timer" msgstr "Det gick inte att återinitiera timern" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not restart PWM" msgstr "Det gick inte att starta om PWM" #: shared-bindings/_bleio/Adapter.c msgid "Could not set address" -msgstr "" +msgstr "Kan inte ange adress" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not start PWM" msgstr "Det gick inte att starta PWM" @@ -756,8 +760,8 @@ msgstr "EXTINT-kanalen används redan" msgid "Error in regex" msgstr "Fel i regex" -#: shared-bindings/aesio/aes.c shared-bindings/busio/SPI.c -#: shared-bindings/microcontroller/Pin.c +#: shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c +#: shared-bindings/busio/SPI.c shared-bindings/microcontroller/Pin.c #: shared-bindings/neopixel_write/__init__.c #: shared-bindings/terminalio/Terminal.c msgid "Expected a %q" @@ -768,10 +772,18 @@ msgstr "Förväntade %q" msgid "Expected a Characteristic" msgstr "Förväntade en karaktäristik" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a DigitalInOut" +msgstr "Förväntar en DigitalInOut" + #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "Förväntade en tjänst" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a UART" +msgstr "Förväntar en UART" + #: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c #: shared-bindings/_bleio/Service.c msgid "Expected a UUID" @@ -844,13 +856,13 @@ msgstr "Filen finns redan" #: shared-module/framebufferio/FramebufferDisplay.c #, c-format msgid "Framebuffer requires %d bytes" -msgstr "" +msgstr "Framebuffer kräver %d byte" #: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c msgid "Frequency captured is above capability. Capture Paused." msgstr "Infångningsfrekvens är för hög. Infångning pausad." -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Frequency must match existing PWMOut using this timer" msgstr "Frekvensen måste matcha befintlig PWMOut med denna timer" @@ -888,7 +900,7 @@ msgstr "I2C init-fel" #: shared-bindings/audiobusio/I2SOut.c msgid "I2SOut not available" -msgstr "" +msgstr "I2SOut är inte tillgängligt" #: shared-bindings/aesio/aes.c #, c-format @@ -940,7 +952,7 @@ msgstr "Ogiltig %q-pinne" #: ports/stm/common-hal/busio/I2C.c ports/stm/common-hal/busio/SPI.c #: ports/stm/common-hal/busio/UART.c ports/stm/common-hal/sdioio/SDCard.c msgid "Invalid %q pin selection" -msgstr "" +msgstr "Ogiltigt val av %q pinne" #: ports/stm/common-hal/analogio/AnalogIn.c msgid "Invalid ADC Unit value" @@ -954,9 +966,9 @@ msgstr "Ogiltig BMP-fil" msgid "Invalid DAC pin supplied" msgstr "Ogiltig DAC-pinne angiven" -#: ports/atmel-samd/common-hal/pulseio/PWMOut.c -#: ports/cxd56/common-hal/pulseio/PWMOut.c -#: ports/nrf/common-hal/pulseio/PWMOut.c shared-bindings/pulseio/PWMOut.c +#: ports/atmel-samd/common-hal/pwmio/PWMOut.c +#: ports/cxd56/common-hal/pwmio/PWMOut.c ports/nrf/common-hal/pwmio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "Invalid PWM frequency" msgstr "Ogiltig PWM-frekvens" @@ -996,7 +1008,7 @@ msgstr "Felaktig fil" msgid "Invalid format chunk size" msgstr "Ogiltig formatsegmentstorlek" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid frequency supplied" msgstr "Ogiltig frekvens angiven" @@ -1014,8 +1026,8 @@ msgid "Invalid phase" msgstr "Ogiltig fas" #: ports/atmel-samd/common-hal/audioio/AudioOut.c -#: ports/atmel-samd/common-hal/touchio/TouchIn.c -#: shared-bindings/pulseio/PWMOut.c shared-module/rgbmatrix/RGBMatrix.c +#: ports/atmel-samd/common-hal/touchio/TouchIn.c shared-bindings/pwmio/PWMOut.c +#: shared-module/rgbmatrix/RGBMatrix.c msgid "Invalid pin" msgstr "Ogiltig pinne" @@ -1039,7 +1051,7 @@ msgstr "Ogiltig pinne för höger kanal" msgid "Invalid pins" msgstr "Ogiltiga pinnar" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid pins for PWMOut" msgstr "Ogiltiga pinnar för PWMOut" @@ -1222,7 +1234,7 @@ msgstr "Ingen nyckel angavs" msgid "No long integer support" msgstr "Inget stöd för långt heltal" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "No more timers available on this pin." msgstr "Inga fler timers tillgängliga på denna pinne." @@ -1258,7 +1270,11 @@ msgstr "Ingen uppspelning" #: main.c msgid "Not running saved code.\n" -msgstr "" +msgstr "Kör inte sparad kod.\n" + +#: shared-bindings/_bleio/__init__.c +msgid "Not settable" +msgstr "Går inte sätta" #: shared-bindings/util.c msgid "" @@ -1295,12 +1311,12 @@ msgstr "" msgid "Oversample must be multiple of 8." msgstr "Översampling måste vara multipel av 8." -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM duty_cycle must be between 0 and 65535 inclusive (16 bit resolution)" msgstr "PWM duty_cykel måste vara mellan 0 och 65535 (16 bitars upplösning)" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM frequency not writable when variable_frequency is False on construction." msgstr "" @@ -1360,9 +1376,11 @@ msgstr "Polygonen behöver minst 3 punkter" #: ports/nrf/common-hal/pulseio/PulseOut.c #: ports/stm/common-hal/pulseio/PulseOut.c msgid "" -"Port does not accept pins or frequency. " -"Construct and pass a PWMOut Carrier instead" +"Port does not accept pins or frequency. Construct and pass a PWMOut Carrier " +"instead" msgstr "" +"Porten accepterar inte pinne eller frekvens. Skapa och skicka en PWMOut " +"Carrier istället" #: shared-bindings/_bleio/Adapter.c msgid "Prefix buffer must be on the heap" @@ -1377,10 +1395,6 @@ msgstr "" msgid "Pull not used when direction is output." msgstr "Pull används inte när riktningen är output." -#: ports/stm/ref/pulseout-pre-timeralloc.c -msgid "PulseOut not supported on this chip" -msgstr "PulseIn stöds inte av detta chip" - #: ports/stm/common-hal/os/__init__.c msgid "RNG DeInit Error" msgstr "RNG DeInit-fel" @@ -1442,7 +1456,7 @@ msgstr "Radvärdet måste vara digitalio.DigitalInOut" #: main.c msgid "Running in safe mode! " -msgstr "" +msgstr "Kör i säkert läge! " #: shared-module/sdcardio/SDCard.c msgid "SD card CSD format not supported" @@ -1456,12 +1470,12 @@ msgstr "SDA eller SCL behöver en pullup" #: ports/stm/common-hal/sdioio/SDCard.c #, c-format msgid "SDIO GetCardInfo Error %d" -msgstr "" +msgstr "SDIO GetCardInfo-fel %d" #: ports/stm/common-hal/sdioio/SDCard.c #, c-format msgid "SDIO Init Error %d" -msgstr "" +msgstr "SDIO Init-fel %d" #: ports/stm/common-hal/busio/SPI.c msgid "SPI Init Error" @@ -1600,7 +1614,7 @@ msgstr "Tile-bredd måste vara jämnt delbar med bredd på bitmap" msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "Åtgärden tog för lång tid: Max väntetid är %d sekunder" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "" "Timer was reserved for internal use - declare PWM pins earlier in the program" msgstr "" @@ -1831,7 +1845,7 @@ msgstr "__init __ () ska returnera None" #: py/objtype.c msgid "__init__() should return None, not '%q'" -msgstr "" +msgstr "__init__() ska returnera None, inte '%q'" #: py/objobject.c msgid "__new__ arg must be a user-type" @@ -1876,7 +1890,7 @@ msgstr "argumentet har fel typ" #: extmod/ulab/code/linalg/linalg.c msgid "argument must be ndarray" -msgstr "" +msgstr "argument måste vara ndarray" #: py/argcheck.c shared-bindings/_stage/__init__.c #: shared-bindings/digitalio/DigitalInOut.c shared-bindings/gamepad/GamePad.c @@ -2019,7 +2033,7 @@ msgstr "kan inte tilldela uttryck" #: py/obj.c py/objint.c shared-bindings/i2cperipheral/I2CPeripheral.c #: shared-module/_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" -msgstr "" +msgstr "kan inte konvertera %q till %q" #: py/objstr.c msgid "can't convert '%q' object to %q implicitly" @@ -2027,7 +2041,7 @@ msgstr "kan inte konvertera '%q' objekt implicit till %q" #: py/obj.c msgid "can't convert to %q" -msgstr "" +msgstr "kan inte konvertera till %q" #: py/objstr.c msgid "can't convert to str implicitly" @@ -2504,6 +2518,10 @@ msgstr "index måste vara heltal, slices, eller Boolean-listor" msgid "initial values must be iterable" msgstr "initialvärden måste vara iterable" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "initial_value length is wrong" +msgstr "initial_value-längd är fel" + #: py/compile.c msgid "inline assembler must be a function" msgstr "inline assembler måste vara en funktion" @@ -2699,6 +2717,10 @@ msgstr "matrisen är inte positiv bestämd" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "max_length måste vara 0-%d när fixed_length är %s" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "max_length must be > 0" +msgstr "max_length måste vara > 0" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "maximal rekursionsdjup överskriden" @@ -2848,7 +2870,7 @@ msgstr "antal punkter måste vara minst 2" #: py/obj.c msgid "object '%q' is not a tuple or list" -msgstr "" +msgstr "objektet '%q' är inte en tuple eller list" #: py/obj.c msgid "object does not support item assignment" @@ -2884,7 +2906,7 @@ msgstr "objektet är inte iterable" #: py/obj.c msgid "object of type '%q' has no len()" -msgstr "" +msgstr "objekt av typen '%q' har inte len()" #: py/obj.c msgid "object with buffer protocol required" @@ -2933,6 +2955,14 @@ msgstr "ord förväntar sig ett tecken" msgid "ord() expected a character, but string of length %d found" msgstr "ord() förväntade sig ett tecken, men en sträng med längden %d hittades" +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of source" +msgstr "utanför räckvidd för source" + +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of target" +msgstr "utanför räckvidd för target" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "Konvertering av long int till machine word överskred maxvärde" @@ -2980,7 +3010,7 @@ msgstr "polygon kan endast registreras i en förälder" #: ports/stm/common-hal/pulseio/PulseIn.c py/objdict.c py/objlist.c py/objset.c #: shared-bindings/ps2io/Ps2.c msgid "pop from empty %q" -msgstr "" +msgstr "pop från tom %q" #: py/objint_mpz.c msgid "pow() 3rd argument cannot be 0" @@ -3113,6 +3143,10 @@ msgstr "sos[:, 3] måste vara ettor" msgid "sosfilt requires iterable arguments" msgstr "sosfilt kräver iterable argument" +#: shared-bindings/displayio/Bitmap.c +msgid "source palette too large" +msgstr "källpalett för stor" + #: py/objstr.c msgid "start/end indices" msgstr "start-/slutindex" @@ -3139,7 +3173,7 @@ msgstr "stream-åtgärd stöds inte" #: py/objstrunicode.c msgid "string indices must be integers, not %q" -msgstr "" +msgstr "strängindex måste vara heltal, inte %q" #: py/stream.c msgid "string not supported; use bytes or bytearray" @@ -3216,7 +3250,7 @@ msgstr "för många värden att packa upp (förväntat %d)" #: extmod/ulab/code/approx/approx.c msgid "trapz is defined for 1D arrays of equal length" -msgstr "" +msgstr "trapz är definierad för 1D-matriser med samma längd" #: extmod/ulab/code/linalg/linalg.c msgid "tuple index out of range" @@ -3282,7 +3316,7 @@ msgstr "okänd konverteringsspecificerare %c" #: py/objstr.c msgid "unknown format code '%c' for object of type '%q'" -msgstr "" +msgstr "okänd formatkod '%c' för objekt av typ '%q'" #: py/compile.c msgid "unknown type" @@ -3322,7 +3356,7 @@ msgstr "Formattecknet '%c' (0x%x) stöds inte vid index %d" #: py/runtime.c msgid "unsupported type for %q: '%q'" -msgstr "" +msgstr "typen %q stöder inte '%q'" #: py/runtime.c msgid "unsupported type for operator" @@ -3330,7 +3364,7 @@ msgstr "typ stöds inte för operatören" #: py/runtime.c msgid "unsupported types for %q: '%q', '%q'" -msgstr "" +msgstr "typen %q stöder inte '%q', '%q'" #: py/objint.c #, c-format @@ -3343,7 +3377,7 @@ msgstr "value_count måste vara > 0" #: extmod/ulab/code/linalg/linalg.c msgid "vectors must have same lengths" -msgstr "" +msgstr "vektorer måste ha samma längd" #: shared-bindings/watchdog/WatchDogTimer.c msgid "watchdog timeout must be greater than 0" @@ -3409,6 +3443,9 @@ msgstr "zi måste vara av typ float" msgid "zi must be of shape (n_section, 2)" msgstr "zi måste vara i formen (n_section, 2)" +#~ msgid "PulseOut not supported on this chip" +#~ msgstr "PulseIn stöds inte av detta chip" + #~ msgid "tuple/list required on RHS" #~ msgstr "tupel/lista krävs för RHS" diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po index 725491f5b2..56f9bae8c1 100644 --- a/locale/zh_Latn_pinyin.po +++ b/locale/zh_Latn_pinyin.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: circuitpython-cn\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-08-18 11:19-0400\n" +"POT-Creation-Date: 2020-08-30 14:38-0400\n" "PO-Revision-Date: 2019-04-13 10:10-0700\n" "Last-Translator: hexthat\n" "Language-Team: Chinese Hanyu Pinyin\n" @@ -309,7 +309,7 @@ msgstr "Suǒyǒu shǐyòng de shìjiàn píndào" msgid "All sync event channels in use" msgstr "Suǒyǒu tóngbù shìjiàn píndào shǐyòng" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "All timers for this pin are in use" msgstr "Cǐ yǐn jiǎo de suǒyǒu jìshí qì zhèngzài shǐyòng" @@ -321,7 +321,7 @@ msgstr "Cǐ yǐn jiǎo de suǒyǒu jìshí qì zhèngzài shǐyòng" #: ports/cxd56/common-hal/pulseio/PulseOut.c #: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c #: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c -#: ports/stm/peripherals/timers.c shared-bindings/pulseio/PWMOut.c +#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c msgid "All timers in use" msgstr "Suǒyǒu jìshí qì shǐyòng" @@ -499,6 +499,10 @@ msgstr "Zài fǎngwèn běn jī wùjiàn zhīqián diàoyòng super().__init__() msgid "Can't set CCCD on local Characteristic" msgstr "Wúfǎ jiāng CCCD shèzhì wéi běndì tèzhēng" +#: shared-bindings/_bleio/Adapter.c +msgid "Cannot create a new Adapter; use _bleio.adapter;" +msgstr "" + #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c @@ -561,7 +565,7 @@ msgstr "Méiyǒu MOSI/MISO jiù wúfǎ zhuǎnyí." msgid "Cannot unambiguously get sizeof scalar" msgstr "Wúfǎ míngquè de huòdé biāoliàng de dàxiǎo" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Cannot vary frequency on a timer that is already in use" msgstr "Wúfǎ gēnggǎi yǐ zài shǐyòng de jìshí qì shàng de pínlǜ" @@ -632,23 +636,23 @@ msgstr "wú fǎ chū shǐ huà SDCard" msgid "Could not initialize UART" msgstr "Wúfǎ chūshǐhuà UART" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize channel" msgstr "Wúfǎ chūshǐhuà píndào" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not initialize timer" msgstr "Wúfǎ chūshǐhuà jìshí qì" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init channel" msgstr "Wúfǎ chóngxīn chūshǐhuà píndào" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not re-init timer" msgstr "Wúfǎ chóngxīn qǐdòng jìshí qì" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not restart PWM" msgstr "Wúfǎ chóngqǐ PWM" @@ -656,7 +660,7 @@ msgstr "Wúfǎ chóngqǐ PWM" msgid "Could not set address" msgstr "wú fǎ shè zhì dì zhǐ" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Could not start PWM" msgstr "Wúfǎ qǐdòng PWM" @@ -753,8 +757,8 @@ msgstr "EXTINT píndào yǐjīng shǐyòng" msgid "Error in regex" msgstr "Zhèngzé biǎodá shì cuòwù" -#: shared-bindings/aesio/aes.c shared-bindings/busio/SPI.c -#: shared-bindings/microcontroller/Pin.c +#: shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c +#: shared-bindings/busio/SPI.c shared-bindings/microcontroller/Pin.c #: shared-bindings/neopixel_write/__init__.c #: shared-bindings/terminalio/Terminal.c msgid "Expected a %q" @@ -765,10 +769,18 @@ msgstr "Yùqí %q" msgid "Expected a Characteristic" msgstr "Yùqí de tèdiǎn" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a DigitalInOut" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c msgid "Expected a Service" msgstr "Yùqí fúwù" +#: shared-bindings/_bleio/Adapter.c +msgid "Expected a UART" +msgstr "" + #: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c #: shared-bindings/_bleio/Service.c msgid "Expected a UUID" @@ -847,7 +859,7 @@ msgstr "zhēn huǎn chōng qū xū yào %d zì jié" msgid "Frequency captured is above capability. Capture Paused." msgstr "Pínlǜ bǔhuò gāo yú nénglì. Bǔhuò zàntíng." -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Frequency must match existing PWMOut using this timer" msgstr "Pínlǜ bìxū yǔ shǐyòng cǐ jìshí qì de xiàn yǒu PWMOut xiāng pǐpèi" @@ -951,9 +963,9 @@ msgstr "Wúxiào de BMP wénjiàn" msgid "Invalid DAC pin supplied" msgstr "Tí gōng liǎo wúxiào de DAC yǐn jiǎo" -#: ports/atmel-samd/common-hal/pulseio/PWMOut.c -#: ports/cxd56/common-hal/pulseio/PWMOut.c -#: ports/nrf/common-hal/pulseio/PWMOut.c shared-bindings/pulseio/PWMOut.c +#: ports/atmel-samd/common-hal/pwmio/PWMOut.c +#: ports/cxd56/common-hal/pwmio/PWMOut.c ports/nrf/common-hal/pwmio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "Invalid PWM frequency" msgstr "Wúxiào de PWM pínlǜ" @@ -993,7 +1005,7 @@ msgstr "Wúxiào de wénjiàn" msgid "Invalid format chunk size" msgstr "Géshì kuài dàxiǎo wúxiào" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid frequency supplied" msgstr "Tígōng de pínlǜ wúxiào" @@ -1011,8 +1023,8 @@ msgid "Invalid phase" msgstr "Jiēduàn wúxiào" #: ports/atmel-samd/common-hal/audioio/AudioOut.c -#: ports/atmel-samd/common-hal/touchio/TouchIn.c -#: shared-bindings/pulseio/PWMOut.c shared-module/rgbmatrix/RGBMatrix.c +#: ports/atmel-samd/common-hal/touchio/TouchIn.c shared-bindings/pwmio/PWMOut.c +#: shared-module/rgbmatrix/RGBMatrix.c msgid "Invalid pin" msgstr "Wúxiào de yǐn jiǎo" @@ -1036,7 +1048,7 @@ msgstr "Yòuxián tōngdào yǐn jiǎo wúxiào" msgid "Invalid pins" msgstr "Wúxiào de yǐn jiǎo" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "Invalid pins for PWMOut" msgstr "PWMOut de yǐn jiǎo wú xiào" @@ -1218,7 +1230,7 @@ msgstr "Wèi zhǐdìng mì yào" msgid "No long integer support" msgstr "Méiyǒu zhǎng zhěngshù zhīchí" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "No more timers available on this pin." msgstr "Gāi yǐn jiǎo shàng méiyǒu kěyòng de dìngshí qì." @@ -1256,6 +1268,10 @@ msgstr "Wèi bòfàng" msgid "Not running saved code.\n" msgstr "Méiyǒu yùnxíng yǐ bǎocún de dàimǎ.\n" +#: shared-bindings/_bleio/__init__.c +msgid "Not settable" +msgstr "" + #: shared-bindings/util.c msgid "" "Object has been deinitialized and can no longer be used. Create a new object." @@ -1291,13 +1307,13 @@ msgstr "" msgid "Oversample must be multiple of 8." msgstr "Guò cǎiyàng bìxū shì 8 de bèishù." -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM duty_cycle must be between 0 and 65535 inclusive (16 bit resolution)" msgstr "" "PWM yìwù zhōuqí bìxū jiè yú 0 zhì 65535 de bāoróng xìng (16 wèi fēnbiàn lǜ)" -#: shared-bindings/pulseio/PWMOut.c +#: shared-bindings/pwmio/PWMOut.c msgid "" "PWM frequency not writable when variable_frequency is False on construction." msgstr "Dāng biànliàng_pínlǜ shì False zài jiànzhú shí PWM pínlǜ bùkě xiě." @@ -1355,8 +1371,8 @@ msgstr "Duōbiānxíng zhìshǎo xūyào 3 diǎn" #: ports/nrf/common-hal/pulseio/PulseOut.c #: ports/stm/common-hal/pulseio/PulseOut.c msgid "" -"Port does not accept pins or frequency. " -"Construct and pass a PWMOut Carrier instead" +"Port does not accept pins or frequency. Construct and pass a PWMOut Carrier " +"instead" msgstr "" #: shared-bindings/_bleio/Adapter.c @@ -1371,10 +1387,6 @@ msgstr "Àn xià rènhé jiàn jìnrù REPL. Shǐyòng CTRL-D chóngxīn jiāzà msgid "Pull not used when direction is output." msgstr "Fāngxiàng shūchū shí Pull méiyǒu shǐyòng." -#: ports/stm/ref/pulseout-pre-timeralloc.c -msgid "PulseOut not supported on this chip" -msgstr "" - #: ports/stm/common-hal/os/__init__.c msgid "RNG DeInit Error" msgstr "RNG qǔxiāo chūshǐhuà cuòwù" @@ -1593,7 +1605,7 @@ msgstr "Píng pū kuāndù bìxū huàfēn wèi tú kuāndù" msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "Chāoshí shíjiān tài zhǎng: Zuìdà chāoshí shíjiān wèi%d miǎo" -#: ports/stm/common-hal/pulseio/PWMOut.c +#: ports/stm/common-hal/pwmio/PWMOut.c msgid "" "Timer was reserved for internal use - declare PWM pins earlier in the program" msgstr "" @@ -2496,6 +2508,10 @@ msgstr "suǒyǐn bìxū shì zhěngshù, qiēpiàn huò bù'ěr zhí lièbiǎo" msgid "initial values must be iterable" msgstr "chūshǐ zhí bìxū shì kě diédài de" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "initial_value length is wrong" +msgstr "" + #: py/compile.c msgid "inline assembler must be a function" msgstr "nèi lián jíhé bìxū shì yīgè hánshù" @@ -2689,6 +2705,10 @@ msgstr "jǔzhèn bùshì zhèngdìng de" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "Dāng gùdìng chángdù wèi %s shí, zuìdà chángdù bìxū wèi 0-%d" +#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c +msgid "max_length must be > 0" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "chāochū zuìdà dìguī shēndù" @@ -2924,6 +2944,14 @@ msgstr "ord yùqí zìfú" msgid "ord() expected a character, but string of length %d found" msgstr "ord() yùqí zìfú, dàn chángdù zìfú chuàn %d" +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of source" +msgstr "" + +#: shared-bindings/displayio/Bitmap.c +msgid "out of range of target" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "chāo gāo zhuǎnhuàn zhǎng zhěng shùzì shí" @@ -3103,6 +3131,10 @@ msgstr "sos [:, 3] yīnggāi quán shì" msgid "sosfilt requires iterable arguments" msgstr "sosfilt xūyào diédài cānshù" +#: shared-bindings/displayio/Bitmap.c +msgid "source palette too large" +msgstr "" + #: py/objstr.c msgid "start/end indices" msgstr "kāishǐ/jiéshù zhǐshù" diff --git a/main.c b/main.c index fb73b09b1f..5b719dc4b6 100755 --- a/main.c +++ b/main.c @@ -105,6 +105,12 @@ void do_str(const char *src, mp_parse_input_kind_t input_kind) { static size_t PLACE_IN_DTCM_BSS(_pystack[CIRCUITPY_PYSTACK_SIZE / sizeof(size_t)]); #endif +static void reset_devices(void) { +#if CIRCUITPY_BLEIO_HCI + bleio_reset(); +#endif +} + void start_mp(supervisor_allocation* heap) { reset_status_led(); autoreload_stop(); @@ -206,6 +212,8 @@ bool maybe_run_list(const char * const * filenames, pyexec_result_t* exec_result } void cleanup_after_vm(supervisor_allocation* heap) { + // Reset port-independent devices, like CIRCUITPY_BLEIO_HCI. + reset_devices(); // Turn off the display and flush the fileystem before the heap disappears. #if CIRCUITPY_DISPLAYIO reset_displays(); @@ -436,11 +444,12 @@ int run_repl(void) { } int __attribute__((used)) main(void) { - memory_init(); - // initialise the cpu and peripherals safe_mode_t safe_mode = port_init(); + // Init memory after the port in case the port needs to set aside memory. + memory_init(); + // Turn on LEDs init_status_leds(); rgb_led_status_init(); @@ -465,6 +474,8 @@ int __attribute__((used)) main(void) { // Reset everything and prep MicroPython to run boot.py. reset_port(); + // Port-independent devices, like CIRCUITPY_BLEIO_HCI. + reset_devices(); reset_board(); // Turn on autoreload by default but before boot.py in case it wants to change it. diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index 30487ae3ef..489f3a7afb 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -107,12 +107,12 @@ CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAME5X -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_ endif # option to override default optimization level, set in boards/$(BOARD)/mpconfigboard.mk -CFLAGS += $(OPTIMIZATION_FLAGS) -DNDEBUG +CFLAGS += $(OPTIMIZATION_FLAGS) $(echo PERIPHERALS_CHIP_FAMILY=$(PERIPHERALS_CHIP_FAMILY)) #Debugging/Optimization ifeq ($(DEBUG), 1) - CFLAGS += -ggdb + CFLAGS += -ggdb3 -Og # You may want to disable -flto if it interferes with debugging. CFLAGS += -flto -flto-partition=none # You may want to enable these flags to make setting breakpoints easier. @@ -121,6 +121,7 @@ ifeq ($(DEBUG), 1) CFLAGS += -DENABLE_MICRO_TRACE_BUFFER endif else + CFLAGS += -DNDEBUG # -finline-limit can shrink the image size. # -finline-limit=80 or so is similar to not having it on. # There is no simple default value, though. @@ -257,9 +258,11 @@ SRC_ASF += \ $(BUILD)/asf4/$(CHIP_FAMILY)/hpl/sdhc/hpl_sdhc.o: CFLAGS += -Wno-cast-align endif +$(BUILD)/asf4/$(CHIP_FAMILY)/hpl/sercom/hpl_sercom.o: CFLAGS += -Wno-maybe-uninitialized + SRC_ASF := $(addprefix asf4/$(CHIP_FAMILY)/, $(SRC_ASF)) -SRC_C = \ +SRC_C += \ audio_dma.c \ background.c \ bindings/samd/Clock.c \ diff --git a/ports/atmel-samd/boards/blm_badge/pins.c b/ports/atmel-samd/boards/blm_badge/pins.c index af1b693584..6e7d8da754 100644 --- a/ports/atmel-samd/boards/blm_badge/pins.c +++ b/ports/atmel-samd/boards/blm_badge/pins.c @@ -39,5 +39,7 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_PA03) }, { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA03) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/matrixportal_m4/board.c b/ports/atmel-samd/boards/matrixportal_m4/board.c new file mode 100644 index 0000000000..2d4f302391 --- /dev/null +++ b/ports/atmel-samd/boards/matrixportal_m4/board.c @@ -0,0 +1,39 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Dan Halbert for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "boards/board.h" +#include "mpconfigboard.h" +#include "hal/include/hal_gpio.h" + +void board_init(void) { +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { +} diff --git a/ports/atmel-samd/boards/matrixportal_m4/mpconfigboard.h b/ports/atmel-samd/boards/matrixportal_m4/mpconfigboard.h new file mode 100644 index 0000000000..0368d577bf --- /dev/null +++ b/ports/atmel-samd/boards/matrixportal_m4/mpconfigboard.h @@ -0,0 +1,30 @@ +#define MICROPY_HW_BOARD_NAME "Adafruit Matrix Portal M4" +#define MICROPY_HW_MCU_NAME "samd51j19" + +#define CIRCUITPY_MCU_FAMILY samd51 + +#define MICROPY_HW_LED_STATUS (&pin_PA14) + +#define MICROPY_HW_NEOPIXEL (&pin_PA23) + +// These are pins not to reset. +// QSPI Data pins, PA23 is NeoPixel +#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11 | PA23) +// QSPI CS, QSPI SCK +#define MICROPY_PORT_B (PORT_PB10 | PORT_PB11) +#define MICROPY_PORT_C (0) +#define MICROPY_PORT_D (0) + +#define DEFAULT_I2C_BUS_SCL (&pin_PB03) +#define DEFAULT_I2C_BUS_SDA (&pin_PB02) + +#define DEFAULT_SPI_BUS_SCK (&pin_PA16) +#define DEFAULT_SPI_BUS_MOSI (&pin_PA19) +#define DEFAULT_SPI_BUS_MISO (&pin_PA17) + +#define DEFAULT_UART_BUS_RX (&pin_PA01) +#define DEFAULT_UART_BUS_TX (&pin_PA00) + +// USB is always used internally so skip the pin objects for it. +#define IGNORE_PIN_PA24 1 +#define IGNORE_PIN_PA25 1 diff --git a/ports/atmel-samd/boards/matrixportal_m4/mpconfigboard.mk b/ports/atmel-samd/boards/matrixportal_m4/mpconfigboard.mk new file mode 100644 index 0000000000..44b28acbcb --- /dev/null +++ b/ports/atmel-samd/boards/matrixportal_m4/mpconfigboard.mk @@ -0,0 +1,12 @@ +USB_VID = 0x239A +USB_PID = 0x80CA +USB_PRODUCT = "Matrix Portal M4" +USB_MANUFACTURER = "Adafruit Industries LLC" + +CHIP_VARIANT = SAMD51J19A +CHIP_FAMILY = samd51 + +QSPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 3 +EXTERNAL_FLASH_DEVICES = "S25FL116K, S25FL216K, GD25Q16C" +LONGINT_IMPL = MPZ diff --git a/ports/atmel-samd/boards/matrixportal_m4/pins.c b/ports/atmel-samd/boards/matrixportal_m4/pins.c new file mode 100644 index 0000000000..34865597b6 --- /dev/null +++ b/ports/atmel-samd/boards/matrixportal_m4/pins.c @@ -0,0 +1,61 @@ +#include "shared-bindings/board/__init__.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA05) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PA04) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA06) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA07) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_TX),MP_ROM_PTR(&pin_PA00) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_RX),MP_ROM_PTR(&pin_PA01) }, + + // ESP control + { MP_OBJ_NEW_QSTR(MP_QSTR_ESP_CS), MP_ROM_PTR(&pin_PB17) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ESP_GPIO0), MP_ROM_PTR(&pin_PA20) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ESP_BUSY), MP_ROM_PTR(&pin_PA22) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ESP_RESET), MP_ROM_PTR(&pin_PA21) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ESP_RTS), MP_ROM_PTR(&pin_PA18) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ESP_TX), MP_ROM_PTR(&pin_PA12) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ESP_RX), MP_ROM_PTR(&pin_PA13) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_SCL),MP_ROM_PTR(&pin_PB30) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SDA),MP_ROM_PTR(&pin_PB31) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_NEOPIXEL),MP_ROM_PTR(&pin_PA23) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_SCK),MP_ROM_PTR(&pin_PA16) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MOSI),MP_ROM_PTR(&pin_PA19) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MISO),MP_ROM_PTR(&pin_PA17) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_MTX_R1),MP_ROM_PTR(&pin_PB00) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MTX_G1),MP_ROM_PTR(&pin_PB01) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MTX_B1),MP_ROM_PTR(&pin_PB02) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_MTX_R2),MP_ROM_PTR(&pin_PB03) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MTX_G2),MP_ROM_PTR(&pin_PB04) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MTX_B2),MP_ROM_PTR(&pin_PB05) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_MTX_ADDRA),MP_ROM_PTR(&pin_PB07) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MTX_ADDRB),MP_ROM_PTR(&pin_PB08) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MTX_ADDRC),MP_ROM_PTR(&pin_PB09) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MTX_ADDRD),MP_ROM_PTR(&pin_PB15) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MTX_ADDRE),MP_ROM_PTR(&pin_PB13) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_MTX_CLK),MP_ROM_PTR(&pin_PB06) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MTX_LAT),MP_ROM_PTR(&pin_PB14) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MTX_OE),MP_ROM_PTR(&pin_PB12) }, + + { MP_ROM_QSTR(MP_QSTR_ACCELEROMETER_INTERRUPT), MP_ROM_PTR(&pin_PA27) }, + + // Grounded when closed. + { MP_OBJ_NEW_QSTR(MP_QSTR_BUTTON_UP),MP_ROM_PTR(&pin_PB22) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_BUTTON_DOWN),MP_ROM_PTR(&pin_PB23) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_L),MP_ROM_PTR(&pin_PA14) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk index 4895cda77b..e999629c32 100644 --- a/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk +++ b/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk @@ -6,6 +6,10 @@ USB_MANUFACTURER = "Adafruit Industries LLC" CHIP_VARIANT = SAMD51J19A CHIP_FAMILY = samd51 +# Support _bleio via the on-board ESP32 module. +CIRCUITPY_BLEIO = 1 +CIRCUITPY_BLEIO_HCI = 1 + QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICE_COUNT = 3 EXTERNAL_FLASH_DEVICES = "S25FL116K, S25FL216K, GD25Q16C" diff --git a/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.h index 96b38810c3..331ee894b1 100644 --- a/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.h @@ -16,8 +16,8 @@ #define MICROPY_PORT_C (0) #define MICROPY_PORT_D (0) -#define DEFAULT_I2C_BUS_SCL (&pin_PB08) -#define DEFAULT_I2C_BUS_SDA (&pin_PB09) +#define DEFAULT_I2C_BUS_SCL (&pin_PB09) +#define DEFAULT_I2C_BUS_SDA (&pin_PB08) // USB is always used internally so skip the pin objects for it. #define IGNORE_PIN_PA24 1 diff --git a/ports/esp32s2/boards/electroniccats_bastwifi/board.c b/ports/esp32s2/boards/electroniccats_bastwifi/board.c new file mode 100644 index 0000000000..9f708874bf --- /dev/null +++ b/ports/esp32s2/boards/electroniccats_bastwifi/board.c @@ -0,0 +1,47 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "boards/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/microcontroller/Pin.h" + +void board_init(void) { + // USB + common_hal_never_reset_pin(&pin_GPIO19); + common_hal_never_reset_pin(&pin_GPIO20); + + // Debug UART + common_hal_never_reset_pin(&pin_GPIO43); + common_hal_never_reset_pin(&pin_GPIO44); +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { + +} diff --git a/ports/esp32s2/boards/electroniccats_bastwifi/mpconfigboard.h b/ports/esp32s2/boards/electroniccats_bastwifi/mpconfigboard.h new file mode 100644 index 0000000000..ed3f23a3c4 --- /dev/null +++ b/ports/esp32s2/boards/electroniccats_bastwifi/mpconfigboard.h @@ -0,0 +1,32 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +//Micropython setup + +#define MICROPY_HW_BOARD_NAME "BastWiFi" +#define MICROPY_HW_MCU_NAME "ESP32S2" + +#define AUTORESET_DELAY_MS 500 diff --git a/ports/esp32s2/boards/electroniccats_bastwifi/mpconfigboard.mk b/ports/esp32s2/boards/electroniccats_bastwifi/mpconfigboard.mk new file mode 100644 index 0000000000..6a6ae7937e --- /dev/null +++ b/ports/esp32s2/boards/electroniccats_bastwifi/mpconfigboard.mk @@ -0,0 +1,19 @@ +USB_VID = 0x1209 +USB_PID = 0xBAB0 +USB_PRODUCT = "Bast WiFi" +USB_MANUFACTURER = "ElectronicCats" + +INTERNAL_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = MPZ + +# The default queue depth of 16 overflows on release builds, +# so increase it to 32. +CFLAGS += -DCFG_TUD_TASK_QUEUE_SZ=32 + +CIRCUITPY_NEOPIXEL_WRITE = 0 + +CIRCUITPY_ESP_FLASH_MODE=dio +CIRCUITPY_ESP_FLASH_FREQ=40m +CIRCUITPY_ESP_FLASH_SIZE=4MB + +CIRCUITPY_MODULE=wrover diff --git a/ports/esp32s2/boards/electroniccats_bastwifi/pins.c b/ports/esp32s2/boards/electroniccats_bastwifi/pins.c new file mode 100644 index 0000000000..2f9987b0ed --- /dev/null +++ b/ports/esp32s2/boards/electroniccats_bastwifi/pins.c @@ -0,0 +1,64 @@ +#include "shared-bindings/board/__init__.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, + + + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_IO26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_IO34), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_IO35), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_IO36), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_IO37), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_CS), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/esp32s2/boards/electroniccats_bastwifi/sdkconfig b/ports/esp32s2/boards/electroniccats_bastwifi/sdkconfig new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ports/esp32s2/boards/espressif_kaluga_1/board.c b/ports/esp32s2/boards/espressif_kaluga_1/board.c new file mode 100644 index 0000000000..9f708874bf --- /dev/null +++ b/ports/esp32s2/boards/espressif_kaluga_1/board.c @@ -0,0 +1,47 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "boards/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/microcontroller/Pin.h" + +void board_init(void) { + // USB + common_hal_never_reset_pin(&pin_GPIO19); + common_hal_never_reset_pin(&pin_GPIO20); + + // Debug UART + common_hal_never_reset_pin(&pin_GPIO43); + common_hal_never_reset_pin(&pin_GPIO44); +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { + +} diff --git a/ports/esp32s2/boards/espressif_kaluga_1/mpconfigboard.h b/ports/esp32s2/boards/espressif_kaluga_1/mpconfigboard.h new file mode 100644 index 0000000000..84d15ffc2b --- /dev/null +++ b/ports/esp32s2/boards/espressif_kaluga_1/mpconfigboard.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +//Micropython setup + +#define MICROPY_HW_BOARD_NAME "Kaluga 1" +#define MICROPY_HW_MCU_NAME "ESP32S2" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO45) + +#define AUTORESET_DELAY_MS 500 diff --git a/ports/esp32s2/boards/espressif_kaluga_1/mpconfigboard.mk b/ports/esp32s2/boards/espressif_kaluga_1/mpconfigboard.mk new file mode 100644 index 0000000000..ba85e46efc --- /dev/null +++ b/ports/esp32s2/boards/espressif_kaluga_1/mpconfigboard.mk @@ -0,0 +1,17 @@ +USB_VID = 0x239A +USB_PID = 0x80C8 +USB_PRODUCT = "Kaluga 1" +USB_MANUFACTURER = "Espressif" + +INTERNAL_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = MPZ + +# The default queue depth of 16 overflows on release builds, +# so increase it to 32. +CFLAGS += -DCFG_TUD_TASK_QUEUE_SZ=32 + +CIRCUITPY_ESP_FLASH_MODE=dio +CIRCUITPY_ESP_FLASH_FREQ=40m +CIRCUITPY_ESP_FLASH_SIZE=4MB + +CIRCUITPY_MODULE=wrover diff --git a/ports/esp32s2/boards/espressif_kaluga_1/pins.c b/ports/esp32s2/boards/espressif_kaluga_1/pins.c new file mode 100644 index 0000000000..c1657d6c0e --- /dev/null +++ b/ports/esp32s2/boards/espressif_kaluga_1/pins.c @@ -0,0 +1,125 @@ +#include "shared-bindings/board/__init__.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, + + + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_IO26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_IO34), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_IO35), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_IO36), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_IO37), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, + + + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO45) }, + + { MP_ROM_QSTR(MP_QSTR_CAMERA_XCLK), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_PCLK), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_HREF), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_VSYNC), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_SIOD), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_SIOC), MP_ROM_PTR(&pin_GPIO7) }, + + + { MP_ROM_QSTR(MP_QSTR_CAMERA_D2), MP_ROM_PTR(&pin_GPIO46) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_D3), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_D4), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_D5), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_D6), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_D7), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_D8), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_D9), MP_ROM_PTR(&pin_GPIO38) }, + + + { MP_ROM_QSTR(MP_QSTR_TOUCH1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH14), MP_ROM_PTR(&pin_GPIO14) }, + + // LED FPC + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_BT_ARRAY_ADC), MP_ROM_PTR(&pin_GPIO6) }, + + // 3.2 inch LCD FPC + { MP_ROM_QSTR(MP_QSTR_LCD_TP_MISO), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_LCD_TP_MOSI), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_LCD_TP_SCK), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_LCD_TP_CS), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_LCD_TP_IRQ), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_LCD_TP_BUSY), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_LCD_BL_CTR), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_LCD_MISO), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_LCD_MOSI), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D_C), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CLK), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_LCD_RST), MP_ROM_PTR(&pin_GPIO16) }, + + // Audio + { MP_ROM_QSTR(MP_QSTR_AUDIO_SPI_MISO), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_AUDIO_SPI_MOSI), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_AUDIO_SPI_SCK), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_AUDIO_SPI_CS), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_AUDIO_BT_ADC), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_AUDIO_SCL), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_AUDIO_SDA), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_AUDIO_I2S0_MCLK), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_AUDIO_I2S0_BCLK), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_AUDIO_I2S0_LRCK), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_AUDIO_I2S0_SDI), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_AUDIO_I2S0_SDO), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_AUDIO_RST), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_AUDIO_WAKE_INT), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_AUDIO_I2S1_MCLK), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_AUDIO_PA_CTRL), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_AUDIO_I2S1_SDI), MP_ROM_PTR(&pin_GPIO46) }, + { MP_ROM_QSTR(MP_QSTR_AUDIO_I2S1_SDO), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_AUDIO_I2S1_LRCK_DAC1), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_AUDIO_I2S1_BCLK_DAC2), MP_ROM_PTR(&pin_GPIO18) }, + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/esp32s2/boards/espressif_kaluga_1/sdkconfig b/ports/esp32s2/boards/espressif_kaluga_1/sdkconfig new file mode 100644 index 0000000000..9d8bbde967 --- /dev/null +++ b/ports/esp32s2/boards/espressif_kaluga_1/sdkconfig @@ -0,0 +1,33 @@ +CONFIG_ESP32S2_SPIRAM_SUPPORT=y + +# +# SPI RAM config +# +# CONFIG_SPIRAM_TYPE_AUTO is not set +CONFIG_SPIRAM_TYPE_ESPPSRAM16=y +# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set +CONFIG_SPIRAM_SIZE=2097152 + +# +# PSRAM clock and cs IO for ESP32S2 +# +CONFIG_DEFAULT_PSRAM_CLK_IO=30 +CONFIG_DEFAULT_PSRAM_CS_IO=26 +# end of PSRAM clock and cs IO for ESP32S2 + +# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set +# CONFIG_SPIRAM_RODATA is not set +# CONFIG_SPIRAM_SPEED_80M is not set +CONFIG_SPIRAM_SPEED_40M=y +# CONFIG_SPIRAM_SPEED_26M is not set +# CONFIG_SPIRAM_SPEED_20M is not set +CONFIG_SPIRAM=y +CONFIG_SPIRAM_BOOT_INIT=y +# CONFIG_SPIRAM_IGNORE_NOTFOUND is not set +CONFIG_SPIRAM_USE_MEMMAP=y +# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set +# CONFIG_SPIRAM_USE_MALLOC is not set +CONFIG_SPIRAM_MEMTEST=y +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is not set +# end of SPI RAM config diff --git a/ports/esp32s2/boards/espressif_saola_1_wrover/sdkconfig b/ports/esp32s2/boards/espressif_saola_1_wrover/sdkconfig index e69de29bb2..9d8bbde967 100644 --- a/ports/esp32s2/boards/espressif_saola_1_wrover/sdkconfig +++ b/ports/esp32s2/boards/espressif_saola_1_wrover/sdkconfig @@ -0,0 +1,33 @@ +CONFIG_ESP32S2_SPIRAM_SUPPORT=y + +# +# SPI RAM config +# +# CONFIG_SPIRAM_TYPE_AUTO is not set +CONFIG_SPIRAM_TYPE_ESPPSRAM16=y +# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set +CONFIG_SPIRAM_SIZE=2097152 + +# +# PSRAM clock and cs IO for ESP32S2 +# +CONFIG_DEFAULT_PSRAM_CLK_IO=30 +CONFIG_DEFAULT_PSRAM_CS_IO=26 +# end of PSRAM clock and cs IO for ESP32S2 + +# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set +# CONFIG_SPIRAM_RODATA is not set +# CONFIG_SPIRAM_SPEED_80M is not set +CONFIG_SPIRAM_SPEED_40M=y +# CONFIG_SPIRAM_SPEED_26M is not set +# CONFIG_SPIRAM_SPEED_20M is not set +CONFIG_SPIRAM=y +CONFIG_SPIRAM_BOOT_INIT=y +# CONFIG_SPIRAM_IGNORE_NOTFOUND is not set +CONFIG_SPIRAM_USE_MEMMAP=y +# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set +# CONFIG_SPIRAM_USE_MALLOC is not set +CONFIG_SPIRAM_MEMTEST=y +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is not set +# end of SPI RAM config diff --git a/ports/esp32s2/boards/microdev_micro_s2/board.c b/ports/esp32s2/boards/microdev_micro_s2/board.c new file mode 100644 index 0000000000..1dc30b5af8 --- /dev/null +++ b/ports/esp32s2/boards/microdev_micro_s2/board.c @@ -0,0 +1,56 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "boards/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/microcontroller/Pin.h" + +void board_init(void) { + // USB + common_hal_never_reset_pin(&pin_GPIO19); + common_hal_never_reset_pin(&pin_GPIO20); + + // Debug UART + common_hal_never_reset_pin(&pin_GPIO43); + common_hal_never_reset_pin(&pin_GPIO44); + + // SPI Flash and RAM + common_hal_never_reset_pin(&pin_GPIO26); + common_hal_never_reset_pin(&pin_GPIO27); + common_hal_never_reset_pin(&pin_GPIO28); + common_hal_never_reset_pin(&pin_GPIO29); + common_hal_never_reset_pin(&pin_GPIO30); + common_hal_never_reset_pin(&pin_GPIO31); + common_hal_never_reset_pin(&pin_GPIO32); +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { + +} diff --git a/ports/esp32s2/boards/microdev_micro_s2/mpconfigboard.h b/ports/esp32s2/boards/microdev_micro_s2/mpconfigboard.h new file mode 100644 index 0000000000..bb28fe16ad --- /dev/null +++ b/ports/esp32s2/boards/microdev_micro_s2/mpconfigboard.h @@ -0,0 +1,35 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +//Micropython setup + +#define MICROPY_HW_BOARD_NAME "microDev microS2" +#define MICROPY_HW_MCU_NAME "ESP32S2" + +#define MICROPY_HW_LED (&pin_GPIO21) +#define MICROPY_HW_NEOPIXEL (&pin_GPIO33) + +#define AUTORESET_DELAY_MS 500 diff --git a/ports/esp32s2/boards/microdev_micro_s2/mpconfigboard.mk b/ports/esp32s2/boards/microdev_micro_s2/mpconfigboard.mk new file mode 100644 index 0000000000..783e7ad4c7 --- /dev/null +++ b/ports/esp32s2/boards/microdev_micro_s2/mpconfigboard.mk @@ -0,0 +1,15 @@ +USB_VID = 0x239A +USB_PID = 0x80C6 +USB_PRODUCT = "microS2" +USB_MANUFACTURER = "microDev" + +INTERNAL_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = MPZ + +# The default queue depth of 16 overflows on release builds, +# so increase it to 32. +CFLAGS += -DCFG_TUD_TASK_QUEUE_SZ=32 + +CIRCUITPY_ESP_FLASH_MODE=qio +CIRCUITPY_ESP_FLASH_FREQ=40m +CIRCUITPY_ESP_FLASH_SIZE=16MB diff --git a/ports/esp32s2/boards/microdev_micro_s2/pins.c b/ports/esp32s2/boards/microdev_micro_s2/pins.c new file mode 100644 index 0000000000..25300b5c3c --- /dev/null +++ b/ports/esp32s2/boards/microdev_micro_s2/pins.c @@ -0,0 +1,49 @@ +#include "shared-bindings/board/__init__.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_IO26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_IO34), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_IO35), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_IO36), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_IO37), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO33) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/esp32s2/boards/microdev_micro_s2/sdkconfig b/ports/esp32s2/boards/microdev_micro_s2/sdkconfig new file mode 100644 index 0000000000..b73c4a8c20 --- /dev/null +++ b/ports/esp32s2/boards/microdev_micro_s2/sdkconfig @@ -0,0 +1,35 @@ +CONFIG_ESP32S2_SPIRAM_SUPPORT=y + +# +# SPI RAM config +# +# CONFIG_SPIRAM_TYPE_AUTO is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM16 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set +CONFIG_SPIRAM_TYPE_ESPPSRAM64=y +CONFIG_SPIRAM_SIZE=8388608 + +# +# PSRAM clock and cs IO for ESP32S2 +# +CONFIG_DEFAULT_PSRAM_CLK_IO=30 +CONFIG_DEFAULT_PSRAM_CS_IO=26 +# end of PSRAM clock and cs IO for ESP32S2 + +CONFIG_SPIRAM_SPIWP_SD3_PIN=28 +# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set +# CONFIG_SPIRAM_RODATA is not set +# CONFIG_SPIRAM_USE_AHB_DBUS3 is not set +# CONFIG_SPIRAM_SPEED_80M is not set +CONFIG_SPIRAM_SPEED_40M=y +# CONFIG_SPIRAM_SPEED_26M is not set +# CONFIG_SPIRAM_SPEED_20M is not set +CONFIG_SPIRAM=y +CONFIG_SPIRAM_BOOT_INIT=y +# CONFIG_SPIRAM_IGNORE_NOTFOUND is not set +CONFIG_SPIRAM_USE_MEMMAP=y +# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set +# CONFIG_SPIRAM_USE_MALLOC is not set +CONFIG_SPIRAM_MEMTEST=y +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is not set +# end of SPI RAM config diff --git a/ports/esp32s2/boards/unexpectedmaker_feathers2/sdkconfig b/ports/esp32s2/boards/unexpectedmaker_feathers2/sdkconfig index e69de29bb2..b73c4a8c20 100644 --- a/ports/esp32s2/boards/unexpectedmaker_feathers2/sdkconfig +++ b/ports/esp32s2/boards/unexpectedmaker_feathers2/sdkconfig @@ -0,0 +1,35 @@ +CONFIG_ESP32S2_SPIRAM_SUPPORT=y + +# +# SPI RAM config +# +# CONFIG_SPIRAM_TYPE_AUTO is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM16 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set +CONFIG_SPIRAM_TYPE_ESPPSRAM64=y +CONFIG_SPIRAM_SIZE=8388608 + +# +# PSRAM clock and cs IO for ESP32S2 +# +CONFIG_DEFAULT_PSRAM_CLK_IO=30 +CONFIG_DEFAULT_PSRAM_CS_IO=26 +# end of PSRAM clock and cs IO for ESP32S2 + +CONFIG_SPIRAM_SPIWP_SD3_PIN=28 +# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set +# CONFIG_SPIRAM_RODATA is not set +# CONFIG_SPIRAM_USE_AHB_DBUS3 is not set +# CONFIG_SPIRAM_SPEED_80M is not set +CONFIG_SPIRAM_SPEED_40M=y +# CONFIG_SPIRAM_SPEED_26M is not set +# CONFIG_SPIRAM_SPEED_20M is not set +CONFIG_SPIRAM=y +CONFIG_SPIRAM_BOOT_INIT=y +# CONFIG_SPIRAM_IGNORE_NOTFOUND is not set +CONFIG_SPIRAM_USE_MEMMAP=y +# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set +# CONFIG_SPIRAM_USE_MALLOC is not set +CONFIG_SPIRAM_MEMTEST=y +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is not set +# end of SPI RAM config diff --git a/ports/esp32s2/common-hal/microcontroller/Processor.c b/ports/esp32s2/common-hal/microcontroller/Processor.c index 39b85a18b8..c64fa010e6 100644 --- a/ports/esp32s2/common-hal/microcontroller/Processor.c +++ b/ports/esp32s2/common-hal/microcontroller/Processor.c @@ -34,8 +34,16 @@ #include "soc/efuse_reg.h" +#include "esp-idf/components/driver/esp32s2/include/driver/temp_sensor.h" + float common_hal_mcu_processor_get_temperature(void) { - return NAN; + float tsens_out; + temp_sensor_config_t temp_sensor = TSENS_CONFIG_DEFAULT(); // DEFAULT: range:-10℃ ~ 80℃, error < 1℃. + temp_sensor_set_config(temp_sensor); + temp_sensor_start(); + temp_sensor_read_celsius(&tsens_out); + temp_sensor_stop(); + return tsens_out; } float common_hal_mcu_processor_get_voltage(void) { diff --git a/ports/esp32s2/common-hal/os/__init__.c b/ports/esp32s2/common-hal/os/__init__.c index 17bda75ad3..4d6a6a2bfc 100644 --- a/ports/esp32s2/common-hal/os/__init__.c +++ b/ports/esp32s2/common-hal/os/__init__.c @@ -30,6 +30,8 @@ #include "py/objtuple.h" #include "py/qstr.h" +#include "esp_system.h" + STATIC const qstr os_uname_info_fields[] = { MP_QSTR_sysname, MP_QSTR_nodename, MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine @@ -57,5 +59,15 @@ mp_obj_t common_hal_os_uname(void) { } bool common_hal_os_urandom(uint8_t* buffer, uint32_t length) { - return false; + uint32_t i = 0; + while (i < length) { + uint32_t new_random = esp_random(); + for (int j = 0; j < 4 && i < length; j++) { + buffer[i] = new_random & 0xff; + i++; + new_random >>= 8; + } + } + + return true; } diff --git a/ports/esp32s2/mpconfigport.mk b/ports/esp32s2/mpconfigport.mk index a7873aa468..d13eb17f72 100644 --- a/ports/esp32s2/mpconfigport.mk +++ b/ports/esp32s2/mpconfigport.mk @@ -25,8 +25,9 @@ CIRCUITPY_COUNTIO = 0 # These modules are implemented in shared-module/ - they can be included in # any port once their prerequisites in common-hal are complete. -CIRCUITPY_RANDOM = 0 # Requires OS -CIRCUITPY_USB_MIDI = 0 # Requires USB -CIRCUITPY_ULAB = 0 # No requirements, but takes extra flash +# Requires USB +CIRCUITPY_USB_MIDI = 0 +# Too large for the partition table! +CIRCUITPY_ULAB = 0 CIRCUITPY_MODULE ?= none diff --git a/ports/esp32s2/supervisor/port.c b/ports/esp32s2/supervisor/port.c index 03caed92e5..1300c2b713 100644 --- a/ports/esp32s2/supervisor/port.c +++ b/ports/esp32s2/supervisor/port.c @@ -43,7 +43,14 @@ #include "supervisor/memory.h" #include "supervisor/shared/tick.h" -#include "rmt.h" +#include "peripherals/rmt.h" +#include "esp-idf/components/heap/include/esp_heap_caps.h" +#include "esp-idf/components/soc/soc/esp32s2/include/soc/cache_memory.h" + +#define HEAP_SIZE (48 * 1024) + +uint32_t* heap; +uint32_t heap_size; STATIC esp_timer_handle_t _tick_timer; @@ -59,6 +66,16 @@ safe_mode_t port_init(void) { args.name = "CircuitPython Tick"; esp_timer_create(&args, &_tick_timer); never_reset_module_internal_pins(); + + #ifdef CONFIG_SPIRAM + heap = (uint32_t*) (DRAM0_CACHE_ADDRESS_HIGH - CONFIG_SPIRAM_SIZE); + heap_size = CONFIG_SPIRAM_SIZE / sizeof(uint32_t); + #endif + + if (heap == NULL) { + heap = malloc(HEAP_SIZE); + heap_size = HEAP_SIZE / sizeof(uint32_t); + } return NO_SAFE_MODE; } @@ -90,14 +107,12 @@ void reset_to_bootloader(void) { void reset_cpu(void) { } -uint32_t heap[64 / sizeof(uint32_t) * 1024]; - uint32_t *port_heap_get_bottom(void) { return heap; } uint32_t *port_heap_get_top(void) { - return heap + sizeof(heap) / sizeof(heap[0]); + return heap + heap_size; } uint32_t *port_stack_get_limit(void) { diff --git a/ports/nrf/bluetooth/ble_drv.c b/ports/nrf/bluetooth/ble_drv.c index e410ac3b42..67c6f34687 100644 --- a/ports/nrf/bluetooth/ble_drv.c +++ b/ports/nrf/bluetooth/ble_drv.c @@ -39,6 +39,7 @@ #include "py/mpstate.h" #include "supervisor/shared/bluetooth.h" +#include "supervisor/bluetooth.h" nrf_nvic_state_t nrf_nvic_state = { 0 }; diff --git a/ports/nrf/common-hal/_bleio/Adapter.c b/ports/nrf/common-hal/_bleio/Adapter.c index 4df26f33a9..537f43f237 100644 --- a/ports/nrf/common-hal/_bleio/Adapter.c +++ b/ports/nrf/common-hal/_bleio/Adapter.c @@ -354,6 +354,8 @@ void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enable if (enabled) { for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { bleio_connection_internal_t *connection = &bleio_connections[i]; + // Reset connection. + bleio_connection_clear(connection); connection->conn_handle = BLE_CONN_HANDLE_INVALID; } bleio_adapter_reset_name(self); @@ -589,6 +591,7 @@ mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_addre for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { bleio_connection_internal_t *connection = &bleio_connections[i]; if (connection->conn_handle == conn_handle) { + connection->is_central = true; return bleio_connection_new_from_internal(connection); } } diff --git a/ports/nrf/common-hal/_bleio/Characteristic.c b/ports/nrf/common-hal/_bleio/Characteristic.c index d507cecca4..57c4814489 100644 --- a/ports/nrf/common-hal/_bleio/Characteristic.c +++ b/ports/nrf/common-hal/_bleio/Characteristic.c @@ -90,7 +90,8 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, self->props = props; self->read_perm = read_perm; self->write_perm = write_perm; - self->descriptor_list = NULL; + self->initial_value = mp_obj_new_bytes(initial_value_bufinfo->buf, initial_value_bufinfo->len); + self->descriptor_list = mp_obj_new_list(0, NULL); const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_MAX; if (max_length < 0 || max_length > max_length_max) { @@ -105,14 +106,10 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, } else { common_hal_bleio_service_add_characteristic(self->service, self, initial_value_bufinfo); } - - if (initial_value_bufinfo != NULL) { - common_hal_bleio_characteristic_set_value(self, initial_value_bufinfo); - } } -bleio_descriptor_obj_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self) { - return self->descriptor_list; +mp_obj_tuple_t *common_hal_bleio_characteristic_get_descriptors(bleio_characteristic_obj_t *self) { + return mp_obj_new_tuple(self->descriptor_list->len, self->descriptor_list->items); } bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_characteristic_obj_t *self) { @@ -124,7 +121,6 @@ size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *sel if (self->handle != BLE_GATT_HANDLE_INVALID) { uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); if (common_hal_bleio_service_get_is_remote(self->service)) { - // self->value is set by evt handler. return common_hal_bleio_gattc_read(self->handle, conn_handle, buf, len); } else { // conn_handle is ignored for non-system attributes. @@ -205,7 +201,7 @@ void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t * bleio_attribute_gatts_set_security_mode(&desc_attr_md.write_perm, descriptor->write_perm); mp_buffer_info_t desc_value_bufinfo; - mp_get_buffer_raise(descriptor->value, &desc_value_bufinfo, MP_BUFFER_READ); + mp_get_buffer_raise(descriptor->initial_value, &desc_value_bufinfo, MP_BUFFER_READ); ble_gatts_attr_t desc_attr = { .p_uuid = &desc_uuid, @@ -218,8 +214,8 @@ void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t * check_nrf_error(sd_ble_gatts_descriptor_add(self->handle, &desc_attr, &descriptor->handle)); - descriptor->next = self->descriptor_list; - self->descriptor_list = descriptor; + mp_obj_list_append(MP_OBJ_FROM_PTR(self->descriptor_list), + MP_OBJ_FROM_PTR(descriptor)); } void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate) { diff --git a/ports/nrf/common-hal/_bleio/Characteristic.h b/ports/nrf/common-hal/_bleio/Characteristic.h index bb8f28495e..382fd4a81e 100644 --- a/ports/nrf/common-hal/_bleio/Characteristic.h +++ b/ports/nrf/common-hal/_bleio/Characteristic.h @@ -39,14 +39,14 @@ typedef struct _bleio_characteristic_obj { // Will be MP_OBJ_NULL before being assigned to a Service. bleio_service_obj_t *service; bleio_uuid_obj_t *uuid; - mp_obj_t value; + mp_obj_t initial_value; uint16_t max_length; bool fixed_length; uint16_t handle; bleio_characteristic_properties_t props; bleio_attribute_security_mode_t read_perm; bleio_attribute_security_mode_t write_perm; - bleio_descriptor_obj_t *descriptor_list; + mp_obj_list_t *descriptor_list; uint16_t user_desc_handle; uint16_t cccd_handle; uint16_t sccd_handle; diff --git a/ports/nrf/common-hal/_bleio/Connection.c b/ports/nrf/common-hal/_bleio/Connection.c index 00c1acd4d4..4f747bf976 100644 --- a/ports/nrf/common-hal/_bleio/Connection.c +++ b/ports/nrf/common-hal/_bleio/Connection.c @@ -325,10 +325,11 @@ bool connection_on_ble_evt(ble_evt_t *ble_evt, void *self_in) { } void bleio_connection_clear(bleio_connection_internal_t *self) { - self->remote_service_list = NULL; + mp_obj_list_clear(MP_OBJ_FROM_PTR(self->remote_service_list)); self->conn_handle = BLE_CONN_HANDLE_INVALID; self->pair_status = PAIR_NOT_PAIRED; + self->is_central = false; bonding_clear_keys(&self->bonding_keys); } @@ -452,8 +453,6 @@ STATIC bool discover_next_descriptors(bleio_connection_internal_t* connection, b } STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *response, bleio_connection_internal_t* connection) { - bleio_service_obj_t* tail = connection->remote_service_list; - for (size_t i = 0; i < response->count; ++i) { ble_gattc_service_t *gattc_service = &response->services[i]; @@ -481,12 +480,10 @@ STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *res service->uuid = NULL; } - service->next = tail; - tail = service; + mp_obj_list_append(MP_OBJ_FROM_PTR(connection->remote_service_list), + MP_OBJ_FROM_PTR(service)); } - connection->remote_service_list = tail; - if (response->count > 0) { m_discovery_successful = true; } @@ -526,9 +523,10 @@ STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio characteristic, m_char_discovery_service, gattc_char->handle_value, uuid, props, SECURITY_MODE_OPEN, SECURITY_MODE_OPEN, GATT_MAX_DATA_LENGTH, false, // max_length, fixed_length: values may not matter for gattc - NULL); + mp_const_empty_bytes); - mp_obj_list_append(m_char_discovery_service->characteristic_list, MP_OBJ_FROM_PTR(characteristic)); + mp_obj_list_append(MP_OBJ_FROM_PTR(m_char_discovery_service->characteristic_list), + MP_OBJ_FROM_PTR(characteristic)); } if (response->count > 0) { @@ -584,7 +582,8 @@ STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, bleio GATT_MAX_DATA_LENGTH, false, mp_const_empty_bytes); descriptor->handle = gattc_desc->handle; - mp_obj_list_append(m_desc_discovery_characteristic->descriptor_list, MP_OBJ_FROM_PTR(descriptor)); + mp_obj_list_append(MP_OBJ_FROM_PTR(m_desc_discovery_characteristic->descriptor_list), + MP_OBJ_FROM_PTR(descriptor)); } if (response->count > 0) { @@ -625,7 +624,7 @@ STATIC void discover_remote_services(bleio_connection_internal_t *self, mp_obj_t ble_drv_add_event_handler(discovery_on_ble_evt, self); // Start over with an empty list. - self->remote_service_list = NULL; + self->remote_service_list = mp_obj_new_list(0, NULL); if (service_uuids_whitelist == mp_const_none) { // List of service UUID's not given, so discover all available services. @@ -637,7 +636,9 @@ STATIC void discover_remote_services(bleio_connection_internal_t *self, mp_obj_t // Get the most recently discovered service, and then ask for services // whose handles start after the last attribute handle inside that service. - const bleio_service_obj_t *service = self->remote_service_list; + // There must be at least one if discover_next_services() returned true. + const bleio_service_obj_t *service = + self->remote_service_list->items[self->remote_service_list->len - 1]; next_service_start_handle = service->end_handle + 1; } } else { @@ -661,11 +662,10 @@ STATIC void discover_remote_services(bleio_connection_internal_t *self, mp_obj_t } - bleio_service_obj_t *service = self->remote_service_list; - while (service != NULL) { + for (size_t i = 0; i < self->remote_service_list->len; i++) { + bleio_service_obj_t *service = MP_OBJ_TO_PTR(self->remote_service_list->items[i]); // Skip the service if it had an unknown (unregistered) UUID. if (service->uuid == NULL) { - service = service->next; continue; } @@ -677,9 +677,9 @@ STATIC void discover_remote_services(bleio_connection_internal_t *self, mp_obj_t while (next_char_start_handle <= service->end_handle && discover_next_characteristics(self, service, next_char_start_handle)) { - // Get the most recently discovered characteristic, and then ask for characteristics // whose handles start after the last attribute handle inside that characteristic. + // There must be at least one if discover_next_characteristics() returned true. const bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(service->characteristic_list->items[service->characteristic_list->len - 1]); @@ -717,24 +717,26 @@ STATIC void discover_remote_services(bleio_connection_internal_t *self, mp_obj_t next_desc_start_handle, next_desc_end_handle)) { // Get the most recently discovered descriptor, and then ask for descriptors // whose handles start after that descriptor's handle. - const bleio_descriptor_obj_t *descriptor = characteristic->descriptor_list; + // There must be at least one if discover_next_descriptors() returned true. + const bleio_descriptor_obj_t *descriptor = + characteristic->descriptor_list->items[characteristic->descriptor_list->len - 1]; next_desc_start_handle = descriptor->handle + 1; } } - service = service->next; } // This event handler is no longer needed. ble_drv_remove_event_handler(discovery_on_ble_evt, self); - } mp_obj_tuple_t *common_hal_bleio_connection_discover_remote_services(bleio_connection_obj_t *self, mp_obj_t service_uuids_whitelist) { discover_remote_services(self->connection, service_uuids_whitelist); bleio_connection_ensure_connected(self); // Convert to a tuple and then clear the list so the callee will take ownership. - mp_obj_tuple_t *services_tuple = service_linked_list_to_tuple(self->connection->remote_service_list); - self->connection->remote_service_list = NULL; + mp_obj_tuple_t *services_tuple = + mp_obj_new_tuple(self->connection->remote_service_list->len, + self->connection->remote_service_list->items); + mp_obj_list_clear(MP_OBJ_FROM_PTR(self->connection->remote_service_list)); return services_tuple; } diff --git a/ports/nrf/common-hal/_bleio/Connection.h b/ports/nrf/common-hal/_bleio/Connection.h index b051e5c511..180b2727ca 100644 --- a/ports/nrf/common-hal/_bleio/Connection.h +++ b/ports/nrf/common-hal/_bleio/Connection.h @@ -53,7 +53,7 @@ typedef struct { uint16_t conn_handle; bool is_central; // Remote services discovered when this peripheral is acting as a client. - bleio_service_obj_t *remote_service_list; + mp_obj_list_t *remote_service_list; // The advertising data and scan response buffers are held by us, not by the SD, so we must // maintain them and not change it. If we need to change the contents during advertising, // there are tricks to get the SD to notice (see DevZone - TBS). @@ -67,7 +67,7 @@ typedef struct { ble_gap_conn_params_t conn_params; volatile bool conn_params_updating; uint16_t mtu; - // Request that CCCD values for this conenction be saved, using sys_attr values. + // Request that CCCD values for this connection be saved, using sys_attr values. volatile bool do_bond_cccds; // Request that security key info for this connection be saved. volatile bool do_bond_keys; @@ -83,6 +83,7 @@ typedef struct { uint8_t disconnect_reason; } bleio_connection_obj_t; +void bleio_connection_clear(bleio_connection_internal_t *self); bool connection_on_ble_evt(ble_evt_t *ble_evt, void *self_in); uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self); diff --git a/ports/nrf/common-hal/_bleio/Descriptor.c b/ports/nrf/common-hal/_bleio/Descriptor.c index faf50c658c..9e91107231 100644 --- a/ports/nrf/common-hal/_bleio/Descriptor.c +++ b/ports/nrf/common-hal/_bleio/Descriptor.c @@ -39,6 +39,7 @@ void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_c self->handle = BLE_GATT_HANDLE_INVALID; self->read_perm = read_perm; self->write_perm = write_perm; + self->initial_value = mp_obj_new_bytes(initial_value_bufinfo->buf, initial_value_bufinfo->len); const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_MAX; if (max_length < 0 || max_length > max_length_max) { @@ -47,8 +48,6 @@ void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_c } self->max_length = max_length; self->fixed_length = fixed_length; - - common_hal_bleio_descriptor_set_value(self, initial_value_bufinfo); } bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self) { @@ -81,8 +80,6 @@ void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buff mp_raise_ValueError(translate("Value length > max_length")); } - self->value = mp_obj_new_bytes(bufinfo->buf, bufinfo->len); - // Do GATT operations only if this descriptor has been registered. if (self->handle != BLE_GATT_HANDLE_INVALID) { uint16_t conn_handle = bleio_connection_get_conn_handle(self->characteristic->service->connection); diff --git a/ports/nrf/common-hal/_bleio/Descriptor.h b/ports/nrf/common-hal/_bleio/Descriptor.h index c70547c08e..4d6ac2543f 100644 --- a/ports/nrf/common-hal/_bleio/Descriptor.h +++ b/ports/nrf/common-hal/_bleio/Descriptor.h @@ -41,13 +41,12 @@ typedef struct _bleio_descriptor_obj { // Will be MP_OBJ_NULL before being assigned to a Characteristic. struct _bleio_characteristic_obj *characteristic; bleio_uuid_obj_t *uuid; - mp_obj_t value; + mp_obj_t initial_value; uint16_t max_length; bool fixed_length; uint16_t handle; bleio_attribute_security_mode_t read_perm; bleio_attribute_security_mode_t write_perm; - struct _bleio_descriptor_obj* next; } bleio_descriptor_obj_t; #endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_DESCRIPTOR_H diff --git a/ports/nrf/common-hal/_bleio/Service.c b/ports/nrf/common-hal/_bleio/Service.c index 19288f7479..3159d3392f 100644 --- a/ports/nrf/common-hal/_bleio/Service.c +++ b/ports/nrf/common-hal/_bleio/Service.c @@ -73,8 +73,8 @@ bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self) { return self->uuid; } -mp_obj_list_t *common_hal_bleio_service_get_characteristic_list(bleio_service_obj_t *self) { - return self->characteristic_list; +mp_obj_tuple_t *common_hal_bleio_service_get_characteristics(bleio_service_obj_t *self) { + return mp_obj_new_tuple(self->characteristic_list->len, self->characteristic_list->items); } bool common_hal_bleio_service_get_is_remote(bleio_service_obj_t *self) { @@ -124,11 +124,14 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, char_attr_md.rd_auth = true; #endif + mp_buffer_info_t char_value_bufinfo; + mp_get_buffer_raise(characteristic->initial_value, &char_value_bufinfo, MP_BUFFER_READ); + ble_gatts_attr_t char_attr = { .p_uuid = &char_uuid, .p_attr_md = &char_attr_md, - .init_len = 0, - .p_value = NULL, + .init_len = char_value_bufinfo.len, + .p_value = char_value_bufinfo.buf, .init_offs = 0, .max_len = characteristic->max_length, }; diff --git a/ports/nrf/common-hal/_bleio/Service.h b/ports/nrf/common-hal/_bleio/Service.h index 6ee9fe63de..00f611dd9d 100644 --- a/ports/nrf/common-hal/_bleio/Service.h +++ b/ports/nrf/common-hal/_bleio/Service.h @@ -46,7 +46,6 @@ typedef struct bleio_service_obj { // Range of attribute handles of this remote service. uint16_t start_handle; uint16_t end_handle; - struct bleio_service_obj* next; } bleio_service_obj_t; void bleio_service_from_connection(bleio_service_obj_t *self, mp_obj_t connection); diff --git a/ports/nrf/common-hal/_bleio/UUID.c b/ports/nrf/common-hal/_bleio/UUID.c index 6a3d643050..0c79e980ee 100644 --- a/ports/nrf/common-hal/_bleio/UUID.c +++ b/ports/nrf/common-hal/_bleio/UUID.c @@ -40,7 +40,7 @@ // If uuid128 is NULL, this is a Bluetooth SIG 16-bit UUID. // If uuid128 is not NULL, it's a 128-bit (16-byte) UUID, with bytes 12 and 13 zero'd out, where // the 16-bit part goes. Those 16 bits are passed in uuid16. -void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, uint32_t uuid16, const uint8_t uuid128[]) { +void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, mp_int_t uuid16, const uint8_t uuid128[16]) { self->nrf_ble_uuid.uuid = uuid16; if (uuid128 == NULL) { self->nrf_ble_uuid.type = BLE_UUID_TYPE_BLE; diff --git a/ports/nrf/common-hal/_bleio/__init__.c b/ports/nrf/common-hal/_bleio/__init__.c index 23d7397c79..496c9429fe 100644 --- a/ports/nrf/common-hal/_bleio/__init__.c +++ b/ports/nrf/common-hal/_bleio/__init__.c @@ -39,6 +39,7 @@ #include "supervisor/shared/bluetooth.h" #include "common-hal/_bleio/__init__.h" +#include "common-hal/_bleio/bonding.h" void check_nrf_error(uint32_t err_code) { if (err_code == NRF_SUCCESS) { @@ -243,6 +244,10 @@ void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buff } +void bleio_background(void) { + bonding_background(); +} + void common_hal_bleio_gc_collect(void) { bleio_adapter_gc_collect(&common_hal_bleio_adapter_obj); } diff --git a/ports/nrf/common-hal/_bleio/__init__.h b/ports/nrf/common-hal/_bleio/__init__.h index 6881c90e6c..97f82ece34 100644 --- a/ports/nrf/common-hal/_bleio/__init__.h +++ b/ports/nrf/common-hal/_bleio/__init__.h @@ -27,6 +27,7 @@ #ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_INIT_H #define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_INIT_H +void bleio_background(void); void bleio_reset(void); typedef struct { diff --git a/ports/nrf/supervisor/bluetooth.c b/ports/nrf/supervisor/bluetooth.c new file mode 100644 index 0000000000..8d89d62723 --- /dev/null +++ b/ports/nrf/supervisor/bluetooth.c @@ -0,0 +1,81 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "supervisor/shared/bluetooth.h" +#include "supervisor/bluetooth.h" + +// This happens in an interrupt so we need to be quick. +bool supervisor_bluetooth_hook(ble_evt_t *ble_evt) { +#if CIRCUITPY_BLE_FILE_SERVICE + // Catch writes to filename or contents. Length is read-only. + + bool done = false; + switch (ble_evt->header.evt_id) { + case BLE_GAP_EVT_CONNECTED: + // We run our background task even if it wasn't us connected to because we may want to + // advertise if the user code stopped advertising. + run_ble_background = true; + break; + case BLE_GAP_EVT_DISCONNECTED: + run_ble_background = true; + break; + case BLE_GATTS_EVT_WRITE: { + // A client wrote to a characteristic. + + ble_gatts_evt_write_t *evt_write = &ble_evt->evt.gatts_evt.params.write; + // Event handle must match the handle for my characteristic. + if (evt_write->handle == supervisor_ble_contents_characteristic.handle) { + // Handle events + //write_to_ringbuf(self, evt_write->data, evt_write->len); + // First packet includes a uint16_t le for length at the start. + uint16_t current_length = ((uint16_t*) current_command)[0]; + memcpy(((uint8_t*) current_command) + current_offset, evt_write->data, evt_write->len); + current_offset += evt_write->len; + current_length = ((uint16_t*) current_command)[0]; + if (current_offset == current_length) { + run_ble_background = true; + done = true; + } + } else if (evt_write->handle == supervisor_ble_filename_characteristic.handle) { + new_filename = true; + run_ble_background = true; + done = true; + } else { + return done; + } + break; + } + + default: + // For debugging. + // mp_printf(&mp_plat_print, "Unhandled peripheral event: 0x%04x\n", ble_evt->header.evt_id); + break; + } + return done; +#else + return false; +#endif +} diff --git a/ports/nrf/supervisor/bluetooth.h b/ports/nrf/supervisor/bluetooth.h new file mode 100644 index 0000000000..425de07e4d --- /dev/null +++ b/ports/nrf/supervisor/bluetooth.h @@ -0,0 +1,36 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_NRF_SUPERVISOR_BLUETOOTH_H +#define MICROPY_INCLUDED_NRF_SUPERVISOR_BLUETOOTH_H + +#include + +#include "ble.h" + +bool supervisor_bluetooth_hook(ble_evt_t *ble_evt); + +#endif // MICROPY_INCLUDED_NRF_SUPERVISOR_BLUETOOTH_H diff --git a/ports/stm/boards/espruino_pico/mpconfigboard.mk b/ports/stm/boards/espruino_pico/mpconfigboard.mk index 201237c9d6..b1b023dd58 100644 --- a/ports/stm/boards/espruino_pico/mpconfigboard.mk +++ b/ports/stm/boards/espruino_pico/mpconfigboard.mk @@ -10,7 +10,8 @@ MCU_VARIANT = STM32F401xE MCU_PACKAGE = UFQFPN48 LD_COMMON = boards/common_default.ld -LD_FILE = boards/STM32F401xd_fs.ld # use for internal flash +# use for internal flash +LD_FILE = boards/STM32F401xd_fs.ld # Disable ulab as we're nearly out of space on this board due to # INTERNAL_FLASH_FILESYSTEM. It can probably be reenabled if we enable diff --git a/ports/stm/boards/feather_stm32f405_express/mpconfigboard.mk b/ports/stm/boards/feather_stm32f405_express/mpconfigboard.mk index 2b2c0d6db5..4d0bd4598d 100644 --- a/ports/stm/boards/feather_stm32f405_express/mpconfigboard.mk +++ b/ports/stm/boards/feather_stm32f405_express/mpconfigboard.mk @@ -13,5 +13,6 @@ MCU_PACKAGE = LQFP64 LD_COMMON = boards/common_default.ld LD_DEFAULT = boards/STM32F405_default.ld -LD_BOOT = boards/STM32F405_boot.ld # UF2 boot option +# UF2 boot option +LD_BOOT = boards/STM32F405_boot.ld UF2_OFFSET = 0x8010000 diff --git a/ports/stm/boards/meowbit_v121/board.c b/ports/stm/boards/meowbit_v121/board.c index 812a8c208c..b74f135165 100644 --- a/ports/stm/boards/meowbit_v121/board.c +++ b/ports/stm/boards/meowbit_v121/board.c @@ -106,7 +106,7 @@ void board_init(void) { &pin_PB03, NO_BRIGHTNESS_COMMAND, 1.0f, // brightness (ignored) - true, // auto_brightness + false, // auto_brightness false, // single_byte_bounds false, // data_as_commands true, // auto_refresh diff --git a/ports/stm/boards/meowbit_v121/mpconfigboard.h b/ports/stm/boards/meowbit_v121/mpconfigboard.h index 106f25b15c..be9f2a75fb 100644 --- a/ports/stm/boards/meowbit_v121/mpconfigboard.h +++ b/ports/stm/boards/meowbit_v121/mpconfigboard.h @@ -36,8 +36,7 @@ #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000) #define HSE_VALUE ((uint32_t)12000000U) -#define LSE_VALUE ((uint32_t)32000U) -#define BOARD_HAS_LOW_SPEED_CRYSTAL (1) +#define BOARD_HAS_LOW_SPEED_CRYSTAL (0) #define BOARD_NO_VBUS_SENSE (1) #define BOARD_VTOR_DEFER (1) //Leave VTOR relocation to bootloader diff --git a/ports/stm/boards/meowbit_v121/mpconfigboard.mk b/ports/stm/boards/meowbit_v121/mpconfigboard.mk index 852836ef8f..16ffb2022a 100644 --- a/ports/stm/boards/meowbit_v121/mpconfigboard.mk +++ b/ports/stm/boards/meowbit_v121/mpconfigboard.mk @@ -18,4 +18,5 @@ OPTIMIZATION_FLAGS = -Os LD_COMMON = boards/common_default.ld LD_FILE = boards/STM32F401xe_boot.ld -# LD_FILE = boards/STM32F401xe_fs.ld # use for internal flash +# For debugging - also comment BOOTLOADER_OFFSET and BOARD_VTOR_DEFER +# LD_FILE = boards/STM32F401xe_fs.ld diff --git a/ports/stm/common-hal/os/__init__.c b/ports/stm/common-hal/os/__init__.c index 84deb81759..8da7243a30 100644 --- a/ports/stm/common-hal/os/__init__.c +++ b/ports/stm/common-hal/os/__init__.c @@ -72,16 +72,20 @@ bool common_hal_os_urandom(uint8_t *buffer, uint32_t length) { if (HAL_RNG_Init(&handle) != HAL_OK) mp_raise_ValueError(translate("RNG Init Error")); //Assign bytes - for (uint i = 0; i < length; i++) { - uint32_t temp; + uint32_t i = 0; + while (i < length) { + uint32_t new_random; uint32_t start = HAL_GetTick(); //the HAL function has a timeout, but it isn't long enough, and isn't adjustable while(!(__HAL_RNG_GET_FLAG(&handle,RNG_FLAG_DRDY)) && ((HAL_GetTick() - start) < RNG_TIMEOUT)); - // - if (HAL_RNG_GenerateRandomNumber(&handle, &temp) != HAL_OK) { + if (HAL_RNG_GenerateRandomNumber(&handle, &new_random) != HAL_OK) { mp_raise_ValueError(translate("Random number generation error")); } - *buffer = (uint8_t)temp; + for (int j = 0; j < 4 && i < length; j++) { + buffer[i] = new_random & 0xff; + i++; + new_random >>= 8; + } } //shut down the peripheral diff --git a/ports/stm/common-hal/pwmio/PWMOut.c b/ports/stm/common-hal/pwmio/PWMOut.c index 5427a39c74..85427185e5 100644 --- a/ports/stm/common-hal/pwmio/PWMOut.c +++ b/ports/stm/common-hal/pwmio/PWMOut.c @@ -239,13 +239,14 @@ void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t* self) { HAL_TIM_PWM_Stop(&self->handle, self->channel); } reset_pin_number(self->tim->pin->port,self->tim->pin->number); - self->tim = NULL; //if reserved timer has no active channels, we can disable it if (!reserved_tim[self->tim->tim_index - 1]) { tim_frequencies[self->tim->tim_index - 1] = 0x00; stm_peripherals_timer_free(self->handle.Instance); } + + self->tim = NULL; } void common_hal_pwmio_pwmout_set_duty_cycle(pwmio_pwmout_obj_t* self, uint16_t duty) { diff --git a/ports/stm/mpconfigport.mk b/ports/stm/mpconfigport.mk index 19f9ffa44c..b827aa48b9 100644 --- a/ports/stm/mpconfigport.mk +++ b/ports/stm/mpconfigport.mk @@ -7,6 +7,7 @@ ifeq ($(MCU_VARIANT),STM32F405xx) CIRCUITPY_FRAMEBUFFERIO ?= 1 CIRCUITPY_RGBMATRIX ?= 1 CIRCUITPY_SDIOIO ?= 1 + USB_NUM_EP = 4 endif ifeq ($(MCU_SERIES),F4) diff --git a/ports/stm/peripherals/stm32f4/clocks.c b/ports/stm/peripherals/stm32f4/clocks.c index 7a16812b36..c2d0a452a0 100644 --- a/ports/stm/peripherals/stm32f4/clocks.c +++ b/ports/stm/peripherals/stm32f4/clocks.c @@ -49,7 +49,6 @@ void stm32_peripherals_clocks_init(void) { RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_OscInitTypeDef RCC_OscInitStruct; RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; - bool lse_failure = false; // Set voltage scaling in accordance with system clock speed __HAL_RCC_PWR_CLK_ENABLE(); @@ -76,15 +75,9 @@ void stm32_peripherals_clocks_init(void) { #endif if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { - // Failure likely means a LSE issue - attempt to swap to LSI, and set to crash - RCC_OscInitStruct.LSEState = RCC_LSE_OFF; - RCC_OscInitStruct.OscillatorType |= RCC_OSCILLATORTYPE_LSI; - RCC_OscInitStruct.LSIState = RCC_LSI_ON; - if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { - // No HSE means no USB, so just fail forever - while(1); - } - lse_failure = true; + // Clock issues are too problematic to even attempt recovery. + // If you end up here, check whether your LSE settings match your board. + while(1); } // Configure bus clock sources and divisors @@ -113,8 +106,4 @@ void stm32_peripherals_clocks_init(void) { #endif HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); - - if (lse_failure) { - reset_into_safe_mode(HARD_CRASH); //TODO: make safe mode category CLOCK_FAULT? - } } diff --git a/ports/stm/peripherals/stm32f7/clocks.c b/ports/stm/peripherals/stm32f7/clocks.c index 93016f6828..f130887822 100644 --- a/ports/stm/peripherals/stm32f7/clocks.c +++ b/ports/stm/peripherals/stm32f7/clocks.c @@ -40,7 +40,6 @@ void stm32_peripherals_clocks_init(void) { RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_OscInitTypeDef RCC_OscInitStruct; RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; - bool lse_failure = false; // Configure LSE Drive HAL_PWR_EnableBkUpAccess(); @@ -68,15 +67,9 @@ void stm32_peripherals_clocks_init(void) { RCC_OscInitStruct.PLL.PLLQ = CPY_CLK_PLLQ; if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { - // Failure likely means a LSE issue - attempt to swap to LSI, and set to crash - RCC_OscInitStruct.LSEState = RCC_LSE_OFF; - RCC_OscInitStruct.OscillatorType |= RCC_OSCILLATORTYPE_LSI; - RCC_OscInitStruct.LSIState = RCC_LSI_ON; - if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { - // No HSE means no USB, so just fail forever - while(1); - } - lse_failure = true; + // Clock issues are too problematic to even attempt recovery. + // If you end up here, check whether your LSE settings match your board. + while(1); } /* Activate the OverDrive to reach the 216 MHz Frequency */ @@ -111,8 +104,4 @@ void stm32_peripherals_clocks_init(void) { #endif HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); - - if (lse_failure) { - reset_into_safe_mode(HARD_CRASH); //TODO: make safe mode category CLOCK_FAULT? - } } diff --git a/ports/stm/peripherals/stm32h7/clocks.c b/ports/stm/peripherals/stm32h7/clocks.c index 0e4e79f9f7..a088f78bf2 100644 --- a/ports/stm/peripherals/stm32h7/clocks.c +++ b/ports/stm/peripherals/stm32h7/clocks.c @@ -37,7 +37,6 @@ void stm32_peripherals_clocks_init(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; - bool lse_failure = false; // Set voltage scaling in accordance with system clock speed HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY); @@ -73,15 +72,9 @@ void stm32_peripherals_clocks_init(void) { RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE; RCC_OscInitStruct.PLL.PLLFRACN = 0; if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { - // Failure likely means a LSE issue - attempt to swap to LSI, and set to crash - RCC_OscInitStruct.LSEState = RCC_LSE_OFF; - RCC_OscInitStruct.OscillatorType |= RCC_OSCILLATORTYPE_LSI; - RCC_OscInitStruct.LSIState = RCC_LSI_ON; - if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { - // No HSE means no USB, so just fail forever - while(1); - } - lse_failure = true; + // Clock issues are too problematic to even attempt recovery. + // If you end up here, check whether your LSE settings match your board. + while(1); } // Configure bus clock sources and divisors @@ -116,8 +109,4 @@ void stm32_peripherals_clocks_init(void) { // Enable USB Voltage detector HAL_PWREx_EnableUSBVoltageDetector(); - - if (lse_failure) { - reset_into_safe_mode(HARD_CRASH); //TODO: make safe mode category CLOCK_FAULT? - } } diff --git a/py/builtinimport.c b/py/builtinimport.c index 597819f55c..47ffab5196 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -488,7 +488,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { // afterwards. gc_collect(); } - if (outer_module_obj != MP_OBJ_NULL) { + if (outer_module_obj != MP_OBJ_NULL && VERIFY_PTR(outer_module_obj) ) { qstr s = qstr_from_strn(mod_str + last, i - last); mp_store_attr(outer_module_obj, s, module_obj); // The above store can cause a dictionary rehash and new allocation. So, diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index ab7a3af60b..36524b2fbf 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -338,6 +338,15 @@ SRC_COMMON_HAL_ALL = \ watchdog/WatchDogTimer.c \ watchdog/__init__.c \ +ifeq ($(CIRCUITPY_BLEIO_HCI),1) +# Helper code for _bleio HCI. +SRC_C += \ + common-hal/_bleio/att.c \ + common-hal/_bleio/hci.c \ + +endif + + SRC_COMMON_HAL = $(filter $(SRC_PATTERNS), $(SRC_COMMON_HAL_ALL)) # These don't have corresponding files in each port but are still located in @@ -439,7 +448,7 @@ SRC_SHARED_MODULE_ALL = \ SRC_SHARED_MODULE = $(filter $(SRC_PATTERNS), $(SRC_SHARED_MODULE_ALL)) # Use the native touchio if requested. This flag is set conditionally in, say, mpconfigport.h. -# The presence of common-hal/touchio/* # does not imply it's available for all chips in a port, +# The presence of common-hal/touchio/* does not imply it's available for all chips in a port, # so there is an explicit flag. For example, SAMD21 touchio is native, but SAMD51 is not. ifeq ($(CIRCUITPY_TOUCHIO_USE_NATIVE),1) SRC_COMMON_HAL_ALL += \ @@ -450,6 +459,14 @@ SRC_SHARED_MODULE_ALL += \ touchio/TouchIn.c \ touchio/__init__.c endif + +# If supporting _bleio via HCI, make devices/ble_hci/common-hal/_bleio be includable, +# and use C source files in devices/ble_hci/common-hal. +ifeq ($(CIRCUITPY_BLEIO_HCI),1) +INC += -I$(TOP)/devices/ble_hci +DEVICES_MODULES += $(TOP)/devices/ble_hci +endif + ifeq ($(CIRCUITPY_AUDIOMP3),1) SRC_MOD += $(addprefix lib/mp3/src/, \ bitstream.c \ @@ -483,6 +500,11 @@ $(filter $(SRC_PATTERNS), \ displayio/display_core.c \ ) +SRC_COMMON_HAL_INTERNAL = \ +$(filter $(SRC_PATTERNS), \ + _bleio/ \ +) + ifeq ($(INTERNAL_LIBM),1) SRC_LIBM = \ $(addprefix lib/,\ diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index 76b91defae..d144f0ba84 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -185,6 +185,7 @@ typedef long mp_off_t; // Turning off FULL_BUILD removes some functionality to reduce flash size on tiny SAMD21s #define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (CIRCUITPY_FULL_BUILD) #define MICROPY_CPYTHON_COMPAT (CIRCUITPY_FULL_BUILD) +#define MICROPY_PY_BUILTINS_POW3 (CIRCUITPY_FULL_BUILD) #define MICROPY_COMP_FSTRING_LITERAL (MICROPY_CPYTHON_COMPAT) #define MICROPY_MODULE_WEAK_LINKS (CIRCUITPY_FULL_BUILD) #define MICROPY_PY_ALL_SPECIAL_METHODS (CIRCUITPY_FULL_BUILD) diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 379c3850e3..90e8b5fdea 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -80,6 +80,10 @@ CFLAGS += -DCIRCUITPY_BITBANGIO=$(CIRCUITPY_BITBANGIO) CIRCUITPY_BLEIO ?= 0 CFLAGS += -DCIRCUITPY_BLEIO=$(CIRCUITPY_BLEIO) +# _bleio can be supported on most any board via HCI +CIRCUITPY_BLEIO_HCI ?= 0 +CFLAGS += -DCIRCUITPY_BLEIO_HCI=$(CIRCUITPY_BLEIO_HCI) + CIRCUITPY_BOARD ?= 1 CFLAGS += -DCIRCUITPY_BOARD=$(CIRCUITPY_BOARD) diff --git a/py/misc.h b/py/misc.h index 944c0a7164..6ed256e705 100644 --- a/py/misc.h +++ b/py/misc.h @@ -120,6 +120,8 @@ size_t m_get_peak_bytes_allocated(void); // align ptr to the nearest multiple of "alignment" #define MP_ALIGN(ptr, alignment) (void*)(((uintptr_t)(ptr) + ((alignment) - 1)) & ~((alignment) - 1)) +#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER)) + /** unichar / UTF-8 *********************************************/ #if MICROPY_PY_BUILTINS_STR_UNICODE diff --git a/py/mkrules.mk b/py/mkrules.mk index 13a73b90e6..0b3ecc0e17 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -42,7 +42,7 @@ $(Q)$(CC) $(CFLAGS) -c -MD -o $@ $< $(RM) -f $(@:.o=.d) endef -vpath %.c . $(TOP) $(USER_C_MODULES) +vpath %.c . $(TOP) $(USER_C_MODULES) $(DEVICES_MODULES) $(BUILD)/%.o: %.c $(call compile_c) @@ -56,8 +56,7 @@ $(BUILD)/%.o: %.c QSTR_GEN_EXTRA_CFLAGS += -I$(BUILD)/tmp -vpath %.c . $(TOP) $(USER_C_MODULES) - +vpath %.c . $(TOP) $(USER_C_MODULES) $(DEVICES_MODULES) $(BUILD)/%.pp: %.c $(STEPECHO) "PreProcess $<" $(Q)$(CC) $(CFLAGS) -E -Wp,-C,-dD,-dI -o $@ $< diff --git a/py/mpz.h b/py/mpz.h index e412f5cce1..ade04a4f7c 100644 --- a/py/mpz.h +++ b/py/mpz.h @@ -135,6 +135,9 @@ void mpz_xor_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs); void mpz_divmod_inpl(mpz_t *dest_quo, mpz_t *dest_rem, const mpz_t *lhs, const mpz_t *rhs); static inline size_t mpz_max_num_bits(const mpz_t *z) { return z->len * MPZ_DIG_SIZE; } +static inline size_t mpz_num_bits(const mpz_t *z) { + size_t last_bits = (8 * (sizeof(long) - sizeof(mpz_dig_t))) - __builtin_clzl(z->dig[z->len-1]); + return z->len * MPZ_DIG_SIZE + last_bits; } mp_int_t mpz_hash(const mpz_t *z); bool mpz_as_int_checked(const mpz_t *z, mp_int_t *value); bool mpz_as_uint_checked(const mpz_t *z, mp_uint_t *value); diff --git a/py/obj.c b/py/obj.c index 0cff2f1a4b..9dc0cf4749 100644 --- a/py/obj.c +++ b/py/obj.c @@ -67,6 +67,8 @@ void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t #ifdef RUN_BACKGROUND_TASKS RUN_BACKGROUND_TASKS; #endif + mp_handle_pending(); + #ifndef NDEBUG if (o_in == MP_OBJ_NULL) { mp_print_str(print, "(nil)"); diff --git a/py/obj.h b/py/obj.h index e9d867f77b..943e1a389b 100644 --- a/py/obj.h +++ b/py/obj.h @@ -303,7 +303,7 @@ typedef struct _mp_rom_obj_t { mp_const_obj_t o; } mp_rom_obj_t; (mp_obj_t)&mp_const_none_obj, \ (mp_obj_t)&mp_const_none_obj}, } -// These macros are used to define constant map/dict objects +// These macros are used to define constant or mutable map/dict objects // You can put "static" in front of the definition to make it local #define MP_DEFINE_CONST_MAP(map_name, table_name) \ @@ -329,6 +329,29 @@ typedef struct _mp_rom_obj_t { mp_const_obj_t o; } mp_rom_obj_t; }, \ } +#define MP_DEFINE_MUTABLE_MAP(map_name, table_name) \ + mp_map_t map_name = { \ + .all_keys_are_qstrs = 1, \ + .is_fixed = 1, \ + .is_ordered = 1, \ + .used = MP_ARRAY_SIZE(table_name), \ + .alloc = MP_ARRAY_SIZE(table_name), \ + .table = table_name, \ + } + +#define MP_DEFINE_MUTABLE_DICT(dict_name, table_name) \ + mp_obj_dict_t dict_name = { \ + .base = {&mp_type_dict}, \ + .map = { \ + .all_keys_are_qstrs = 1, \ + .is_fixed = 1, \ + .is_ordered = 1, \ + .used = MP_ARRAY_SIZE(table_name), \ + .alloc = MP_ARRAY_SIZE(table_name), \ + .table = table_name, \ + }, \ + } + // These macros are used to declare and define constant staticmethond and classmethod objects // You can put "static" in front of the definitions to make them local diff --git a/py/objint.c b/py/objint.c index b12bb39952..5a33ccbc04 100644 --- a/py/objint.c +++ b/py/objint.c @@ -457,6 +457,28 @@ mp_obj_t mp_obj_int_binary_op_extra_cases(mp_binary_op_t op, mp_obj_t lhs_in, mp return MP_OBJ_NULL; // op not supported } +#if MICROPY_CPYTHON_COMPAT +STATIC mp_obj_t int_bit_length(mp_obj_t self_in) { + #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE + if (!MP_OBJ_IS_SMALL_INT(self_in)) { + return mp_obj_int_bit_length_impl(self_in); + } + else + #endif + { + mp_int_t int_val = MP_OBJ_SMALL_INT_VALUE(self_in); + mp_uint_t value = + (int_val == 0) ? 0 : + (int_val == MP_SMALL_INT_MIN) ? 8 * sizeof(mp_int_t) : + (int_val < 0) ? 8 * sizeof(long) - __builtin_clzl(-int_val) : + 8 * sizeof(long) - __builtin_clzl(int_val); + return mp_obj_new_int_from_uint(value); + } + +} +MP_DEFINE_CONST_FUN_OBJ_1(int_bit_length_obj, int_bit_length); +#endif + // this is a classmethod STATIC mp_obj_t int_from_bytes(size_t n_args, const mp_obj_t *args) { // TODO: Support signed param (assumes signed=False at the moment) @@ -537,6 +559,9 @@ STATIC mp_obj_t int_to_bytes(size_t n_args, const mp_obj_t *pos_args, mp_map_t * STATIC MP_DEFINE_CONST_FUN_OBJ_KW(int_to_bytes_obj, 3, int_to_bytes); STATIC const mp_rom_map_elem_t int_locals_dict_table[] = { +#if MICROPY_CPYTHON_COMPAT + { MP_ROM_QSTR(MP_QSTR_bit_length), MP_ROM_PTR(&int_bit_length_obj) }, +#endif { MP_ROM_QSTR(MP_QSTR_from_bytes), MP_ROM_PTR(&int_from_bytes_obj) }, { MP_ROM_QSTR(MP_QSTR_to_bytes), MP_ROM_PTR(&int_to_bytes_obj) }, }; diff --git a/py/objint.h b/py/objint.h index bba9ff50a5..68997ced27 100644 --- a/py/objint.h +++ b/py/objint.h @@ -60,6 +60,7 @@ void mp_obj_int_buffer_overflow_check(mp_obj_t self_in, size_t nbytes, bool is_s void mp_small_int_buffer_overflow_check(mp_int_t val, size_t nbytes, bool is_signed); mp_int_t mp_obj_int_hash(mp_obj_t self_in); +mp_obj_t mp_obj_int_bit_length_impl(mp_obj_t self_in); mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf); void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf); int mp_obj_int_sign(mp_obj_t self_in); diff --git a/py/objint_longlong.c b/py/objint_longlong.c index 1890496305..0a65098c78 100644 --- a/py/objint_longlong.c +++ b/py/objint_longlong.c @@ -45,6 +45,17 @@ const mp_obj_int_t mp_maxsize_obj = {{&mp_type_int}, MP_SSIZE_MAX}; #endif +mp_obj_t mp_obj_int_bit_length_impl(mp_obj_t self_in) { + assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int)); + mp_obj_int_t *self = self_in; + long long val = self->val; + return MP_OBJ_NEW_SMALL_INT( + (val == 0) ? 0 : + (val == MP_SMALL_INT_MIN) ? 8 * sizeof(long long) : + (val < 0) ? 8 * sizeof(long long) - __builtin_clzll(-val) : + 8 * sizeof(long long) - __builtin_clzll(val)); +} + mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf) { int delta = 1; if (!big_endian) { diff --git a/py/objint_mpz.c b/py/objint_mpz.c index 90060114ed..d32fdfbe8d 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -107,6 +107,12 @@ char *mp_obj_int_formatted_impl(char **buf, size_t *buf_size, size_t *fmt_size, return str; } +mp_obj_t mp_obj_int_bit_length_impl(mp_obj_t self_in) { + assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int)); + mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); + return MP_OBJ_NEW_SMALL_INT(mpz_num_bits(&self->mpz)); +} + mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf) { mp_obj_int_t *o = mp_obj_int_new_mpz(); mpz_set_from_bytes(&o->mpz, big_endian, len, buf); diff --git a/py/py.mk b/py/py.mk index c5073d0f02..49fb0acaf9 100644 --- a/py/py.mk +++ b/py/py.mk @@ -19,7 +19,7 @@ endif QSTR_GLOBAL_DEPENDENCIES += $(PY_SRC)/mpconfig.h mpconfigport.h # some code is performance bottleneck and compiled with other optimization options -CSUPEROPT = -O3 +_CSUPEROPT = -O3 # this sets the config file for FatFs CFLAGS_MOD += -DFFCONF_H=\"lib/oofatfs/ffconf.h\" diff --git a/shared-bindings/_bleio/Adapter.c b/shared-bindings/_bleio/Adapter.c index 3ffe65be3d..682177093d 100644 --- a/shared-bindings/_bleio/Adapter.c +++ b/shared-bindings/_bleio/Adapter.c @@ -48,29 +48,76 @@ #define WINDOW_DEFAULT (0.1f) //| class Adapter: -//| """BLE adapter -//| -//| The Adapter manages the discovery and connection to other nearby Bluetooth Low Energy devices. +//| """ +//| The BLE Adapter object manages the discovery and connection to other nearby Bluetooth Low Energy devices. //| This part of the Bluetooth Low Energy Specification is known as Generic Access Profile (GAP). //| //| Discovery of other devices happens during a scanning process that listens for small packets of //| information, known as advertisements, that are broadcast unencrypted. The advertising packets //| have two different uses. The first is to broadcast a small piece of data to anyone who cares and -//| and nothing more. These are known as Beacons. The second class of advertisement is to promote +//| and nothing more. These are known as beacons. The second class of advertisement is to promote //| additional functionality available after the devices establish a connection. For example, a -//| BLE keyboard may advertise that it can provide key information, but not what the key info is. +//| BLE heart rate monitor would advertise that it provides the standard BLE Heart Rate Service. //| -//| The built-in BLE adapter can do both parts of this process: it can scan for other device +//| The Adapter can do both parts of this process: it can scan for other device //| advertisements and it can advertise its own data. Furthermore, Adapters can accept incoming //| connections and also initiate connections.""" //| -//| def __init__(self) -> None: -//| """You cannot create an instance of `_bleio.Adapter`. -//| Use `_bleio.adapter` to access the sole instance available.""" +//| def __init__(self, *, uart: busio.UART, rts: digitalio.DigitalInOut, cts: digitalio.DigitalInOut) -> None: +//| """On boards that do not have native BLE, you can use an HCI co-processor. +//| Pass the uart and pins used to communicate with the co-processor, such as an Adafruit AirLift. +//| The co-processor must have been reset and put into BLE mode beforehand +//| by the appropriate pin manipulation. +//| The ``uart``, ``rts``, and ``cts`` objects are used to +//| communicate with the HCI co-processor in HCI mode. +//| The `Adapter` object is enabled during this call. +//| +//| After instantiating an Adapter, call `_bleio.set_adapter()` to set `_bleio.adapter` +//| +//| On boards with native BLE, you cannot create an instance of `_bleio.Adapter`; +//| this constructor will raise `NotImplementedError`. +//| Use `_bleio.adapter` to access the sole instance already available. +//| """ //| ... //| +STATIC mp_obj_t bleio_adapter_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { +#if CIRCUITPY_BLEIO_HCI + bleio_adapter_obj_t *self = common_hal_bleio_allocate_adapter_or_raise(); + enum { ARG_uart, ARG_rts, ARG_cts }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_uart, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_rts, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_cts, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + busio_uart_obj_t *uart = args[ARG_uart].u_obj; + if (!MP_OBJ_IS_TYPE(uart, &busio_uart_type)) { + mp_raise_ValueError(translate("Expected a UART")); + } + + digitalio_digitalinout_obj_t *rts = args[ARG_rts].u_obj; + digitalio_digitalinout_obj_t *cts = args[ARG_cts].u_obj; + if (!MP_OBJ_IS_TYPE(rts, &digitalio_digitalinout_type) || + !MP_OBJ_IS_TYPE(cts, &digitalio_digitalinout_type)) { + mp_raise_ValueError(translate("Expected a DigitalInOut")); + } + + // Will enable the adapter. + common_hal_bleio_adapter_construct_hci_uart(self, uart, rts, cts); + + return MP_OBJ_FROM_PTR(self); +#else + mp_raise_NotImplementedError(translate("Cannot create a new Adapter; use _bleio.adapter;")); + return mp_const_none; +#endif // CIRCUITPY_BLEIO_HCI +} + +//| //| enabled: bool //| """State of the BLE adapter.""" //| @@ -362,7 +409,7 @@ const mp_obj_property_t bleio_adapter_connections_obj = { //| """Attempts a connection to the device with the given address. //| //| :param Address address: The address of the peripheral to connect to -//| :param float timeout: Try to connect for timeout seconds.""" +//| :param float/int timeout: Try to connect for timeout seconds.""" //| ... //| STATIC mp_obj_t bleio_adapter_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -426,5 +473,6 @@ STATIC MP_DEFINE_CONST_DICT(bleio_adapter_locals_dict, bleio_adapter_locals_dict const mp_obj_type_t bleio_adapter_type = { .base = { &mp_type_type }, .name = MP_QSTR_Adapter, + .make_new = bleio_adapter_make_new, .locals_dict = (mp_obj_t)&bleio_adapter_locals_dict, }; diff --git a/shared-bindings/_bleio/Adapter.h b/shared-bindings/_bleio/Adapter.h index c56dbb01cf..ac7e216d83 100644 --- a/shared-bindings/_bleio/Adapter.h +++ b/shared-bindings/_bleio/Adapter.h @@ -37,6 +37,10 @@ extern const mp_obj_type_t bleio_adapter_type; +#if CIRCUITPY_BLEIO_HCI +void common_hal_bleio_adapter_construct_hci_uart(bleio_adapter_obj_t *self, busio_uart_obj_t *uart, digitalio_digitalinout_obj_t *rts, digitalio_digitalinout_obj_t *cts); +#endif // CIRCUITPY_BLEIO_HCI + extern bool common_hal_bleio_adapter_get_advertising(bleio_adapter_obj_t *self); extern bool common_hal_bleio_adapter_get_enabled(bleio_adapter_obj_t *self); extern void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enabled); diff --git a/shared-bindings/_bleio/Characteristic.c b/shared-bindings/_bleio/Characteristic.c index dbbacb7d57..5e384a44ca 100644 --- a/shared-bindings/_bleio/Characteristic.c +++ b/shared-bindings/_bleio/Characteristic.c @@ -109,11 +109,14 @@ STATIC mp_obj_t bleio_characteristic_add_to_service(size_t n_args, const mp_obj_ const bleio_attribute_security_mode_t write_perm = args[ARG_write_perm].u_int; common_hal_bleio_attribute_security_mode_check_valid(write_perm); - const mp_int_t max_length = args[ARG_max_length].u_int; + const mp_int_t max_length_int = args[ARG_max_length].u_int; + if (max_length_int <= 0) { + mp_raise_ValueError(translate("max_length must be > 0")); + } + const size_t max_length = (size_t) max_length_int; const bool fixed_length = args[ARG_fixed_length].u_bool; mp_obj_t initial_value = args[ARG_initial_value].u_obj; - // Length will be validated in common_hal. mp_buffer_info_t initial_value_bufinfo; if (initial_value == mp_const_none) { if (fixed_length && max_length > 0) { @@ -122,7 +125,12 @@ STATIC mp_obj_t bleio_characteristic_add_to_service(size_t n_args, const mp_obj_ initial_value = mp_const_empty_bytes; } } + mp_get_buffer_raise(initial_value, &initial_value_bufinfo, MP_BUFFER_READ); + if (initial_value_bufinfo.len > max_length || + (fixed_length && initial_value_bufinfo.len != max_length)) { + mp_raise_ValueError(translate("initial_value length is wrong")); + } bleio_characteristic_obj_t *characteristic = m_new_obj(bleio_characteristic_obj_t); characteristic->base.type = &bleio_characteristic_type; @@ -212,26 +220,14 @@ const mp_obj_property_t bleio_characteristic_value_obj = { }; //| descriptors: Descriptor -//| """A tuple of :py:class:`Descriptor` that describe this characteristic. (read-only)""" +//| """A tuple of :py:class:`Descriptor` objects related to this characteristic. (read-only)""" //| STATIC mp_obj_t bleio_characteristic_get_descriptors(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); // Return list as a tuple so user won't be able to change it. - bleio_descriptor_obj_t *descriptors = common_hal_bleio_characteristic_get_descriptor_list(self); - bleio_descriptor_obj_t *head = descriptors; - size_t len = 0; - while (head != NULL) { - len++; - head = head->next; - } - mp_obj_tuple_t * t = MP_OBJ_TO_PTR(mp_obj_new_tuple(len, NULL)); - head = descriptors; - for (size_t i = len - 1; i >= 0; i--) { - t->items[i] = MP_OBJ_FROM_PTR(head); - head = head->next; - } - return MP_OBJ_FROM_PTR(t); + return MP_OBJ_FROM_PTR(common_hal_bleio_characteristic_get_descriptors(self)); } + STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_descriptors_obj, bleio_characteristic_get_descriptors); const mp_obj_property_t bleio_characteristic_descriptors_obj = { diff --git a/shared-bindings/_bleio/Characteristic.h b/shared-bindings/_bleio/Characteristic.h index c4356fd4b9..e28d61e1f0 100644 --- a/shared-bindings/_bleio/Characteristic.h +++ b/shared-bindings/_bleio/Characteristic.h @@ -36,14 +36,14 @@ extern const mp_obj_type_t bleio_characteristic_type; -extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo); -extern size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self, uint8_t* buf, size_t len); -extern void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo); extern bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties(bleio_characteristic_obj_t *self); -extern bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characteristic_obj_t *self); -extern bleio_descriptor_obj_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self); +extern mp_obj_tuple_t *common_hal_bleio_characteristic_get_descriptors(bleio_characteristic_obj_t *self); extern bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_characteristic_obj_t *self); +extern bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characteristic_obj_t *self); +extern size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self, uint8_t* buf, size_t len); extern void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *self, bleio_descriptor_obj_t *descriptor); +extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo); extern void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate); +extern void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CHARACTERISTIC_H diff --git a/shared-bindings/_bleio/Connection.c b/shared-bindings/_bleio/Connection.c index 5d1b63bdd6..b5eeaa9069 100644 --- a/shared-bindings/_bleio/Connection.c +++ b/shared-bindings/_bleio/Connection.c @@ -31,7 +31,6 @@ #include #include -#include "ble_drv.h" #include "py/objarray.h" #include "py/objproperty.h" #include "py/objstr.h" diff --git a/shared-bindings/_bleio/Descriptor.c b/shared-bindings/_bleio/Descriptor.c index 97422f1630..c313007c6d 100644 --- a/shared-bindings/_bleio/Descriptor.c +++ b/shared-bindings/_bleio/Descriptor.c @@ -100,11 +100,14 @@ STATIC mp_obj_t bleio_descriptor_add_to_characteristic(size_t n_args, const mp_o const bleio_attribute_security_mode_t write_perm = args[ARG_write_perm].u_int; common_hal_bleio_attribute_security_mode_check_valid(write_perm); - const mp_int_t max_length = args[ARG_max_length].u_int; + const mp_int_t max_length_int = args[ARG_max_length].u_int; + if (max_length_int <= 0) { + mp_raise_ValueError(translate("max_length must be > 0")); + } + const size_t max_length = (size_t) max_length_int; const bool fixed_length = args[ARG_fixed_length].u_bool; mp_obj_t initial_value = args[ARG_initial_value].u_obj; - // Length will be validated in common_hal. mp_buffer_info_t initial_value_bufinfo; if (initial_value == mp_const_none) { if (fixed_length && max_length > 0) { @@ -114,6 +117,10 @@ STATIC mp_obj_t bleio_descriptor_add_to_characteristic(size_t n_args, const mp_o } } mp_get_buffer_raise(initial_value, &initial_value_bufinfo, MP_BUFFER_READ); + if (initial_value_bufinfo.len > max_length || + (fixed_length && initial_value_bufinfo.len != max_length)) { + mp_raise_ValueError(translate("initial_value length is wrong")); + } bleio_descriptor_obj_t *descriptor = m_new_obj(bleio_descriptor_obj_t); descriptor->base.type = &bleio_descriptor_type; diff --git a/shared-bindings/_bleio/Service.c b/shared-bindings/_bleio/Service.c index f410b1798e..2ddf1a7126 100644 --- a/shared-bindings/_bleio/Service.c +++ b/shared-bindings/_bleio/Service.c @@ -79,9 +79,7 @@ STATIC mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args, //| STATIC mp_obj_t bleio_service_get_characteristics(mp_obj_t self_in) { bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); - // Return list as a tuple so user won't be able to change it. - mp_obj_list_t *char_list = common_hal_bleio_service_get_characteristic_list(self); - return mp_obj_new_tuple(char_list->len, char_list->items); + return MP_OBJ_FROM_PTR(common_hal_bleio_service_get_characteristics(self)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_service_get_characteristics_obj, bleio_service_get_characteristics); @@ -151,7 +149,7 @@ STATIC const mp_rom_map_elem_t bleio_service_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_characteristics), MP_ROM_PTR(&bleio_service_characteristics_obj) }, { MP_ROM_QSTR(MP_QSTR_secondary), MP_ROM_PTR(&bleio_service_secondary_obj) }, { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_service_uuid_obj) }, - { MP_ROM_QSTR(MP_QSTR_remote), MP_ROM_PTR(&bleio_service_remote_obj) }, + { MP_ROM_QSTR(MP_QSTR_remote), MP_ROM_PTR(&bleio_service_remote_obj) }, }; STATIC MP_DEFINE_CONST_DICT(bleio_service_locals_dict, bleio_service_locals_dict_table); @@ -173,21 +171,3 @@ const mp_obj_type_t bleio_service_type = { .print = bleio_service_print, .locals_dict = (mp_obj_dict_t*)&bleio_service_locals_dict }; - -// Helper for classes that store lists of services. -mp_obj_tuple_t* service_linked_list_to_tuple(bleio_service_obj_t * services) { - // Return list as a tuple so user won't be able to change it. - bleio_service_obj_t *head = services; - size_t len = 0; - while (head != NULL) { - len++; - head = head->next; - } - mp_obj_tuple_t * t = MP_OBJ_TO_PTR(mp_obj_new_tuple(len, NULL)); - head = services; - for (int32_t i = len - 1; i >= 0; i--) { - t->items[i] = MP_OBJ_FROM_PTR(head); - head = head->next; - } - return t; -} diff --git a/shared-bindings/_bleio/Service.h b/shared-bindings/_bleio/Service.h index 3af427f950..44d11f60d4 100644 --- a/shared-bindings/_bleio/Service.h +++ b/shared-bindings/_bleio/Service.h @@ -41,11 +41,9 @@ extern uint32_t _common_hal_bleio_service_construct(bleio_service_obj_t *self, b extern void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary); extern void common_hal_bleio_service_from_remote_service(bleio_service_obj_t *self, bleio_connection_obj_t* connection, bleio_uuid_obj_t *uuid, bool is_secondary); extern bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self); -extern mp_obj_list_t *common_hal_bleio_service_get_characteristic_list(bleio_service_obj_t *self); +extern mp_obj_tuple_t *common_hal_bleio_service_get_characteristics(bleio_service_obj_t *self); extern bool common_hal_bleio_service_get_is_remote(bleio_service_obj_t *self); extern bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self); extern void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *initial_value_bufinfo); -mp_obj_tuple_t* service_linked_list_to_tuple(bleio_service_obj_t * services); - #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H diff --git a/shared-bindings/_bleio/UUID.c b/shared-bindings/_bleio/UUID.c index 18eda0b33b..fe045f3853 100644 --- a/shared-bindings/_bleio/UUID.c +++ b/shared-bindings/_bleio/UUID.c @@ -283,7 +283,7 @@ void bleio_uuid_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t mp_printf(print, "UUID(0x%04x)", common_hal_bleio_uuid_get_uuid16(self)); } else { uint8_t uuid128[16]; - (void) common_hal_bleio_uuid_get_uuid128(self, uuid128); + common_hal_bleio_uuid_get_uuid128(self, uuid128); mp_printf(print, "UUID('" "%02x%02x%02x%02x-" "%02x%02x-" diff --git a/shared-bindings/_bleio/UUID.h b/shared-bindings/_bleio/UUID.h index 1490737a71..b10cce67f3 100644 --- a/shared-bindings/_bleio/UUID.h +++ b/shared-bindings/_bleio/UUID.h @@ -34,9 +34,9 @@ void bleio_uuid_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t extern const mp_obj_type_t bleio_uuid_type; -extern void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, mp_int_t uuid16, const uint8_t uuid128[]); +extern void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, mp_int_t uuid16, const uint8_t uuid128[16]); extern uint32_t common_hal_bleio_uuid_get_uuid16(bleio_uuid_obj_t *self); -extern bool common_hal_bleio_uuid_get_uuid128(bleio_uuid_obj_t *self, uint8_t uuid128[16]); +extern void common_hal_bleio_uuid_get_uuid128(bleio_uuid_obj_t *self, uint8_t uuid128[16]); extern uint32_t common_hal_bleio_uuid_get_size(bleio_uuid_obj_t *self); void common_hal_bleio_uuid_pack_into(bleio_uuid_obj_t *self, uint8_t* buf); diff --git a/shared-bindings/_bleio/__init__.c b/shared-bindings/_bleio/__init__.c index ee9c4bf4a6..3d9084dd53 100644 --- a/shared-bindings/_bleio/__init__.c +++ b/shared-bindings/_bleio/__init__.c @@ -108,43 +108,95 @@ NORETURN void mp_raise_bleio_SecurityError(const compressed_string_t* fmt, ...) // Called when _bleio is imported. STATIC mp_obj_t bleio___init__(void) { +// HCI cannot be enabled on import, because we need to setup the HCI adapter first. +#if !CIRCUITPY_BLEIO_HCI common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, true); +#endif return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(bleio___init___obj, bleio___init__); +// Need a forward reference due to mutual references. +#if CIRCUITPY_BLEIO_HCI +STATIC mp_obj_dict_t bleio_module_globals; +#endif + +//| def set_adapter(adapter: Optional[_bleio.Adapter]) -> None: +//| """Set the adapter to use for BLE, such as when using an HCI adapter. +//| Raises `NotImplementedError` when the adapter is a singleton and cannot be set.""" +//| ... +//| +mp_obj_t bleio_set_adapter(mp_obj_t adapter_obj) { +#if CIRCUITPY_BLEIO_HCI + if (adapter_obj != mp_const_none && !MP_OBJ_IS_TYPE(adapter_obj, &bleio_adapter_type)) { + mp_raise_TypeError_varg(translate("Expected a %q"), bleio_adapter_type.name); + } + + // Equivalent of: + // bleio.adapter = adapter_obj + mp_map_elem_t *elem = mp_map_lookup(&bleio_module_globals.map, MP_ROM_QSTR(MP_QSTR_adapter), MP_MAP_LOOKUP); + if (elem) { + elem->value = adapter_obj; + } +#else + mp_raise_NotImplementedError(translate("Not settable")); +#endif + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(bleio_set_adapter_obj, bleio_set_adapter); + +#if CIRCUITPY_BLEIO_HCI +// Make the module dictionary be in RAM, so that _bleio.adapter can be set. +// Use a local macro to define how table entries should be converted. +#define OBJ_FROM_PTR MP_OBJ_FROM_PTR +STATIC mp_map_elem_t bleio_module_globals_table[] = { +#else +#define OBJ_FROM_PTR MP_ROM_PTR STATIC const mp_rom_map_elem_t bleio_module_globals_table[] = { +#endif // 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) }, - { MP_ROM_QSTR(MP_QSTR_Attribute), MP_ROM_PTR(&bleio_attribute_type) }, - { MP_ROM_QSTR(MP_QSTR_Connection), MP_ROM_PTR(&bleio_connection_type) }, - { MP_ROM_QSTR(MP_QSTR_Characteristic), MP_ROM_PTR(&bleio_characteristic_type) }, - { MP_ROM_QSTR(MP_QSTR_CharacteristicBuffer), MP_ROM_PTR(&bleio_characteristic_buffer_type) }, - { MP_ROM_QSTR(MP_QSTR_Descriptor), MP_ROM_PTR(&bleio_descriptor_type) }, - { MP_ROM_QSTR(MP_QSTR_PacketBuffer), MP_ROM_PTR(&bleio_packet_buffer_type) }, - { MP_ROM_QSTR(MP_QSTR_ScanEntry), MP_ROM_PTR(&bleio_scanentry_type) }, - { MP_ROM_QSTR(MP_QSTR_ScanResults), MP_ROM_PTR(&bleio_scanresults_type) }, - { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&bleio_service_type) }, - { MP_ROM_QSTR(MP_QSTR_UUID), MP_ROM_PTR(&bleio_uuid_type) }, + { MP_ROM_QSTR(MP_QSTR_Adapter), OBJ_FROM_PTR(&bleio_adapter_type) }, + { MP_ROM_QSTR(MP_QSTR_Address), OBJ_FROM_PTR(&bleio_address_type) }, + { MP_ROM_QSTR(MP_QSTR_Attribute), OBJ_FROM_PTR(&bleio_attribute_type) }, + { MP_ROM_QSTR(MP_QSTR_Connection), OBJ_FROM_PTR(&bleio_connection_type) }, + { MP_ROM_QSTR(MP_QSTR_Characteristic), OBJ_FROM_PTR(&bleio_characteristic_type) }, + { MP_ROM_QSTR(MP_QSTR_CharacteristicBuffer), OBJ_FROM_PTR(&bleio_characteristic_buffer_type) }, + { MP_ROM_QSTR(MP_QSTR_Descriptor), OBJ_FROM_PTR(&bleio_descriptor_type) }, + { MP_ROM_QSTR(MP_QSTR_PacketBuffer), OBJ_FROM_PTR(&bleio_packet_buffer_type) }, + { MP_ROM_QSTR(MP_QSTR_ScanEntry), OBJ_FROM_PTR(&bleio_scanentry_type) }, + { MP_ROM_QSTR(MP_QSTR_ScanResults), OBJ_FROM_PTR(&bleio_scanresults_type) }, + { MP_ROM_QSTR(MP_QSTR_Service), OBJ_FROM_PTR(&bleio_service_type) }, + { MP_ROM_QSTR(MP_QSTR_UUID), OBJ_FROM_PTR(&bleio_uuid_type) }, - // Properties +#if CIRCUITPY_BLEIO_HCI + // For HCI, _bleio.adapter is settable, and starts as None. + { MP_ROM_QSTR(MP_QSTR_adapter), mp_const_none }, + { MP_ROM_QSTR(MP_QSTR_set_adapter), (mp_obj_t) &bleio_set_adapter_obj }, +#else + // For non-HCI _bleio.adapter is a fixed singleton, and is not settable. + // _bleio.set_adapter will raise NotImplementedError. { MP_ROM_QSTR(MP_QSTR_adapter), MP_ROM_PTR(&common_hal_bleio_adapter_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_adapter), MP_ROM_PTR(&bleio_set_adapter_obj) }, +#endif // 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) }, + { MP_ROM_QSTR(MP_QSTR_BluetoothError), OBJ_FROM_PTR(&mp_type_bleio_BluetoothError) }, + { MP_ROM_QSTR(MP_QSTR_ConnectionError), OBJ_FROM_PTR(&mp_type_bleio_ConnectionError) }, + { MP_ROM_QSTR(MP_QSTR_RoleError), OBJ_FROM_PTR(&mp_type_bleio_RoleError) }, + { MP_ROM_QSTR(MP_QSTR_SecurityError), OBJ_FROM_PTR(&mp_type_bleio_SecurityError) }, // Initialization - { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&bleio___init___obj) }, - + { MP_ROM_QSTR(MP_QSTR___init__), OBJ_FROM_PTR(&bleio___init___obj) }, }; +#if CIRCUITPY_BLEIO_HCI +// Module dict is mutable to allow setting _bleio.adapter. +STATIC MP_DEFINE_MUTABLE_DICT(bleio_module_globals, bleio_module_globals_table); +#else STATIC MP_DEFINE_CONST_DICT(bleio_module_globals, bleio_module_globals_table); +#endif 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; diff --git a/shared-bindings/_bleio/__init__.h b/shared-bindings/_bleio/__init__.h index 5256bdaa0e..588b1f1973 100644 --- a/shared-bindings/_bleio/__init__.h +++ b/shared-bindings/_bleio/__init__.h @@ -55,15 +55,17 @@ 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; +extern mp_obj_t bleio_set_adapter(mp_obj_t adapter_obj); + 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, ...); +bleio_adapter_obj_t *common_hal_bleio_allocate_adapter_or_raise(void); void common_hal_bleio_check_connected(uint16_t conn_handle); uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device); -mp_obj_list_t *common_hal_bleio_device_get_remote_service_list(mp_obj_t device); void common_hal_bleio_device_discover_remote_services(mp_obj_t device, mp_obj_t service_uuids_whitelist); size_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle, uint8_t* buf, size_t len); diff --git a/shared-bindings/displayio/Display.c b/shared-bindings/displayio/Display.c index c4fbdab2e4..f36aeed18c 100644 --- a/shared-bindings/displayio/Display.c +++ b/shared-bindings/displayio/Display.c @@ -215,28 +215,33 @@ STATIC mp_obj_t displayio_display_obj_show(mp_obj_t self_in, mp_obj_t group_in) } MP_DEFINE_CONST_FUN_OBJ_2(displayio_display_show_obj, displayio_display_obj_show); -//| def refresh(self, *, target_frames_per_second: int = 60, minimum_frames_per_second: int = 1) -> bool: +//| def refresh(self, *, target_frames_per_second: Optional[int] = None, minimum_frames_per_second: int = 1) -> bool: //| """When auto refresh is off, waits for the target frame rate and then refreshes the display, //| returning True. If the call has taken too long since the last refresh call for the given //| target frame rate, then the refresh returns False immediately without updating the screen to //| hopefully help getting caught up. //| //| If the time since the last successful refresh is below the minimum frame rate, then an -//| exception will be raised. Set minimum_frames_per_second to 0 to disable. +//| exception will be raised. Set ``minimum_frames_per_second`` to 0 to disable. +//| +//| When auto refresh is off, ``display.refresh()`` or ``display.refresh(target_frames_per_second=None)`` +//| will update the display immediately. //| //| When auto refresh is on, updates the display immediately. (The display will also update //| without calls to this.) //| //| :param int target_frames_per_second: How many times a second `refresh` should be called and the screen updated. +//| Set to `None` for immediate refresh. //| :param int minimum_frames_per_second: The minimum number of times the screen should be updated per second.""" //| ... //| STATIC mp_obj_t displayio_display_obj_refresh(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_target_frames_per_second, ARG_minimum_frames_per_second }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_target_frames_per_second, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 60} }, + { MP_QSTR_target_frames_per_second, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} }, { MP_QSTR_minimum_frames_per_second, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, }; + 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); @@ -246,8 +251,18 @@ STATIC mp_obj_t displayio_display_obj_refresh(size_t n_args, const mp_obj_t *pos if (minimum_frames_per_second > 0) { maximum_ms_per_real_frame = 1000 / minimum_frames_per_second; } - return mp_obj_new_bool(common_hal_displayio_display_refresh(self, 1000 / args[ARG_target_frames_per_second].u_int, maximum_ms_per_real_frame)); + + uint32_t target_ms_per_frame; + if (args[ARG_target_frames_per_second].u_obj == mp_const_none) { + target_ms_per_frame = 0xffffffff; + } + else { + target_ms_per_frame = 1000 / mp_obj_get_int(args[ARG_target_frames_per_second].u_obj); + } + + return mp_obj_new_bool(common_hal_displayio_display_refresh(self, target_ms_per_frame, maximum_ms_per_real_frame)); } + MP_DEFINE_CONST_FUN_OBJ_KW(displayio_display_refresh_obj, 1, displayio_display_obj_refresh); //| auto_refresh: bool diff --git a/shared-bindings/rgbmatrix/RGBMatrix.c b/shared-bindings/rgbmatrix/RGBMatrix.c index 9cfc0d4095..e4683af920 100644 --- a/shared-bindings/rgbmatrix/RGBMatrix.c +++ b/shared-bindings/rgbmatrix/RGBMatrix.c @@ -252,7 +252,7 @@ STATIC mp_obj_t rgbmatrix_rgbmatrix_deinit(mp_obj_t self_in) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(rgbmatrix_rgbmatrix_deinit_obj, rgbmatrix_rgbmatrix_deinit); static void check_for_deinit(rgbmatrix_rgbmatrix_obj_t *self) { - if (!self->core.rgbPins) { + if (!self->protomatter.rgbPins) { raise_deinited_error(); } } diff --git a/shared-bindings/rgbmatrix/RGBMatrix.h b/shared-bindings/rgbmatrix/RGBMatrix.h index 027f817bb6..1dc5a406ca 100644 --- a/shared-bindings/rgbmatrix/RGBMatrix.h +++ b/shared-bindings/rgbmatrix/RGBMatrix.h @@ -24,29 +24,12 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_RGBMATRIX_RGBMATRIX_H -#define MICROPY_INCLUDED_SHARED_BINDINGS_RGBMATRIX_RGBMATRIX_H +#pragma once #include "shared-module/rgbmatrix/RGBMatrix.h" #include "lib/protomatter/core.h" extern const mp_obj_type_t rgbmatrix_RGBMatrix_type; -typedef struct { - mp_obj_base_t base; - mp_obj_t framebuffer; - mp_buffer_info_t bufinfo; - Protomatter_core core; - void *timer; - uint16_t bufsize, width; - uint8_t rgb_pins[30]; - uint8_t addr_pins[10]; - uint8_t clock_pin, latch_pin, oe_pin; - uint8_t rgb_count, addr_count; - uint8_t bit_depth; - bool core_is_initialized; - bool paused; - bool doublebuffer; -} rgbmatrix_rgbmatrix_obj_t; void common_hal_rgbmatrix_rgbmatrix_construct(rgbmatrix_rgbmatrix_obj_t* self, int width, int bit_depth, uint8_t rgb_count, uint8_t* rgb_pins, uint8_t addr_count, uint8_t* addr_pins, uint8_t clock_pin, uint8_t latch_pin, uint8_t oe_pin, bool doublebuffer, mp_obj_t framebuffer, void* timer); void common_hal_rgbmatrix_rgbmatrix_deinit(rgbmatrix_rgbmatrix_obj_t*); @@ -57,5 +40,3 @@ bool common_hal_rgbmatrix_rgbmatrix_get_paused(rgbmatrix_rgbmatrix_obj_t* self); void common_hal_rgbmatrix_rgbmatrix_refresh(rgbmatrix_rgbmatrix_obj_t* self); int common_hal_rgbmatrix_rgbmatrix_get_width(rgbmatrix_rgbmatrix_obj_t* self); int common_hal_rgbmatrix_rgbmatrix_get_height(rgbmatrix_rgbmatrix_obj_t* self); - -#endif diff --git a/shared-bindings/usb_midi/__init__.c b/shared-bindings/usb_midi/__init__.c index e61086f84f..d88a0db48d 100644 --- a/shared-bindings/usb_midi/__init__.c +++ b/shared-bindings/usb_midi/__init__.c @@ -51,17 +51,7 @@ mp_map_elem_t usb_midi_module_globals_table[] = { }; // This isn't const so we can set ports dynamically. -mp_obj_dict_t usb_midi_module_globals = { - .base = {&mp_type_dict}, - .map = { - .all_keys_are_qstrs = 1, - .is_fixed = 1, - .is_ordered = 1, - .used = MP_ARRAY_SIZE(usb_midi_module_globals_table), - .alloc = MP_ARRAY_SIZE(usb_midi_module_globals_table), - .table = usb_midi_module_globals_table, - }, -}; +MP_DEFINE_MUTABLE_DICT(usb_midi_module_globals, usb_midi_module_globals_table); const mp_obj_module_t usb_midi_module = { .base = { &mp_type_module }, diff --git a/shared-module/_bleio/Characteristic.h b/shared-module/_bleio/Characteristic.h index 409a57c76e..7776b1fa57 100644 --- a/shared-module/_bleio/Characteristic.h +++ b/shared-module/_bleio/Characteristic.h @@ -27,6 +27,9 @@ #ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H #define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H +// These are not the Bluetooth spec values. They are what is used by the Nordic SoftDevice. +// The bit values are in different positions. + typedef enum { CHAR_PROP_NONE = 0, CHAR_PROP_BROADCAST = 1u << 0, @@ -40,4 +43,14 @@ typedef enum { } bleio_characteristic_properties_enum_t; typedef uint8_t bleio_characteristic_properties_t; +// Bluetooth spec property values +#define BT_GATT_CHRC_BROADCAST 0x01 +#define BT_GATT_CHRC_READ 0x02 +#define BT_GATT_CHRC_WRITE_WITHOUT_RESP 0x04 +#define BT_GATT_CHRC_WRITE 0x08 +#define BT_GATT_CHRC_NOTIFY 0x10 +#define BT_GATT_CHRC_INDICATE 0x20 +#define BT_GATT_CHRC_AUTH 0x40 +#define BT_GATT_CHRC_EXT_PROP 0x80 + #endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H diff --git a/shared-module/displayio/Display.c b/shared-module/displayio/Display.c index 4f92f249fd..021159c0d9 100644 --- a/shared-module/displayio/Display.c +++ b/shared-module/displayio/Display.c @@ -352,7 +352,7 @@ uint16_t common_hal_displayio_display_get_rotation(displayio_display_obj_t* self bool common_hal_displayio_display_refresh(displayio_display_obj_t* self, uint32_t target_ms_per_frame, uint32_t maximum_ms_per_real_frame) { - if (!self->auto_refresh && !self->first_manual_refresh) { + if (!self->auto_refresh && !self->first_manual_refresh && (target_ms_per_frame != 0xffffffff) ) { uint64_t current_time = supervisor_ticks_ms64(); uint32_t current_ms_since_real_refresh = current_time - self->core.last_refresh; // Test to see if the real frame time is below our minimum. diff --git a/shared-module/framebufferio/FramebufferDisplay.c b/shared-module/framebufferio/FramebufferDisplay.c index 6b5346877c..5163c3a7bc 100644 --- a/shared-module/framebufferio/FramebufferDisplay.c +++ b/shared-module/framebufferio/FramebufferDisplay.c @@ -66,7 +66,7 @@ void common_hal_framebufferio_framebufferdisplay_construct(framebufferio_framebu ram_height, 0, 0, - rotation, + 0, // rotation depth, fb_getter_default(get_grayscale, (depth < 8)), fb_getter_default(get_pixels_in_byte_share_row, false), @@ -92,6 +92,10 @@ void common_hal_framebufferio_framebufferdisplay_construct(framebufferio_framebu self->native_frames_per_second = fb_getter_default(get_native_frames_per_second, 60); self->native_ms_per_frame = 1000 / self->native_frames_per_second; + if (rotation != 0) { + common_hal_framebufferio_framebufferdisplay_set_rotation(self, rotation); + } + supervisor_start_terminal(self->core.width, self->core.height); // Set the group after initialization otherwise we may send pixels while we delay in diff --git a/shared-module/rgbmatrix/RGBMatrix.c b/shared-module/rgbmatrix/RGBMatrix.c index 6dad91679f..3007ca4db5 100644 --- a/shared-module/rgbmatrix/RGBMatrix.c +++ b/shared-module/rgbmatrix/RGBMatrix.c @@ -66,9 +66,9 @@ void common_hal_rgbmatrix_rgbmatrix_construct(rgbmatrix_rgbmatrix_obj_t *self, i } void common_hal_rgbmatrix_rgbmatrix_reconstruct(rgbmatrix_rgbmatrix_obj_t* self, mp_obj_t framebuffer) { + common_hal_rgbmatrix_timer_disable(self->timer); if (framebuffer) { self->framebuffer = framebuffer; - framebuffer = mp_obj_new_bytearray_of_zeros(self->bufsize); mp_get_buffer_raise(self->framebuffer, &self->bufinfo, MP_BUFFER_READ); if (mp_get_buffer(self->framebuffer, &self->bufinfo, MP_BUFFER_RW)) { self->bufinfo.typecode = 'H' | MP_OBJ_ARRAY_TYPECODE_FLAG_RW; @@ -79,17 +79,18 @@ void common_hal_rgbmatrix_rgbmatrix_reconstruct(rgbmatrix_rgbmatrix_obj_t* self, mp_get_index(mp_obj_get_type(self->framebuffer), self->bufinfo.len, MP_OBJ_NEW_SMALL_INT(self->bufsize-1), false); } else { _PM_FREE(self->bufinfo.buf); - _PM_FREE(self->core.rgbPins); - _PM_FREE(self->core.addr); - _PM_FREE(self->core.screenData); + _PM_FREE(self->protomatter.rgbPins); + _PM_FREE(self->protomatter.addr); + _PM_FREE(self->protomatter.screenData); self->framebuffer = NULL; - self->bufinfo.buf = _PM_allocator_impl(self->bufsize); + self->bufinfo.buf = common_hal_rgbmatrix_allocator_impl(self->bufsize); self->bufinfo.len = self->bufsize; self->bufinfo.typecode = 'H' | MP_OBJ_ARRAY_TYPECODE_FLAG_RW; } - ProtomatterStatus stat = _PM_init(&self->core, + memset(&self->protomatter, 0, sizeof(self->protomatter)); + ProtomatterStatus stat = _PM_init(&self->protomatter, self->width, self->bit_depth, self->rgb_count/6, self->rgb_pins, self->addr_count, self->addr_pins, @@ -97,18 +98,21 @@ void common_hal_rgbmatrix_rgbmatrix_reconstruct(rgbmatrix_rgbmatrix_obj_t* self, self->doublebuffer, self->timer); if (stat == PROTOMATTER_OK) { - _PM_protoPtr = &self->core; + _PM_protoPtr = &self->protomatter; common_hal_mcu_disable_interrupts(); common_hal_rgbmatrix_timer_enable(self->timer); - stat = _PM_begin(&self->core); - _PM_convert_565(&self->core, self->bufinfo.buf, self->width); + stat = _PM_begin(&self->protomatter); + + if (stat == PROTOMATTER_OK) { + _PM_convert_565(&self->protomatter, self->bufinfo.buf, self->width); + } common_hal_mcu_enable_interrupts(); - _PM_swapbuffer_maybe(&self->core); + if (stat == PROTOMATTER_OK) { + _PM_swapbuffer_maybe(&self->protomatter); + } } if (stat != PROTOMATTER_OK) { - // XXX this deinit() actually makes crashy-crashy - // can trigger it by sending inappropriate pins common_hal_rgbmatrix_rgbmatrix_deinit(self); switch (stat) { case PROTOMATTER_ERR_PINS: @@ -117,7 +121,9 @@ void common_hal_rgbmatrix_rgbmatrix_reconstruct(rgbmatrix_rgbmatrix_obj_t* self, case PROTOMATTER_ERR_ARG: mp_raise_ValueError(translate("Invalid argument")); break; - case PROTOMATTER_ERR_MALLOC: /// should have already been signaled as NLR + case PROTOMATTER_ERR_MALLOC: + mp_raise_msg(&mp_type_MemoryError, NULL); + break; default: mp_raise_msg_varg(&mp_type_RuntimeError, translate("Internal error #%d"), (int)stat); @@ -126,7 +132,6 @@ void common_hal_rgbmatrix_rgbmatrix_reconstruct(rgbmatrix_rgbmatrix_obj_t* self, } self->paused = 0; - } STATIC void free_pin(uint8_t *pin) { @@ -148,7 +153,7 @@ void common_hal_rgbmatrix_rgbmatrix_deinit(rgbmatrix_rgbmatrix_obj_t* self) { self->timer = 0; } - if (_PM_protoPtr == &self->core) { + if (_PM_protoPtr == &self->protomatter) { _PM_protoPtr = NULL; } @@ -158,10 +163,10 @@ void common_hal_rgbmatrix_rgbmatrix_deinit(rgbmatrix_rgbmatrix_obj_t* self) { free_pin(&self->latch_pin); free_pin(&self->oe_pin); - if (self->core.rgbPins) { - _PM_free(&self->core); + if (self->protomatter.rgbPins) { + _PM_free(&self->protomatter); } - memset(&self->core, 0, sizeof(self->core)); + memset(&self->protomatter, 0, sizeof(self->protomatter)); // If it was supervisor-allocated, it is supervisor-freed and the pointer // is zeroed, otherwise the pointer is just zeroed @@ -175,16 +180,16 @@ void common_hal_rgbmatrix_rgbmatrix_deinit(rgbmatrix_rgbmatrix_obj_t* self) { void rgbmatrix_rgbmatrix_collect_ptrs(rgbmatrix_rgbmatrix_obj_t* self) { gc_collect_ptr(self->framebuffer); - gc_collect_ptr(self->core.rgbPins); - gc_collect_ptr(self->core.addr); - gc_collect_ptr(self->core.screenData); + gc_collect_ptr(self->protomatter.rgbPins); + gc_collect_ptr(self->protomatter.addr); + gc_collect_ptr(self->protomatter.screenData); } void common_hal_rgbmatrix_rgbmatrix_set_paused(rgbmatrix_rgbmatrix_obj_t* self, bool paused) { if (paused && !self->paused) { - _PM_stop(&self->core); + _PM_stop(&self->protomatter); } else if (!paused && self->paused) { - _PM_resume(&self->core); + _PM_resume(&self->protomatter); } self->paused = paused; } @@ -194,8 +199,8 @@ bool common_hal_rgbmatrix_rgbmatrix_get_paused(rgbmatrix_rgbmatrix_obj_t* self) } void common_hal_rgbmatrix_rgbmatrix_refresh(rgbmatrix_rgbmatrix_obj_t* self) { - _PM_convert_565(&self->core, self->bufinfo.buf, self->width); - _PM_swapbuffer_maybe(&self->core); + _PM_convert_565(&self->protomatter, self->bufinfo.buf, self->width); + _PM_swapbuffer_maybe(&self->protomatter); } int common_hal_rgbmatrix_rgbmatrix_get_width(rgbmatrix_rgbmatrix_obj_t* self) { @@ -206,3 +211,20 @@ int common_hal_rgbmatrix_rgbmatrix_get_height(rgbmatrix_rgbmatrix_obj_t* self) { int computed_height = (self->rgb_count / 3) << (self->addr_count); return computed_height; } + +void *common_hal_rgbmatrix_allocator_impl(size_t sz) { + if (gc_alloc_possible()) { + return m_malloc_maybe(sz + sizeof(void*), true); + } else { + supervisor_allocation *allocation = allocate_memory(align32_size(sz), false); + return allocation ? allocation->ptr : NULL; + } +} + +void common_hal_rgbmatrix_free_impl(void *ptr_in) { + supervisor_allocation *allocation = allocation_from_ptr(ptr_in); + + if (allocation) { + free_memory(allocation); + } +} diff --git a/shared-module/rgbmatrix/RGBMatrix.h b/shared-module/rgbmatrix/RGBMatrix.h index e69de29bb2..19d7d5f2e7 100644 --- a/shared-module/rgbmatrix/RGBMatrix.h +++ b/shared-module/rgbmatrix/RGBMatrix.h @@ -0,0 +1,47 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include "lib/protomatter/core.h" + +extern const mp_obj_type_t rgbmatrix_RGBMatrix_type; +typedef struct { + mp_obj_base_t base; + mp_obj_t framebuffer; + mp_buffer_info_t bufinfo; + Protomatter_core protomatter; + void *timer; + uint16_t bufsize, width; + uint8_t rgb_pins[30]; + uint8_t addr_pins[10]; + uint8_t clock_pin, latch_pin, oe_pin; + uint8_t rgb_count, addr_count; + uint8_t bit_depth; + bool core_is_initialized; + bool paused; + bool doublebuffer; +} rgbmatrix_rgbmatrix_obj_t; diff --git a/shared-module/rgbmatrix/allocator.h b/shared-module/rgbmatrix/allocator.h index 5e6f0b41d2..323fa5ec06 100644 --- a/shared-module/rgbmatrix/allocator.h +++ b/shared-module/rgbmatrix/allocator.h @@ -1,29 +1,37 @@ -#ifndef MICROPY_INCLUDED_SHARED_MODULE_RGBMATRIX_ALLOCATOR_H -#define MICROPY_INCLUDED_SHARED_MODULE_RGBMATRIX_ALLOCATOR_H +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once #include #include "py/gc.h" #include "py/misc.h" #include "supervisor/memory.h" -#define _PM_ALLOCATOR _PM_allocator_impl -#define _PM_FREE(x) (_PM_free_impl((x)), (x)=NULL, (void)0) - -static inline void *_PM_allocator_impl(size_t sz) { - if (gc_alloc_possible()) { - return m_malloc(sz + sizeof(void*), true); - } else { - supervisor_allocation *allocation = allocate_memory(align32_size(sz), false); - return allocation ? allocation->ptr : NULL; - } -} - -static inline void _PM_free_impl(void *ptr_in) { - supervisor_allocation *allocation = allocation_from_ptr(ptr_in); - - if (allocation) { - free_memory(allocation); - } -} - -#endif +#define _PM_ALLOCATOR common_hal_rgbmatrix_allocator_impl +#define _PM_FREE(x) (common_hal_rgbmatrix_free_impl((x)), (x)=NULL, (void)0) +extern void *common_hal_rgbmatrix_allocator_impl(size_t sz); +extern void common_hal_rgbmatrix_free_impl(void *); diff --git a/supervisor/shared/bluetooth.c b/supervisor/shared/bluetooth.c index 98d0fab38e..56bf321173 100644 --- a/supervisor/shared/bluetooth.c +++ b/supervisor/shared/bluetooth.c @@ -24,6 +24,15 @@ * THE SOFTWARE. */ +#if !CIRCUITPY_BLE_FILE_SERVICE +void supervisor_start_bluetooth(void) { +} + +void supervisor_bluetooth_background(void) { +} + +#else + #include #include "extmod/vfs.h" @@ -41,6 +50,8 @@ #include "py/mpstate.h" + + bleio_service_obj_t supervisor_ble_service; bleio_uuid_obj_t supervisor_ble_service_uuid; bleio_characteristic_obj_t supervisor_ble_version_characteristic; @@ -63,10 +74,7 @@ mp_obj_t service_list_items[1]; mp_obj_list_t characteristic_list; mp_obj_t characteristic_list_items[4]; -void supervisor_bluetooth_start_advertising(void) { - #if !CIRCUITPY_BLE_FILE_SERVICE - return; - #endif +STATIC void supervisor_bluetooth_start_advertising(void) { bool is_connected = common_hal_bleio_adapter_get_connected(&common_hal_bleio_adapter_obj); if (is_connected) { return; @@ -83,10 +91,6 @@ void supervisor_bluetooth_start_advertising(void) { } void supervisor_start_bluetooth(void) { - #if !CIRCUITPY_BLE_FILE_SERVICE - return; - #endif - common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, true); supervisor_ble_service_uuid.base.type = &bleio_uuid_type; @@ -177,7 +181,7 @@ volatile bool new_filename; volatile bool run_ble_background; bool was_connected; -void update_file_length(void) { +STATIC void update_file_length(void) { int32_t file_length = -1; mp_buffer_info_t bufinfo; bufinfo.buf = &file_length; @@ -188,7 +192,7 @@ void update_file_length(void) { common_hal_bleio_characteristic_set_value(&supervisor_ble_length_characteristic, &bufinfo); } -void open_current_file(void) { +STATIC void open_current_file(void) { if (active_file.obj.fs != 0) { return; } @@ -203,7 +207,7 @@ void open_current_file(void) { update_file_length(); } -void close_current_file(void) { +STATIC void close_current_file(void) { f_close(&active_file); } @@ -211,9 +215,6 @@ uint32_t current_command[1024 / sizeof(uint32_t)]; volatile size_t current_offset; void supervisor_bluetooth_background(void) { - #if !CIRCUITPY_BLE_FILE_SERVICE - return; - #endif if (!run_ble_background) { return; } @@ -305,54 +306,4 @@ void supervisor_bluetooth_background(void) { } } -// This happens in an interrupt so we need to be quick. -bool supervisor_bluetooth_hook(ble_evt_t *ble_evt) { - #if !CIRCUITPY_BLE_FILE_SERVICE - return false; - #endif - // Catch writes to filename or contents. Length is read-only. - - bool done = false; - switch (ble_evt->header.evt_id) { - case BLE_GAP_EVT_CONNECTED: - // We run our background task even if it wasn't us connected to because we may want to - // advertise if the user code stopped advertising. - run_ble_background = true; - break; - case BLE_GAP_EVT_DISCONNECTED: - run_ble_background = true; - break; - case BLE_GATTS_EVT_WRITE: { - // A client wrote to a characteristic. - - ble_gatts_evt_write_t *evt_write = &ble_evt->evt.gatts_evt.params.write; - // Event handle must match the handle for my characteristic. - if (evt_write->handle == supervisor_ble_contents_characteristic.handle) { - // Handle events - //write_to_ringbuf(self, evt_write->data, evt_write->len); - // First packet includes a uint16_t le for length at the start. - uint16_t current_length = ((uint16_t*) current_command)[0]; - memcpy(((uint8_t*) current_command) + current_offset, evt_write->data, evt_write->len); - current_offset += evt_write->len; - current_length = ((uint16_t*) current_command)[0]; - if (current_offset == current_length) { - run_ble_background = true; - done = true; - } - } else if (evt_write->handle == supervisor_ble_filename_characteristic.handle) { - new_filename = true; - run_ble_background = true; - done = true; - } else { - return done; - } - break; - } - - default: - // For debugging. - // mp_printf(&mp_plat_print, "Unhandled peripheral event: 0x%04x\n", ble_evt->header.evt_id); - break; - } - return done; -} +#endif // #else diff --git a/supervisor/shared/bluetooth.h b/supervisor/shared/bluetooth.h index 1fb6a879a8..55f9c86fa5 100644 --- a/supervisor/shared/bluetooth.h +++ b/supervisor/shared/bluetooth.h @@ -27,8 +27,7 @@ #ifndef MICROPY_INCLUDED_SUPERVISOR_SHARED_BLUETOOTH_H #define MICROPY_INCLUDED_SUPERVISOR_SHARED_BLUETOOTH_H -void supervisor_start_bluetooth(void); -bool supervisor_bluetooth_hook(ble_evt_t *ble_evt); void supervisor_bluetooth_background(void); +void supervisor_start_bluetooth(void); -#endif +#endif // MICROPY_INCLUDED_SUPERVISOR_SHARED_BLUETOOTH_H diff --git a/supervisor/shared/display.c b/supervisor/shared/display.c index 634720d0ab..afb3f3a9a6 100644 --- a/supervisor/shared/display.c +++ b/supervisor/shared/display.c @@ -65,10 +65,14 @@ void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) { if (width_in_tiles < 80) { scale = 1; } + width_in_tiles = (width_px - blinka_bitmap.width * scale) / (grid->tile_width * scale); + if (width_in_tiles < 1) { + width_in_tiles = 1; + } uint16_t height_in_tiles = height_px / (grid->tile_height * scale); uint16_t remaining_pixels = height_px % (grid->tile_height * scale); - if (remaining_pixels > 0) { + if (height_in_tiles < 1 || remaining_pixels > 0) { height_in_tiles += 1; } @@ -94,6 +98,8 @@ void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) { } grid->width_in_tiles = width_in_tiles; grid->height_in_tiles = height_in_tiles; + assert(width_in_tiles > 0); + assert(height_in_tiles > 0); grid->pixel_width = width_in_tiles * grid->tile_width; grid->pixel_height = height_in_tiles * grid->tile_height; grid->tiles = tiles; diff --git a/supervisor/shared/micropython.c b/supervisor/shared/micropython.c index 245db11d42..bbc4807f97 100644 --- a/supervisor/shared/micropython.c +++ b/supervisor/shared/micropython.c @@ -29,14 +29,24 @@ #include "supervisor/serial.h" #include "lib/oofatfs/ff.h" #include "py/mpconfig.h" +#include "py/mpstate.h" +#include "py/runtime.h" #include "supervisor/shared/status_leds.h" +#if CIRCUITPY_WATCHDOG +#include "shared-bindings/watchdog/__init__.h" +#define WATCHDOG_EXCEPTION_CHECK() (MP_STATE_VM(mp_pending_exception) == &mp_watchdog_timeout_exception) +#else +#define WATCHDOG_EXCEPTION_CHECK() 0 +#endif + int mp_hal_stdin_rx_chr(void) { for (;;) { #ifdef MICROPY_VM_HOOK_LOOP MICROPY_VM_HOOK_LOOP #endif + mp_handle_pending(); if (serial_bytes_available()) { toggle_rx_led(); return serial_read(); diff --git a/supervisor/shared/tick.c b/supervisor/shared/tick.c index 4af59f78e3..91ffa307d7 100644 --- a/supervisor/shared/tick.c +++ b/supervisor/shared/tick.c @@ -27,6 +27,7 @@ #include "supervisor/shared/tick.h" #include "py/mpstate.h" +#include "py/runtime.h" #include "supervisor/linker.h" #include "supervisor/filesystem.h" #include "supervisor/background_callback.h" @@ -36,7 +37,7 @@ #if CIRCUITPY_BLEIO #include "supervisor/shared/bluetooth.h" -#include "common-hal/_bleio/bonding.h" +#include "common-hal/_bleio/__init__.h" #endif #if CIRCUITPY_DISPLAYIO @@ -86,7 +87,7 @@ void supervisor_background_tasks(void *unused) { #if CIRCUITPY_BLEIO supervisor_bluetooth_background(); - bonding_background(); + bleio_background(); #endif port_background_task(); @@ -149,17 +150,7 @@ void mp_hal_delay_ms(mp_uint_t delay) { while (remaining > 0) { RUN_BACKGROUND_TASKS; // Check to see if we've been CTRL-Ced by autoreload or the user. - if(MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) - { - // clear exception and generate stacktrace - MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; - nlr_raise(&MP_STATE_VM(mp_kbd_exception)); - } - if( MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception)) || - WATCHDOG_EXCEPTION_CHECK()) { - // stop sleeping immediately - break; - } + mp_handle_pending(); remaining = end_tick - port_get_raw_ticks(NULL); // We break a bit early so we don't risk setting the alarm before the time when we call // sleep. diff --git a/supervisor/supervisor.mk b/supervisor/supervisor.mk index c876a11cce..e81c51a88c 100644 --- a/supervisor/supervisor.mk +++ b/supervisor/supervisor.mk @@ -34,7 +34,7 @@ endif CFLAGS += -DSPI_FLASH_FILESYSTEM=$(SPI_FLASH_FILESYSTEM) ifeq ($(CIRCUITPY_BLEIO),1) - SRC_SUPERVISOR += supervisor/shared/bluetooth.c + SRC_SUPERVISOR += supervisor/shared/bluetooth.c supervisor/bluetooth.c endif # Choose which flash filesystem impl to use. diff --git a/tests/basics/bit_length.py b/tests/basics/bit_length.py new file mode 100644 index 0000000000..5eb33f604e --- /dev/null +++ b/tests/basics/bit_length.py @@ -0,0 +1,4 @@ +for i in range(129): + j = (1 << i) + print(i, (j-1).bit_length(), (j).bit_length(), (j+1).bit_length()) + print(i, (-j-1).bit_length(), (-j).bit_length(), (-j+1).bit_length()) diff --git a/tests/basics/builtin_help.py.exp b/tests/basics/builtin_help.py.exp index ed8a7d74b8..89350a6c79 100644 --- a/tests/basics/builtin_help.py.exp +++ b/tests/basics/builtin_help.py.exp @@ -1,14 +1,14 @@ ######## object is of type function object is of type type + bit_length -- from_bytes -- to_bytes -- object 1 is of type int + bit_length -- from_bytes -- to_bytes -- object is of type module __name__ -- micropython - const -- - opt_level -- ######## done diff --git a/tests/cmdline/repl_autocomplete.py.exp b/tests/cmdline/repl_autocomplete.py.exp index 7d160e7bf9..0dabc90144 100644 --- a/tests/cmdline/repl_autocomplete.py.exp +++ b/tests/cmdline/repl_autocomplete.py.exp @@ -12,7 +12,7 @@ Use \.\+ 'abc' >>> x = 5 >>> x. -from_bytes to_bytes +bit_length from_bytes to_bytes >>> x. >>> x.__class__ diff --git a/tools/gen_usb_descriptor.py b/tools/gen_usb_descriptor.py index baee8cad7b..15bf2daa00 100644 --- a/tools/gen_usb_descriptor.py +++ b/tools/gen_usb_descriptor.py @@ -382,8 +382,8 @@ if args.max_ep != 0: for interface in interfaces: for subdescriptor in interface.subdescriptors: endpoint_address = getattr(subdescriptor, 'bEndpointAddress', 0) & 0x7f - if endpoint_address > args.max_ep: - raise ValueError("Endpoint address %d of %s may not exceed %d" % (endpoint_address & 0x7f, interface.description, args.max_ep)) + if endpoint_address >= args.max_ep: + raise ValueError("Endpoint address %d of %s must be less than %d" % (endpoint_address & 0x7f, interface.description, args.max_ep)) else: print("Unable to check whether maximum number of endpoints is respected", file=sys.stderr) diff --git a/tools/mpconfig_category_reader.py b/tools/mpconfig_category_reader.py new file mode 100644 index 0000000000..2f813931e8 --- /dev/null +++ b/tools/mpconfig_category_reader.py @@ -0,0 +1,31 @@ +filepath = '../py/circuitpy_mpconfig.mk' +with open(filepath) as fp: + line = fp.readline() + cnt = 1 + fullbuild = [] + defon = [] + defoff = [] + while line: + wordlist = line.split() + if wordlist: + if wordlist[-1] == "$(CIRCUITPY_FULL_BUILD)": + fullbuild.append(wordlist[0]) + elif wordlist[-1] == "0": + defoff.append(wordlist[0]) + elif wordlist[-1] == "1": + defon.append(wordlist[0]) + line = fp.readline() + cnt += 1 + + print(str(cnt) + " Lines Read\n") + print("\nFULL BUILDS ------------------------") + for string in fullbuild: + print(string) + + print("\nON BUILDS ------------------------") + for string in defon: + print(string) + + print("\nOFF BUILDS ------------------------") + for string in defoff: + print(string)