From 759929c24a9966b64075bedfb365f3dfc66ad681 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Thu, 25 Jun 2020 20:57:17 -0400 Subject: hci early wip; refactor supervisor bluetooth.c for nrf: tested --- ports/atmel-samd/asf4 | 2 +- .../boards/metro_m4_airlift_lite/mpconfigboard.mk | 4 ++ ports/atmel-samd/peripherals | 2 +- ports/nrf/bluetooth/ble_drv.c | 1 + ports/nrf/supervisor/bluetooth.c | 81 ++++++++++++++++++++++ ports/nrf/supervisor/bluetooth.h | 36 ++++++++++ 6 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 ports/nrf/supervisor/bluetooth.c create mode 100644 ports/nrf/supervisor/bluetooth.h (limited to 'ports') diff --git a/ports/atmel-samd/asf4 b/ports/atmel-samd/asf4 index c0eef7b75..039b5f3bb 160000 --- a/ports/atmel-samd/asf4 +++ b/ports/atmel-samd/asf4 @@ -1 +1 @@ -Subproject commit c0eef7b75124fc946af5f75e12d82d6d01315ab1 +Subproject commit 039b5f3bbc3f4ba4421e581db290560d59fef625 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 4895cda77..e999629c3 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/peripherals b/ports/atmel-samd/peripherals index e4161d7d6..6b531fc92 160000 --- a/ports/atmel-samd/peripherals +++ b/ports/atmel-samd/peripherals @@ -1 +1 @@ -Subproject commit e4161d7d6d98d78eddcccb82128856af4baf7e50 +Subproject commit 6b531fc923d9f02b14bd731a5f584ddf716e8773 diff --git a/ports/nrf/bluetooth/ble_drv.c b/ports/nrf/bluetooth/ble_drv.c index e410ac3b4..67c6f3468 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/supervisor/bluetooth.c b/ports/nrf/supervisor/bluetooth.c new file mode 100644 index 000000000..8d89d6272 --- /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 000000000..425de07e4 --- /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 -- cgit v1.2.3 From 3e616ccead60030a04e237d28cd1034527818509 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Fri, 26 Jun 2020 12:21:57 -0400 Subject: update submodules --- ports/atmel-samd/asf4 | 2 +- ports/atmel-samd/peripherals | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'ports') diff --git a/ports/atmel-samd/asf4 b/ports/atmel-samd/asf4 index 039b5f3bb..c0eef7b75 160000 --- a/ports/atmel-samd/asf4 +++ b/ports/atmel-samd/asf4 @@ -1 +1 @@ -Subproject commit 039b5f3bbc3f4ba4421e581db290560d59fef625 +Subproject commit c0eef7b75124fc946af5f75e12d82d6d01315ab1 diff --git a/ports/atmel-samd/peripherals b/ports/atmel-samd/peripherals index 6b531fc92..e4161d7d6 160000 --- a/ports/atmel-samd/peripherals +++ b/ports/atmel-samd/peripherals @@ -1 +1 @@ -Subproject commit 6b531fc923d9f02b14bd731a5f584ddf716e8773 +Subproject commit e4161d7d6d98d78eddcccb82128856af4baf7e50 -- cgit v1.2.3 From 11cb3e3b4b18a12b56f926f342c65c0f7db93896 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Tue, 30 Jun 2020 23:19:40 -0400 Subject: hci skeleton done; not working yet --- devices/ble_hci/common-hal/_bleio/Adapter.c | 46 +- devices/ble_hci/common-hal/_bleio/Adapter.h | 12 +- devices/ble_hci/common-hal/_bleio/hci.c | 1015 +++++++++++++-------------- ports/atmel-samd/Makefile | 2 +- py/circuitpy_defns.mk | 4 +- shared-bindings/_bleio/Adapter.c | 14 +- shared-bindings/_bleio/__init__.c | 3 + 7 files changed, 567 insertions(+), 529 deletions(-) (limited to 'ports') diff --git a/devices/ble_hci/common-hal/_bleio/Adapter.c b/devices/ble_hci/common-hal/_bleio/Adapter.c index c25bec5b8..5f5259f7e 100644 --- a/devices/ble_hci/common-hal/_bleio/Adapter.c +++ b/devices/ble_hci/common-hal/_bleio/Adapter.c @@ -31,6 +31,8 @@ #include #include +#include "hci.h" + #include "py/gc.h" #include "py/mphal.h" #include "py/objstr.h" @@ -178,10 +180,10 @@ char default_ble_name[] = { 'C', 'I', 'R', 'C', 'U', 'I', 'T', 'P', 'Y', 0, 0, 0 // } void common_hal_bleio_adapter_hci_init(bleio_adapter_obj_t *self, const mcu_pin_obj_t *tx, const mcu_pin_obj_t *rx, const mcu_pin_obj_t *rts, const mcu_pin_obj_t *cts, uint32_t baudrate, uint32_t buffer_size) { - self->tx = tx; - self->rx = rx; - self->rts = rts; - self->cts = cts; + self->tx_pin = tx; + self->rx_pin = rx; + self->rts_pin = rts; + self->cts_pin = cts; self->baudrate = baudrate; self->buffer_size = buffer_size; self->enabled = false; @@ -195,6 +197,35 @@ void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enable return; } + if (enabled) { + common_hal_busio_uart_construct( + &self->hci_uart, + self->tx_pin, // tx pin + self->rx_pin, // rx pin + NULL, // rts pin + NULL, // cts pin + NULL, // rs485 dir pin + false, // rs485 invert + 0, // timeout + self->baudrate, // baudrate + 8, // nbits + PARITY_NONE, // parity + 1, // stop bits + self->buffer_size, // buffer size + NULL, // buffer + false // sigint_enabled + ); + common_hal_digitalio_digitalinout_construct(&self->rts_digitalinout, self->rts_pin); + common_hal_digitalio_digitalinout_construct(&self->cts_digitalinout, self->cts_pin); + + hci_init(self); + } else { + common_hal_busio_uart_deinit(&self->hci_uart); + common_hal_digitalio_digitalinout_deinit(&self->rts_digitalinout); + common_hal_digitalio_digitalinout_deinit(&self->cts_digitalinout); + } + + //FIX enable/disable HCI adapter, but don't reset it, since we don't know how. self->enabled = enabled; } @@ -206,13 +237,14 @@ bool common_hal_bleio_adapter_get_enabled(bleio_adapter_obj_t *self) { bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_obj_t *self) { common_hal_bleio_adapter_set_enabled(self, true); - // ble_gap_addr_t local_address; - // get_address(self, &local_address); + uint8_t addr[6]; + hci_readBdAddr(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, local_address.addr, local_address.addr_type); + // 0 is the type designating a public address. + common_hal_bleio_address_construct(address, addr, 0); return address; } diff --git a/devices/ble_hci/common-hal/_bleio/Adapter.h b/devices/ble_hci/common-hal/_bleio/Adapter.h index 38303062a..565963dc0 100644 --- a/devices/ble_hci/common-hal/_bleio/Adapter.h +++ b/devices/ble_hci/common-hal/_bleio/Adapter.h @@ -52,15 +52,15 @@ typedef struct { bleio_scanresults_obj_t* scan_results; mp_obj_t name; mp_obj_tuple_t *connection_objs; - const mcu_pin_obj_t* tx; - const mcu_pin_obj_t* rx; - const mcu_pin_obj_t* rts; - const mcu_pin_obj_t* cts; + const mcu_pin_obj_t* tx_pin; + const mcu_pin_obj_t* rx_pin; + const mcu_pin_obj_t* rts_pin; + const mcu_pin_obj_t* cts_pin; uint32_t baudrate; uint16_t buffer_size; busio_uart_obj_t hci_uart; - digitalio_digitalinout_obj_t rts_digitalio; - digitalio_digitalinout_obj_t cts_digitalio; + digitalio_digitalinout_obj_t rts_digitalinout; + digitalio_digitalinout_obj_t cts_digitalinout; bool enabled; } bleio_adapter_obj_t; diff --git a/devices/ble_hci/common-hal/_bleio/hci.c b/devices/ble_hci/common-hal/_bleio/hci.c index 8ff69f202..7d4add9af 100644 --- a/devices/ble_hci/common-hal/_bleio/hci.c +++ b/devices/ble_hci/common-hal/_bleio/hci.c @@ -1,3 +1,6 @@ +/* + 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 @@ -9,7 +12,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "HCI.h" +#include "hci.h" +#include + +#include "supervisor/shared/tick.h" + +#define ATT_CID 0x0004 #define HCI_COMMAND_PKT 0x01 #define HCI_ACLDATA_PKT 0x02 @@ -59,617 +67,608 @@ #define HCI_OE_USER_ENDED_CONNECTION 0x13 -HCIClass::HCIClass() : - _debug(NULL), - _recvIndex(0), - _pendingPkt(0) + +#define RECV_BUFFER_SIZE (3 + 255) +#define ACL_PKT_BUFFER_SIZE (255) + +STATIC bleio_adapter_obj_t *adapter; + +STATIC int recv_idx; +STATIC uint8_t recv_buffer[RECV_BUFFER_SIZE]; +STATIC uint16_t cmd_complete_opcode; +STATIC int cmd_complete_status; +STATIC uint8_t cmd_response_len; +STATIC uint8_t* cmd_response; + +STATIC uint8_t max_pkt; +STATIC uint8_t pending_pkt; + +//FIX STATIC uint8_t acl_pkt_buffer[255]; + +STATIC bool debug = true; + +typedef struct __attribute__ ((packed)) { + uint8_t evt; + uint8_t plen; +} HCIEventHdr; + +STATIC void dumpPkt(const char* prefix, uint8_t plen, uint8_t pdata[]) { + if (debug) { + mp_printf(&mp_plat_print, "%s", prefix); + + for (uint8_t i = 0; i < plen; i++) { + mp_printf(&mp_plat_print, "%02x", pdata[i]); + } + mp_printf(&mp_plat_print, "\n"); + } } -HCIClass::~HCIClass() + +STATIC void handleAclDataPkt(uint8_t plen, uint8_t pdata[]) { + // typedef struct __attribute__ ((packed)) { + // uint16_t handle; + // uint16_t dlen; + // uint16_t len; + // uint16_t cid; + // } HCIACLHdr; + + // HCIACLHdr *aclHdr = (HCIACLHdr*)pdata; + + // uint16_t aclFlags = (aclHdr->handle & 0xf000) >> 12; + + // if ((aclHdr->dlen - 4) != aclHdr->len) { + // // packet is fragmented + // if (aclFlags != 0x01) { + // // copy into ACL buffer + // memcpy(acl_pkt_buffer, &recv_buffer[1], sizeof(HCIACLHdr) + aclHdr->dlen - 4); + // } else { + // // copy next chunk into the buffer + // HCIACLHdr* aclBufferHeader = (HCIACLHdr*)acl_pkt_buffer; + + // memcpy(&acl_pkt_buffer[sizeof(HCIACLHdr) + aclBufferHeader->dlen - 4], &recv_buffer[1 + sizeof(aclHdr->handle) + sizeof(aclHdr->dlen)], aclHdr->dlen); + + // aclBufferHeader->dlen += aclHdr->dlen; + // aclHdr = aclBufferHeader; + // } + // } + + // if ((aclHdr->dlen - 4) != aclHdr->len) { + // // don't have the full packet yet + // return; + // } + + // if (aclHdr->cid == ATT_CID) { + // if (aclFlags == 0x01) { + // // use buffered packet + // ATT.handleData(aclHdr->handle & 0x0fff, aclHdr->len, &acl_pkt_buffer[sizeof(HCIACLHdr)]); + // } else { + // // use the recv buffer + // ATT.handleData(aclHdr->handle & 0x0fff, aclHdr->len, &recv_buffer[1 + sizeof(HCIACLHdr)]); + // } + // } else if (aclHdr->cid == SIGNALING_CID) { + // L2CAPSignaling.handleData(aclHdr->handle & 0x0fff, aclHdr->len, &recv_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); + // } } -int HCIClass::begin() +STATIC void handleNumCompPkts(uint16_t handle, uint16_t numPkts) { - _recvIndex = 0; - - return HCITransport.begin(); + if (numPkts && pending_pkt > numPkts) { + pending_pkt -= numPkts; + } else { + pending_pkt = 0; + } } -void HCIClass::end() +STATIC void handleEventPkt(uint8_t plen, uint8_t pdata[]) { - HCITransport.end(); + HCIEventHdr *eventHdr = (HCIEventHdr*)pdata; + + if (eventHdr->evt == EVT_DISCONN_COMPLETE) { + typedef struct __attribute__ ((packed)) { + uint8_t status; + uint16_t handle; + uint8_t reason; + } DisconnComplete; + + DisconnComplete *disconnComplete = (DisconnComplete*)&pdata[sizeof(HCIEventHdr)]; + (void) disconnComplete; + //FIX + // ATT.removeConnection(disconnComplete->handle, disconnComplete->reason); + // L2CAPSignaling.removeConnection(disconnComplete->handle, disconnComplete->reason); + + hci_leSetAdvertiseEnable(0x01); + } else if (eventHdr->evt == EVT_CMD_COMPLETE) { + typedef struct __attribute__ ((packed)) { + uint8_t ncmd; + uint16_t opcode; + uint8_t status; + } CmdComplete; + + CmdComplete *cmdCompleteHeader = (CmdComplete*)&pdata[sizeof(HCIEventHdr)]; + cmd_complete_opcode = cmdCompleteHeader->opcode; + cmd_complete_status = cmdCompleteHeader->status; + cmd_response_len = pdata[1] - sizeof(CmdComplete); + cmd_response = &pdata[sizeof(HCIEventHdr) + sizeof(CmdComplete)]; + + } else if (eventHdr->evt == EVT_CMD_STATUS) { + typedef struct __attribute__ ((packed)) { + uint8_t status; + uint8_t ncmd; + uint16_t opcode; + } CmdStatus; + + CmdStatus *cmdStatusHeader = (CmdStatus*)&pdata[sizeof(HCIEventHdr)]; + cmd_complete_opcode = cmdStatusHeader->opcode; + cmd_complete_status = cmdStatusHeader->status; + cmd_response_len = 0; + } else if (eventHdr->evt == EVT_NUM_COMP_PKTS) { + uint8_t numHandles = pdata[sizeof(HCIEventHdr)]; + uint8_t* data = &pdata[sizeof(HCIEventHdr) + sizeof(numHandles)]; + + for (uint8_t i = 0; i < numHandles; i++) { + handleNumCompPkts(data[0], data[1]); + + data += 2; + } + } else if (eventHdr->evt == EVT_LE_META_EVENT) { + typedef struct __attribute__ ((packed)) { + uint8_t subevent; + } LeMetaEventHeader; + + LeMetaEventHeader *leMetaHeader = (LeMetaEventHeader*)&pdata[sizeof(HCIEventHdr)]; + if (leMetaHeader->subevent == EVT_LE_CONN_COMPLETE) { + typedef struct __attribute__ ((packed)) { + uint8_t status; + uint16_t handle; + uint8_t role; + uint8_t peerBdaddrType; + uint8_t peerBdaddr[6]; + uint16_t interval; + uint16_t latency; + uint16_t supervisionTimeout; + uint8_t masterClockAccuracy; + } EvtLeConnectionComplete; + + EvtLeConnectionComplete *leConnectionComplete = (EvtLeConnectionComplete*)&pdata[sizeof(HCIEventHdr) + sizeof(LeMetaEventHeader)]; + + if (leConnectionComplete->status == 0x00) { + // ATT.addConnection(leConnectionComplete->handle, + // leConnectionComplete->role, + // leConnectionComplete->peerBdaddrType, + // leConnectionComplete->peerBdaddr, + // leConnectionComplete->interval, + // leConnectionComplete->latency, + // leConnectionComplete->supervisionTimeout, + // leConnectionComplete->masterClockAccuracy); + + // L2CAPSignaling.addConnection(leConnectionComplete->handle, + // leConnectionComplete->role, + // leConnectionComplete->peerBdaddrType, + // leConnectionComplete->peerBdaddr, + // leConnectionComplete->interval, + // leConnectionComplete->latency, + // leConnectionComplete->supervisionTimeout, + // leConnectionComplete->masterClockAccuracy); + } + } else if (leMetaHeader->subevent == EVT_LE_ADVERTISING_REPORT) { + typedef struct __attribute__ ((packed)) { + uint8_t status; + uint8_t type; + uint8_t peerBdaddrType; + uint8_t peerBdaddr[6]; + uint8_t eirLength; + uint8_t eirData[31]; + } EvtLeAdvertisingReport; + + EvtLeAdvertisingReport*leAdvertisingReport = (EvtLeAdvertisingReport*)&pdata[sizeof(HCIEventHdr) + sizeof(LeMetaEventHeader)]; + + if (leAdvertisingReport->status == 0x01) { + // last byte is RSSI + //FIX int8_t rssi = leAdvertisingReport->eirData[leAdvertisingReport->eirLength]; + + // GAP.handleLeAdvertisingReport(leAdvertisingReport->type, + // leAdvertisingReport->peerBdaddrType, + // leAdvertisingReport->peerBdaddr, + // leAdvertisingReport->eirLength, + // leAdvertisingReport->eirData, + // rssi); + + } + } + } } -void HCIClass::poll() -{ - poll(0); +void hci_init(bleio_adapter_obj_t *adapter_in) { + adapter = adapter_in; + recv_idx = 0; + pending_pkt = 0; } -void HCIClass::poll(unsigned long timeout) -{ -#if defined(ARDUINO_AVR_UNO_WIFI_REV2) || defined(ARDUINO_METRO_M4_AIRLIFT_LITE) - digitalWrite(NINA_RTS, LOW); -#endif +void hci_poll(void) { + // Assert RTS low to say we're ready to read data. + common_hal_digitalio_digitalinout_set_value(&adapter->rts_digitalinout, false); + + int errcode = 0; + while (common_hal_busio_uart_rx_characters_available(&adapter->hci_uart)) { + // Read just one character. + common_hal_busio_uart_read(&adapter->hci_uart, recv_buffer + recv_idx, 1, &errcode); + recv_idx++; + + if (recv_buffer[0] == HCI_ACLDATA_PKT) { + if (recv_idx > 5 && recv_idx >= (5 + (recv_buffer[3] + (recv_buffer[4] << 8)))) { + if (debug) { + dumpPkt("HCI ACLDATA RX <- ", recv_idx, recv_buffer); + } + // Hold data while processing packet. + common_hal_digitalio_digitalinout_set_value(&adapter->rts_digitalinout, true); + size_t pktLen = recv_idx - 1; + recv_idx = 0; + + handleAclDataPkt(pktLen, &recv_buffer[1]); + + common_hal_digitalio_digitalinout_set_value(&adapter->rts_digitalinout, false); + } + } else if (recv_buffer[0] == HCI_EVENT_PKT) { + if (recv_idx > 3 && recv_idx >= (3 + recv_buffer[2])) { + if (debug) { + dumpPkt("HCI EVENT RX <- ", recv_idx, recv_buffer); + } + // Hold data while processing packet. + common_hal_digitalio_digitalinout_set_value(&adapter->rts_digitalinout, true); + // Received full event. Reset buffer and handle packet. + size_t pktLen = recv_idx - 1; + recv_idx = 0; + + handleEventPkt(pktLen, &recv_buffer[1]); + + common_hal_digitalio_digitalinout_set_value(&adapter->rts_digitalinout, false); + } + } else { + recv_idx = 0; + } + } - if (timeout) { - HCITransport.wait(timeout); - } + common_hal_digitalio_digitalinout_set_value(&adapter->rts_digitalinout, true); +} - while (HCITransport.available()) { - byte b = HCITransport.read(); - _recvBuffer[_recvIndex++] = b; +int hci_sendCommand(uint8_t ogf, uint16_t ocf, uint8_t plen, void* parameters) +{ + uint16_t opcode = ogf << 10 | ocf; - if (_recvBuffer[0] == HCI_ACLDATA_PKT) { - if (_recvIndex > 5 && _recvIndex >= (5 + (_recvBuffer[3] + (_recvBuffer[4] << 8)))) { - if (_debug) { - dumpPkt("HCI ACLDATA RX <- ", _recvIndex, _recvBuffer); - } -#if defined(ARDUINO_AVR_UNO_WIFI_REV2) || defined(ARDUINO_METRO_M4_AIRLIFT_LITE) - digitalWrite(NINA_RTS, HIGH); -#endif - int pktLen = _recvIndex - 1; - _recvIndex = 0; + struct __attribute__ ((packed)) { + uint8_t pktType; + uint16_t opcode; + uint8_t plen; + } pktHdr = {HCI_COMMAND_PKT, opcode, plen}; - handleAclDataPkt(pktLen, &_recvBuffer[1]); + uint8_t txBuffer[sizeof(pktHdr) + plen]; + memcpy(txBuffer, &pktHdr, sizeof(pktHdr)); + memcpy(&txBuffer[sizeof(pktHdr)], parameters, plen); -#if defined(ARDUINO_AVR_UNO_WIFI_REV2) || defined(ARDUINO_METRO_M4_AIRLIFT_LITE) - digitalWrite(NINA_RTS, LOW); -#endif - } - } else if (_recvBuffer[0] == HCI_EVENT_PKT) { - if (_recvIndex > 3 && _recvIndex >= (3 + _recvBuffer[2])) { - if (_debug) { - dumpPkt("HCI EVENT RX <- ", _recvIndex, _recvBuffer); - } -#if defined(ARDUINO_AVR_UNO_WIFI_REV2) || defined(ARDUINO_METRO_M4_AIRLIFT_LITE) - digitalWrite(NINA_RTS, HIGH); -#endif - // received full event - int pktLen = _recvIndex - 1; - _recvIndex = 0; + if (debug) { + dumpPkt("HCI COMMAND TX -> ", sizeof(pktHdr) + plen, txBuffer); + } - handleEventPkt(pktLen, &_recvBuffer[1]); + int errcode = 0; + common_hal_busio_uart_write(&adapter->hci_uart, txBuffer, sizeof(pktHdr) + plen, &errcode); + if (errcode) { + return -1; + } -#if defined(ARDUINO_AVR_UNO_WIFI_REV2) || defined(ARDUINO_METRO_M4_AIRLIFT_LITE) - digitalWrite(NINA_RTS, LOW); -#endif - } - } else { - _recvIndex = 0; + cmd_complete_opcode = 0xffff; + cmd_complete_status = -1; - if (_debug) { - _debug->println(b, HEX); - } + // Wait up to one second for a response. + for (uint64_t start = supervisor_ticks_ms64(); + cmd_complete_opcode != opcode && supervisor_ticks_ms64() < (start + 5000); + ) { + hci_poll(); } - } -#if defined(ARDUINO_AVR_UNO_WIFI_REV2) || defined(ARDUINO_METRO_M4_AIRLIFT_LITE) - digitalWrite(NINA_RTS, HIGH); -#endif + return cmd_complete_status; } -int HCIClass::reset() -{ - return sendCommand(OGF_HOST_CTL << 10 | OCF_RESET); +int hci_reset(void) { + return hci_sendCommand(OGF_HOST_CTL, OCF_RESET, 0, NULL); } -int HCIClass::readLocalVersion(uint8_t& hciVer, uint16_t& hciRev, uint8_t& lmpVer, uint16_t& manufacturer, uint16_t& lmpSubVer) -{ - int result = sendCommand(OGF_INFO_PARAM << 10 | OCF_READ_LOCAL_VERSION); - - if (result == 0) { - struct __attribute__ ((packed)) HCILocalVersion { - uint8_t hciVer; - uint16_t hciRev; - uint8_t lmpVer; - uint16_t manufacturer; - uint16_t lmpSubVer; - } *localVersion = (HCILocalVersion*)_cmdResponse; - - hciVer = localVersion->hciVer; - hciRev = localVersion->hciRev; - lmpVer = localVersion->lmpVer; - manufacturer = localVersion->manufacturer; - lmpSubVer = localVersion->lmpSubVer; - } - - return result; +int hci_readLocalVersion(uint8_t *hciVer, uint16_t *hciRev, uint8_t *lmpVer, uint16_t *manufacturer, uint16_t *lmpSubVer) { + int result = hci_sendCommand(OGF_INFO_PARAM, OCF_READ_LOCAL_VERSION, 0, NULL); + + if (result == 0) { + typedef struct __attribute__ ((packed)) { + uint8_t hciVer; + uint16_t hciRev; + uint8_t lmpVer; + uint16_t manufacturer; + uint16_t lmpSubVer; + } HCILocalVersion; + + HCILocalVersion *localVersion = (HCILocalVersion*)cmd_response; + *hciVer = localVersion->hciVer; + *hciRev = localVersion->hciRev; + *lmpVer = localVersion->lmpVer; + *manufacturer = localVersion->manufacturer; + *lmpSubVer = localVersion->lmpSubVer; + } + + return result; } -int HCIClass::readBdAddr(uint8_t addr[6]) -{ - int result = sendCommand(OGF_INFO_PARAM << 10 | OCF_READ_BD_ADDR); +int hci_readBdAddr(uint8_t addr[6]) { + int result = hci_sendCommand(OGF_INFO_PARAM, OCF_READ_BD_ADDR, 0, NULL); - if (result == 0) { - memcpy(addr, _cmdResponse, 6); - } + if (result == 0) { + memcpy(addr, cmd_response, 6); + } - return result; + return result; } -int HCIClass::readRssi(uint16_t handle) -{ - int result = sendCommand(OGF_STATUS_PARAM << 10 | OCF_READ_RSSI, sizeof(handle), &handle); - int rssi = 127; +int hci_readRssi(uint16_t handle) { + int result = hci_sendCommand(OGF_STATUS_PARAM, OCF_READ_RSSI, sizeof(handle), &handle); + int rssi = 127; - if (result == 0) { - struct __attribute__ ((packed)) HCIReadRssi { - uint16_t handle; - int8_t rssi; - } *readRssi = (HCIReadRssi*)_cmdResponse; + if (result == 0) { + typedef struct __attribute__ ((packed)) { + uint16_t handle; + int8_t rssi; + } HCIReadRssi; - if (readRssi->handle == handle) { - rssi = readRssi->rssi; + HCIReadRssi *readRssi = (HCIReadRssi*)cmd_response; + if (readRssi->handle == handle) { + rssi = readRssi->rssi; + } } - } - return rssi; + return rssi; } -int HCIClass::setEventMask(uint64_t eventMask) -{ - return sendCommand(OGF_HOST_CTL << 10 | OCF_SET_EVENT_MASK, sizeof(eventMask), &eventMask); +int hci_setEventMask(uint64_t eventMask) { + return hci_sendCommand(OGF_HOST_CTL, OCF_SET_EVENT_MASK, sizeof(eventMask), &eventMask); } -int HCIClass::readLeBufferSize(uint16_t& pktLen, uint8_t& maxPkt) +int hci_readLeBufferSize(uint16_t *pktLen, uint8_t *maxPkt) { - int result = sendCommand(OGF_LE_CTL << 10 | OCF_LE_READ_BUFFER_SIZE); + int result = hci_sendCommand(OGF_LE_CTL, OCF_LE_READ_BUFFER_SIZE, 0, NULL); - if (result == 0) { - struct __attribute__ ((packed)) HCILeBufferSize { - uint16_t pktLen; - uint8_t maxPkt; - } *leBufferSize = (HCILeBufferSize*)_cmdResponse; + if (result == 0) { + typedef struct __attribute__ ((packed)) { + uint16_t pktLen; + uint8_t maxPkt; + } HCILeBufferSize; - pktLen = leBufferSize->pktLen; - _maxPkt = maxPkt = leBufferSize->maxPkt; + HCILeBufferSize *leBufferSize = (HCILeBufferSize*)cmd_response; + *pktLen = leBufferSize->pktLen; + *maxPkt = leBufferSize->maxPkt; #ifndef __AVR__ - ATT.setMaxMtu(pktLen - 9); // max pkt len - ACL header size + // FIX (needed?) ATT.setMaxMtu(pktLen - 9); // max pkt len - ACL header size #endif - } + } - return result; + return result; } -int HCIClass::leSetRandomAddress(uint8_t addr[6]) +int hci_leSetRandomAddress(uint8_t addr[6]) { - return sendCommand(OGF_LE_CTL << 10 | OCF_LE_SET_RANDOM_ADDRESS, 6, addr); + return hci_sendCommand(OGF_LE_CTL, OCF_LE_SET_RANDOM_ADDRESS, 6, addr); } -int HCIClass::leSetAdvertisingParameters(uint16_t minInterval, uint16_t maxInterval, +int hci_leSetAdvertisingParameters(uint16_t minInterval, uint16_t maxInterval, uint8_t advType, uint8_t ownBdaddrType, uint8_t directBdaddrType, uint8_t directBdaddr[6], uint8_t chanMap, uint8_t filter) { - struct __attribute__ ((packed)) HCILeAdvertisingParameters { - uint16_t minInterval; - uint16_t maxInterval; - uint8_t advType; - uint8_t ownBdaddrType; - uint8_t directBdaddrType; - uint8_t directBdaddr[6]; - uint8_t chanMap; - uint8_t filter; - } leAdvertisingParamters; - - leAdvertisingParamters.minInterval = minInterval; - leAdvertisingParamters.maxInterval = maxInterval; - leAdvertisingParamters.advType = advType; - leAdvertisingParamters.ownBdaddrType = ownBdaddrType; - leAdvertisingParamters.directBdaddrType = directBdaddrType; - memcpy(leAdvertisingParamters.directBdaddr, directBdaddr, 6); - leAdvertisingParamters.chanMap = chanMap; - leAdvertisingParamters.filter = filter; - - return sendCommand(OGF_LE_CTL << 10 | OCF_LE_SET_ADVERTISING_PARAMETERS, sizeof(leAdvertisingParamters), &leAdvertisingParamters); + struct __attribute__ ((packed)) HCILeAdvertisingParameters { + uint16_t minInterval; + uint16_t maxInterval; + uint8_t advType; + uint8_t ownBdaddrType; + uint8_t directBdaddrType; + uint8_t directBdaddr[6]; + uint8_t chanMap; + uint8_t filter; + } leAdvertisingParamters; + + leAdvertisingParamters.minInterval = minInterval; + leAdvertisingParamters.maxInterval = maxInterval; + leAdvertisingParamters.advType = advType; + leAdvertisingParamters.ownBdaddrType = ownBdaddrType; + leAdvertisingParamters.directBdaddrType = directBdaddrType; + memcpy(leAdvertisingParamters.directBdaddr, directBdaddr, 6); + leAdvertisingParamters.chanMap = chanMap; + leAdvertisingParamters.filter = filter; + + return hci_sendCommand(OGF_LE_CTL, OCF_LE_SET_ADVERTISING_PARAMETERS, sizeof(leAdvertisingParamters), &leAdvertisingParamters); } -int HCIClass::leSetAdvertisingData(uint8_t length, uint8_t data[]) +int hci_leSetAdvertisingData(uint8_t length, uint8_t data[]) { - struct __attribute__ ((packed)) HCILeAdvertisingData { - uint8_t length; - uint8_t data[31]; - } leAdvertisingData; + struct __attribute__ ((packed)) HCILeAdvertisingData { + uint8_t length; + uint8_t data[31]; + } leAdvertisingData; - memset(&leAdvertisingData, 0, sizeof(leAdvertisingData)); - leAdvertisingData.length = length; - memcpy(leAdvertisingData.data, data, length); + memset(&leAdvertisingData, 0, sizeof(leAdvertisingData)); + leAdvertisingData.length = length; + memcpy(leAdvertisingData.data, data, length); - return sendCommand(OGF_LE_CTL << 10 | OCF_LE_SET_ADVERTISING_DATA, sizeof(leAdvertisingData), &leAdvertisingData); + return hci_sendCommand(OGF_LE_CTL, OCF_LE_SET_ADVERTISING_DATA, sizeof(leAdvertisingData), &leAdvertisingData); } -int HCIClass::leSetScanResponseData(uint8_t length, uint8_t data[]) +int hci_leSetScanResponseData(uint8_t length, uint8_t data[]) { - struct __attribute__ ((packed)) HCILeScanResponseData { - uint8_t length; - uint8_t data[31]; - } leScanResponseData; - - memset(&leScanResponseData, 0, sizeof(leScanResponseData)); - leScanResponseData.length = length; - memcpy(leScanResponseData.data, data, length); - - return sendCommand(OGF_LE_CTL << 10 | OCF_LE_SET_SCAN_RESPONSE_DATA, sizeof(leScanResponseData), &leScanResponseData); -} + struct __attribute__ ((packed)) HCILeScanResponseData { + uint8_t length; + uint8_t data[31]; + } leScanResponseData; -int HCIClass::leSetAdvertiseEnable(uint8_t enable) -{ - return sendCommand(OGF_LE_CTL << 10 | OCF_LE_SET_ADVERTISE_ENABLE, sizeof(enable), &enable); -} + memset(&leScanResponseData, 0, sizeof(leScanResponseData)); + leScanResponseData.length = length; + memcpy(leScanResponseData.data, data, length); -int HCIClass::leSetScanParameters(uint8_t type, uint16_t interval, uint16_t window, - uint8_t ownBdaddrType, uint8_t filter) -{ - struct __attribute__ ((packed)) HCILeSetScanParameters { - uint8_t type; - uint16_t interval; - uint16_t window; - uint8_t ownBdaddrType; - uint8_t filter; - } leScanParameters; - - leScanParameters.type = type; - leScanParameters.interval = interval; - leScanParameters.window = window; - leScanParameters.ownBdaddrType = ownBdaddrType; - leScanParameters.filter = filter; - - return sendCommand(OGF_LE_CTL << 10 | OCF_LE_SET_SCAN_PARAMETERS, sizeof(leScanParameters), &leScanParameters); + return hci_sendCommand(OGF_LE_CTL, OCF_LE_SET_SCAN_RESPONSE_DATA, sizeof(leScanResponseData), &leScanResponseData); } -int HCIClass::leSetScanEnable(uint8_t enabled, uint8_t duplicates) +int hci_leSetAdvertiseEnable(uint8_t enable) { - struct __attribute__ ((packed)) HCILeSetScanEnableData { - uint8_t enabled; - uint8_t duplicates; - } leScanEnableData; - - leScanEnableData.enabled = enabled; - leScanEnableData.duplicates = duplicates; - - return sendCommand(OGF_LE_CTL << 10 | OCF_LE_SET_SCAN_ENABLE, sizeof(leScanEnableData), &leScanEnableData); + return hci_sendCommand(OGF_LE_CTL, OCF_LE_SET_ADVERTISE_ENABLE, sizeof(enable), &enable); } -int HCIClass::leCreateConn(uint16_t interval, uint16_t window, uint8_t initiatorFilter, - uint8_t peerBdaddrType, uint8_t peerBdaddr[6], uint8_t ownBdaddrType, - uint16_t minInterval, uint16_t maxInterval, uint16_t latency, - uint16_t supervisionTimeout, uint16_t minCeLength, uint16_t maxCeLength) +int hci_leSetScanParameters(uint8_t type, uint16_t interval, uint16_t window, + uint8_t ownBdaddrType, uint8_t filter) { - struct __attribute__ ((packed)) HCILeCreateConnData { - uint16_t interval; - uint16_t window; - uint8_t initiatorFilter; - uint8_t peerBdaddrType; - uint8_t peerBdaddr[6]; - uint8_t ownBdaddrType; - uint16_t minInterval; - uint16_t maxInterval; - uint16_t latency; - uint16_t supervisionTimeout; - uint16_t minCeLength; - uint16_t maxCeLength; - } leCreateConnData; - - leCreateConnData.interval = interval; - leCreateConnData.window = window; - leCreateConnData.initiatorFilter = initiatorFilter; - leCreateConnData.peerBdaddrType = peerBdaddrType; - memcpy(leCreateConnData.peerBdaddr, peerBdaddr, sizeof(leCreateConnData.peerBdaddr)); - leCreateConnData.ownBdaddrType = ownBdaddrType; - leCreateConnData.minInterval = minInterval; - leCreateConnData.maxInterval = maxInterval; - leCreateConnData.latency = latency; - leCreateConnData.supervisionTimeout = supervisionTimeout; - leCreateConnData.minCeLength = minCeLength; - leCreateConnData.maxCeLength = maxCeLength; - - return sendCommand(OGF_LE_CTL << 10 | OCF_LE_CREATE_CONN, sizeof(leCreateConnData), &leCreateConnData); + struct __attribute__ ((packed)) HCILeSetScanParameters { + uint8_t type; + uint16_t interval; + uint16_t window; + uint8_t ownBdaddrType; + uint8_t filter; + } leScanParameters; + + leScanParameters.type = type; + leScanParameters.interval = interval; + leScanParameters.window = window; + leScanParameters.ownBdaddrType = ownBdaddrType; + leScanParameters.filter = filter; + + return hci_sendCommand(OGF_LE_CTL, OCF_LE_SET_SCAN_PARAMETERS, sizeof(leScanParameters), &leScanParameters); } -int HCIClass::leCancelConn() +int hci_leSetScanEnable(uint8_t enabled, uint8_t duplicates) { - return sendCommand(OGF_LE_CTL << 10 | OCF_LE_CANCEL_CONN, 0, NULL); -} + struct __attribute__ ((packed)) HCILeSetScanEnableData { + uint8_t enabled; + uint8_t duplicates; + } leScanEnableData; -int HCIClass::leConnUpdate(uint16_t handle, uint16_t minInterval, uint16_t maxInterval, - uint16_t latency, uint16_t supervisionTimeout) -{ - struct __attribute__ ((packed)) HCILeConnUpdateData { - uint16_t handle; - uint16_t minInterval; - uint16_t maxInterval; - uint16_t latency; - uint16_t supervisionTimeout; - uint16_t minCeLength; - uint16_t maxCeLength; - } leConnUpdateData; - - leConnUpdateData.handle = handle; - leConnUpdateData.minInterval = minInterval; - leConnUpdateData.maxInterval = maxInterval; - leConnUpdateData.latency = latency; - leConnUpdateData.supervisionTimeout = supervisionTimeout; - leConnUpdateData.minCeLength = 0x0004; - leConnUpdateData.maxCeLength = 0x0006; - - return sendCommand(OGF_LE_CTL << 10 | OCF_LE_CONN_UPDATE, sizeof(leConnUpdateData), &leConnUpdateData); -} + leScanEnableData.enabled = enabled; + leScanEnableData.duplicates = duplicates; -int HCIClass::sendAclPkt(uint16_t handle, uint8_t cid, uint8_t plen, void* data) -{ - while (_pendingPkt >= _maxPkt) { - poll(); - } - - struct __attribute__ ((packed)) HCIACLHdr { - uint8_t pktType; - uint16_t handle; - uint16_t dlen; - uint16_t plen; - uint16_t cid; - } aclHdr = { HCI_ACLDATA_PKT, handle, uint8_t(plen + 4), plen, cid }; - - uint8_t txBuffer[sizeof(aclHdr) + plen]; - memcpy(txBuffer, &aclHdr, sizeof(aclHdr)); - memcpy(&txBuffer[sizeof(aclHdr)], data, plen); - - if (_debug) { - dumpPkt("HCI ACLDATA TX -> ", sizeof(aclHdr) + plen, txBuffer); - } - - _pendingPkt++; - HCITransport.write(txBuffer, sizeof(aclHdr) + plen); - - return 0; + return hci_sendCommand(OGF_LE_CTL, OCF_LE_SET_SCAN_ENABLE, sizeof(leScanEnableData), &leScanEnableData); } -int HCIClass::disconnect(uint16_t handle) +int hci_leCreateConn(uint16_t interval, uint16_t window, uint8_t initiatorFilter, + uint8_t peerBdaddrType, uint8_t peerBdaddr[6], uint8_t ownBdaddrType, + uint16_t minInterval, uint16_t maxInterval, uint16_t latency, + uint16_t supervisionTimeout, uint16_t minCeLength, uint16_t maxCeLength) { - struct __attribute__ ((packed)) HCIDisconnectData { - uint16_t handle; - uint8_t reason; - } disconnectData = { handle, HCI_OE_USER_ENDED_CONNECTION }; - - return sendCommand(OGF_LINK_CTL << 10 | OCF_DISCONNECT, sizeof(disconnectData), &disconnectData); + struct __attribute__ ((packed)) HCILeCreateConnData { + uint16_t interval; + uint16_t window; + uint8_t initiatorFilter; + uint8_t peerBdaddrType; + uint8_t peerBdaddr[6]; + uint8_t ownBdaddrType; + uint16_t minInterval; + uint16_t maxInterval; + uint16_t latency; + uint16_t supervisionTimeout; + uint16_t minCeLength; + uint16_t maxCeLength; + } leCreateConnData; + + leCreateConnData.interval = interval; + leCreateConnData.window = window; + leCreateConnData.initiatorFilter = initiatorFilter; + leCreateConnData.peerBdaddrType = peerBdaddrType; + memcpy(leCreateConnData.peerBdaddr, peerBdaddr, sizeof(leCreateConnData.peerBdaddr)); + leCreateConnData.ownBdaddrType = ownBdaddrType; + leCreateConnData.minInterval = minInterval; + leCreateConnData.maxInterval = maxInterval; + leCreateConnData.latency = latency; + leCreateConnData.supervisionTimeout = supervisionTimeout; + leCreateConnData.minCeLength = minCeLength; + leCreateConnData.maxCeLength = maxCeLength; + + return hci_sendCommand(OGF_LE_CTL, OCF_LE_CREATE_CONN, sizeof(leCreateConnData), &leCreateConnData); } -void HCIClass::debug(Stream& stream) +int hci_leCancelConn() { - _debug = &stream; + return hci_sendCommand(OGF_LE_CTL, OCF_LE_CANCEL_CONN, 0, NULL); } -void HCIClass::noDebug() +int hci_leConnUpdate(uint16_t handle, uint16_t minInterval, uint16_t maxInterval, + uint16_t latency, uint16_t supervisionTimeout) { - _debug = NULL; + struct __attribute__ ((packed)) HCILeConnUpdateData { + uint16_t handle; + uint16_t minInterval; + uint16_t maxInterval; + uint16_t latency; + uint16_t supervisionTimeout; + uint16_t minCeLength; + uint16_t maxCeLength; + } leConnUpdateData; + + leConnUpdateData.handle = handle; + leConnUpdateData.minInterval = minInterval; + leConnUpdateData.maxInterval = maxInterval; + leConnUpdateData.latency = latency; + leConnUpdateData.supervisionTimeout = supervisionTimeout; + leConnUpdateData.minCeLength = 0x0004; + leConnUpdateData.maxCeLength = 0x0006; + + return hci_sendCommand(OGF_LE_CTL, OCF_LE_CONN_UPDATE, sizeof(leConnUpdateData), &leConnUpdateData); } -int HCIClass::sendCommand(uint16_t opcode, uint8_t plen, void* parameters) -{ - struct __attribute__ ((packed)) { - uint8_t pktType; - uint16_t opcode; - uint8_t plen; - } pktHdr = {HCI_COMMAND_PKT, opcode, plen}; - - uint8_t txBuffer[sizeof(pktHdr) + plen]; - memcpy(txBuffer, &pktHdr, sizeof(pktHdr)); - memcpy(&txBuffer[sizeof(pktHdr)], parameters, plen); - - if (_debug) { - dumpPkt("HCI COMMAND TX -> ", sizeof(pktHdr) + plen, txBuffer); - } - - HCITransport.write(txBuffer, sizeof(pktHdr) + plen); - - _cmdCompleteOpcode = 0xffff; - _cmdCompleteStatus = -1; - - for (unsigned long start = millis(); _cmdCompleteOpcode != opcode && millis() < (start + 1000);) { - poll(); - } +int hci_sendAclPkt(uint16_t handle, uint8_t cid, uint8_t plen, void* data) { + while (pending_pkt >= max_pkt) { + hci_poll(); + } - return _cmdCompleteStatus; -} + typedef struct __attribute__ ((packed)) { + uint8_t pktType; + uint16_t handle; + uint16_t dlen; + uint16_t plen; + uint16_t cid; + } HCIACLHdr; -void HCIClass::handleAclDataPkt(uint8_t /*plen*/, uint8_t pdata[]) -{ - struct __attribute__ ((packed)) HCIACLHdr { - uint16_t handle; - uint16_t dlen; - uint16_t len; - uint16_t cid; - } *aclHdr = (HCIACLHdr*)pdata; - - uint16_t aclFlags = (aclHdr->handle & 0xf000) >> 12; - - if ((aclHdr->dlen - 4) != aclHdr->len) { - // packet is fragmented - if (aclFlags != 0x01) { - // copy into ACL buffer - memcpy(_aclPktBuffer, &_recvBuffer[1], sizeof(HCIACLHdr) + aclHdr->dlen - 4); - } else { - // copy next chunk into the buffer - HCIACLHdr* aclBufferHeader = (HCIACLHdr*)_aclPktBuffer; + HCIACLHdr aclHdr = { HCI_ACLDATA_PKT, handle, (uint8_t)(plen + 4), plen, cid }; - memcpy(&_aclPktBuffer[sizeof(HCIACLHdr) + aclBufferHeader->dlen - 4], &_recvBuffer[1 + sizeof(aclHdr->handle) + sizeof(aclHdr->dlen)], aclHdr->dlen); + uint8_t txBuffer[sizeof(aclHdr) + plen]; + memcpy(txBuffer, &aclHdr, sizeof(aclHdr)); + memcpy(&txBuffer[sizeof(aclHdr)], data, plen); - aclBufferHeader->dlen += aclHdr->dlen; - aclHdr = aclBufferHeader; + if (debug) { + dumpPkt("HCI ACLDATA TX -> ", sizeof(aclHdr) + plen, txBuffer); } - } - if ((aclHdr->dlen - 4) != aclHdr->len) { - // don't have the full packet yet - return; - } + pending_pkt++; - if (aclHdr->cid == ATT_CID) { - if (aclFlags == 0x01) { - // use buffered packet - ATT.handleData(aclHdr->handle & 0x0fff, aclHdr->len, &_aclPktBuffer[sizeof(HCIACLHdr)]); - } else { - // use the recv buffer - ATT.handleData(aclHdr->handle & 0x0fff, aclHdr->len, &_recvBuffer[1 + sizeof(HCIACLHdr)]); + int errcode = 0; + common_hal_busio_uart_write(&adapter->hci_uart, txBuffer, sizeof(aclHdr) + plen, &errcode); + if (errcode) { + return -1; } - } else if (aclHdr->cid == SIGNALING_CID) { - L2CAPSignaling.handleData(aclHdr->handle & 0x0fff, aclHdr->len, &_recvBuffer[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); - } -} -void HCIClass::handleNumCompPkts(uint16_t /*handle*/, uint16_t numPkts) -{ - if (numPkts && _pendingPkt > numPkts) { - _pendingPkt -= numPkts; - } else { - _pendingPkt = 0; - } + return 0; } -void HCIClass::handleEventPkt(uint8_t /*plen*/, uint8_t pdata[]) +int hci_disconnect(uint16_t handle) { - struct __attribute__ ((packed)) HCIEventHdr { - uint8_t evt; - uint8_t plen; - } *eventHdr = (HCIEventHdr*)pdata; - - if (eventHdr->evt == EVT_DISCONN_COMPLETE) { - struct __attribute__ ((packed)) DisconnComplete { - uint8_t status; - uint16_t handle; - uint8_t reason; - } *disconnComplete = (DisconnComplete*)&pdata[sizeof(HCIEventHdr)]; - - ATT.removeConnection(disconnComplete->handle, disconnComplete->reason); - L2CAPSignaling.removeConnection(disconnComplete->handle, disconnComplete->reason); - - HCI.leSetAdvertiseEnable(0x01); - } else if (eventHdr->evt == EVT_CMD_COMPLETE) { - struct __attribute__ ((packed)) CmdComplete { - uint8_t ncmd; - uint16_t opcode; - uint8_t status; - } *cmdCompleteHeader = (CmdComplete*)&pdata[sizeof(HCIEventHdr)]; - - _cmdCompleteOpcode = cmdCompleteHeader->opcode; - _cmdCompleteStatus = cmdCompleteHeader->status; - _cmdResponseLen = pdata[1] - sizeof(CmdComplete); - _cmdResponse = &pdata[sizeof(HCIEventHdr) + sizeof(CmdComplete)]; - - } else if (eventHdr->evt == EVT_CMD_STATUS) { - struct __attribute__ ((packed)) CmdStatus { - uint8_t status; - uint8_t ncmd; - uint16_t opcode; - } *cmdStatusHeader = (CmdStatus*)&pdata[sizeof(HCIEventHdr)]; - - _cmdCompleteOpcode = cmdStatusHeader->opcode; - _cmdCompleteStatus = cmdStatusHeader->status; - _cmdResponseLen = 0; - } else if (eventHdr->evt == EVT_NUM_COMP_PKTS) { - uint8_t numHandles = pdata[sizeof(HCIEventHdr)]; - uint16_t* data = (uint16_t*)&pdata[sizeof(HCIEventHdr) + sizeof(numHandles)]; - - for (uint8_t i = 0; i < numHandles; i++) { - handleNumCompPkts(data[0], data[1]); - - data += 2; - } - } else if (eventHdr->evt == EVT_LE_META_EVENT) { - struct __attribute__ ((packed)) LeMetaEventHeader { - uint8_t subevent; - } *leMetaHeader = (LeMetaEventHeader*)&pdata[sizeof(HCIEventHdr)]; - - if (leMetaHeader->subevent == EVT_LE_CONN_COMPLETE) { - struct __attribute__ ((packed)) EvtLeConnectionComplete { - uint8_t status; + struct __attribute__ ((packed)) HCIDisconnectData { uint16_t handle; - uint8_t role; - uint8_t peerBdaddrType; - uint8_t peerBdaddr[6]; - uint16_t interval; - uint16_t latency; - uint16_t supervisionTimeout; - uint8_t masterClockAccuracy; - } *leConnectionComplete = (EvtLeConnectionComplete*)&pdata[sizeof(HCIEventHdr) + sizeof(LeMetaEventHeader)]; - - if (leConnectionComplete->status == 0x00) { - ATT.addConnection(leConnectionComplete->handle, - leConnectionComplete->role, - leConnectionComplete->peerBdaddrType, - leConnectionComplete->peerBdaddr, - leConnectionComplete->interval, - leConnectionComplete->latency, - leConnectionComplete->supervisionTimeout, - leConnectionComplete->masterClockAccuracy); - - L2CAPSignaling.addConnection(leConnectionComplete->handle, - leConnectionComplete->role, - leConnectionComplete->peerBdaddrType, - leConnectionComplete->peerBdaddr, - leConnectionComplete->interval, - leConnectionComplete->latency, - leConnectionComplete->supervisionTimeout, - leConnectionComplete->masterClockAccuracy); - } - } else if (leMetaHeader->subevent == EVT_LE_ADVERTISING_REPORT) { - struct __attribute__ ((packed)) EvtLeAdvertisingReport { - uint8_t status; - uint8_t type; - uint8_t peerBdaddrType; - uint8_t peerBdaddr[6]; - uint8_t eirLength; - uint8_t eirData[31]; - } *leAdvertisingReport = (EvtLeAdvertisingReport*)&pdata[sizeof(HCIEventHdr) + sizeof(LeMetaEventHeader)]; - - if (leAdvertisingReport->status == 0x01) { - // last byte is RSSI - int8_t rssi = leAdvertisingReport->eirData[leAdvertisingReport->eirLength]; - - GAP.handleLeAdvertisingReport(leAdvertisingReport->type, - leAdvertisingReport->peerBdaddrType, - leAdvertisingReport->peerBdaddr, - leAdvertisingReport->eirLength, - leAdvertisingReport->eirData, - rssi); - - } - } - } -} - -void HCIClass::dumpPkt(const char* prefix, uint8_t plen, uint8_t pdata[]) -{ - if (_debug) { - _debug->print(prefix); - - for (uint8_t i = 0; i < plen; i++) { - byte b = pdata[i]; - - if (b < 16) { - _debug->print("0"); - } - - _debug->print(b, HEX); - } + uint8_t reason; + } disconnectData = { handle, HCI_OE_USER_ENDED_CONNECTION }; - _debug->println(); - _debug->flush(); - } + return hci_sendCommand(OGF_LINK_CTL, OCF_DISCONNECT, sizeof(disconnectData), &disconnectData); } -` diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index 5f901a199..cce89a7ac 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -248,7 +248,7 @@ endif SRC_ASF := $(addprefix asf4/$(CHIP_FAMILY)/, $(SRC_ASF)) -SRC_C = \ +SRC_C += \ audio_dma.c \ background.c \ bindings/samd/Clock.c \ diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 38ef37312..b30159c7c 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -318,8 +318,8 @@ SRC_COMMON_HAL_ALL = \ watchdog/__init__.c \ ifeq ($(CIRCUITPY_BLEIO_HCI),1) -SRC_C +=\ - common_hal/_bleio/hci.c \ +SRC_C += \ + common-hal/_bleio/hci.c \ endif diff --git a/shared-bindings/_bleio/Adapter.c b/shared-bindings/_bleio/Adapter.c index 911fa6d35..1b991ac6d 100644 --- a/shared-bindings/_bleio/Adapter.c +++ b/shared-bindings/_bleio/Adapter.c @@ -64,20 +64,20 @@ //| advertisements and it can advertise its own data. Furthermore, Adapters can accept incoming //| connections and also initiate connections.""" //| - -//| def __init__(self, *, tx: Pin, rx: Pin, rts: Pin, cts: Pin, baudrate: int = 115200, buffer_size: int = 256): //| You cannot create an instance of `_bleio.Adapter`. //| Use `_bleio.adapter` to access the sole instance available.""" //| -//| On boards that do not have native BLE. You can use HCI co-processor. + +//| def hci_init(self, *, tx: Pin, rx: Pin, rts: Pin, cts: Pin, baudrate: int = 115200, buffer_size: int = 256): +//| On boards that do not have native BLE, you can an use HCI co-processor. //| Call `_bleio.adapter.hci_init()` passing it the 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 `tx`, `rx`, `rts`, and `cs` pins are used to communicate with the HCI co-processor in HCI mode. //| -#if CIRCUITPY_BLEIO_HCI mp_obj_t bleio_adapter_hci_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { +#if CIRCUITPY_BLEIO_HCI bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); if (self->enabled) { @@ -114,10 +114,14 @@ mp_obj_t bleio_adapter_hci_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_m common_hal_bleio_adapter_hci_init(&common_hal_bleio_adapter_obj, tx, rx, rts, cts, baudrate, buffer_size); + + return mp_const_none; +#else + mp_raise_RuntimeError(translate("hci_init not available")); return mp_const_none; +#endif // CIRCUITPY_BLEIO_HCI } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_adapter_hci_init_obj, 1, bleio_adapter_hci_init); -#endif // CIRCUITPY_BLEIO_HCI //| //| enabled: Any = ... diff --git a/shared-bindings/_bleio/__init__.c b/shared-bindings/_bleio/__init__.c index 90b185f79..29405ecad 100644 --- a/shared-bindings/_bleio/__init__.c +++ b/shared-bindings/_bleio/__init__.c @@ -112,7 +112,10 @@ NORETURN void mp_raise_bleio_SecurityError(const compressed_string_t* fmt, ...) // Called when _bleio is imported. STATIC mp_obj_t bleio___init__(void) { +#if !CIRCUITPY_BLEIO_HCI + // HCI cannot be enabled on import, because we need to setup the HCI adapter first. 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__); -- cgit v1.2.3 From f6869c69c5fda701b57fbfca0eaf1aa03a2d164b Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sun, 12 Jul 2020 19:45:23 -0400 Subject: wip: advertising; not tested --- devices/ble_hci/common-hal/_bleio/Adapter.c | 351 ++++++++++++--------- devices/ble_hci/common-hal/_bleio/Adapter.h | 18 +- devices/ble_hci/common-hal/_bleio/__init__.c | 7 + devices/ble_hci/common-hal/_bleio/__init__.h | 1 + devices/ble_hci/common-hal/_bleio/hci_api.c | 63 +++- devices/ble_hci/common-hal/_bleio/hci_api.h | 11 +- .../ble_hci/common-hal/_bleio/hci_include/hci.h | 2 + ports/atmel-samd/background.c | 24 +- ports/cxd56/background.c | 4 + ports/esp32s2/background.c | 4 + ports/litex/background.c | 13 +- ports/mimxrt10xx/background.c | 18 +- ports/nrf/background.c | 3 +- ports/nrf/common-hal/_bleio/__init__.c | 5 + ports/nrf/common-hal/_bleio/__init__.h | 1 + ports/stm/background.c | 13 +- shared-bindings/_bleio/Adapter.c | 14 + supervisor/shared/bluetooth.c | 1 - supervisor/shared/bluetooth.h | 3 +- 19 files changed, 378 insertions(+), 178 deletions(-) (limited to 'ports') diff --git a/devices/ble_hci/common-hal/_bleio/Adapter.c b/devices/ble_hci/common-hal/_bleio/Adapter.c index c08eb2db4..7817ea470 100644 --- a/devices/ble_hci/common-hal/_bleio/Adapter.c +++ b/devices/ble_hci/common-hal/_bleio/Adapter.c @@ -48,6 +48,21 @@ #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) + +// 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 @@ -158,32 +173,66 @@ bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT]; // return true; // } -// STATIC void get_address(bleio_adapter_obj_t *self, ble_gap_addr_t *address) { -// check_nrf_error(sd_ble_gap_addr_get(address)); -// } - char default_ble_name[] = { 'C', 'I', 'R', 'C', 'U', 'I', 'T', 'P', 'Y', 0, 0, 0, 0 , 0}; -// STATIC void bleio_adapter_reset_name(bleio_adapter_obj_t *self) { -// // uint8_t len = sizeof(default_ble_name) - 1; +STATIC void bleio_adapter_reset_name(bleio_adapter_obj_t *self) { + uint8_t len = sizeof(default_ble_name) - 1; + + bt_addr_t addr; + check_hci_error(hci_read_bd_addr(&addr)); -// // ble_gap_addr_t local_address; -// // get_address(self, &local_address); + 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]; + default_ble_name[len] = '\0'; // for now we add null for compatibility with C ASCIIZ strings -// // default_ble_name[len - 4] = nibble_to_hex_lower[local_address.addr[1] >> 4 & 0xf]; -// // default_ble_name[len - 3] = nibble_to_hex_lower[local_address.addr[1] & 0xf]; -// // default_ble_name[len - 2] = nibble_to_hex_lower[local_address.addr[0] >> 4 & 0xf]; -// // default_ble_name[len - 1] = nibble_to_hex_lower[local_address.addr[0] & 0xf]; -// // default_ble_name[len] = '\0'; // for now we add null for compatibility with C ASCIIZ strings + common_hal_bleio_adapter_set_name(self, (char*) default_ble_name); +} -// common_hal_bleio_adapter_set_name(self, (char*) default_ble_name); -// } +// Get various values and limits set by the adapter. +STATIC void bleio_adapter_get_info(bleio_adapter_obj_t *self) { + + // 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. + 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; +} void common_hal_bleio_adapter_hci_uart_init(bleio_adapter_obj_t *self, busio_uart_obj_t *uart, digitalio_digitalinout_obj_t *rts, digitalio_digitalinout_obj_t *cts) { self->hci_uart = uart; self->rts_digitalinout = rts; self->cts_digitalinout = cts; self->enabled = false; + self->now_advertising = false; + self->circuitpython_advertising = false; + self->extended_advertising = false; + self->advertising_timeout_msecs = 0; + + bleio_adapter_get_info(self); + + bleio_adapter_reset_name(self); } void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enabled) { @@ -196,6 +245,13 @@ void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enable //FIX enable/disable HCI adapter, but don't reset it, since we don't know how. self->enabled = enabled; + if (!enabled) { + // Stop any current activity. + check_hci_error(hci_reset()); + self->now_advertising = false; + self->extended_advertising = false; + self->circuitpython_advertising = false; + } } bool common_hal_bleio_adapter_get_enabled(bleio_adapter_obj_t *self) { @@ -221,6 +277,7 @@ void common_hal_bleio_adapter_set_name(bleio_adapter_obj_t *self, const char* na self->name = mp_obj_new_str(name, strlen(name)); } + // 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; @@ -262,6 +319,7 @@ mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t* 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; @@ -298,9 +356,8 @@ mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t* } void common_hal_bleio_adapter_stop_scan(bleio_adapter_obj_t *self) { - // sd_ble_gap_scan_stop(); + check_hci_error(hci_le_set_scan_enable(BT_HCI_LE_SCAN_DISABLE, BT_HCI_LE_SCAN_FILTER_DUP_DISABLE)); shared_module_bleio_scanresults_set_done(self->scan_results, true); - // ble_drv_remove_event_handler(scan_on_ble_evt, self->scan_results); self->scan_results = NULL; } @@ -431,99 +488,123 @@ STATIC void check_data_fit(size_t data_len, bool connectable) { // } 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) { - // if (self->current_advertising_data != NULL && self->current_advertising_data == self->advertising_data) { - // return NRF_ERROR_BUSY; - // } + 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; + } + } - // // If the current advertising data isn't owned by the adapter then it must be an internal - // // advertisement that we should stop. - // if (self->current_advertising_data != NULL) { - // common_hal_bleio_adapter_stop_advertising(self); - // } + // Peer address, which we don't use (no directed advertising). + bt_addr_le_t empty_addr = { 0 }; - // uint32_t err_code; - // bool extended = advertising_data_len > BLE_GAP_ADV_SET_DATA_SIZE_MAX || - // scan_response_data_len > BLE_GAP_ADV_SET_DATA_SIZE_MAX; - - // uint8_t adv_type; - // if (extended) { - // if (connectable) { - // adv_type = BLE_GAP_ADV_TYPE_EXTENDED_CONNECTABLE_NONSCANNABLE_UNDIRECTED; - // } else if (scan_response_data_len > 0) { - // adv_type = BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_SCANNABLE_UNDIRECTED; - // } else { - // adv_type = BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED; - // } - // } else if (connectable) { - // adv_type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED; - // } else if (scan_response_data_len > 0) { - // adv_type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_SCANNABLE_UNDIRECTED; - // } else { - // adv_type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED; - // } + bool extended = + advertising_data_len > self->max_adv_data_len || scan_response_data_len > self->max_adv_data_len; - // if (anonymous) { - // ble_gap_privacy_params_t privacy = { - // .privacy_mode = BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY, - // .private_addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE, - // // Rotate the keys one second after we're scheduled to stop - // // advertising. This prevents a potential race condition where we - // // fire off a beacon with the same advertising data but a new MAC - // // address just as we tear down the connection. - // .private_addr_cycle_s = timeout + 1, - // .p_device_irk = NULL, - // }; - // err_code = sd_ble_gap_privacy_set(&privacy); - // } else { - // ble_gap_privacy_params_t privacy = { - // .privacy_mode = BLE_GAP_PRIVACY_MODE_OFF, - // .private_addr_type = BLE_GAP_ADDR_TYPE_PUBLIC, - // .private_addr_cycle_s = 0, - // .p_device_irk = NULL, - // }; - // err_code = sd_ble_gap_privacy_set(&privacy); - // } - // if (err_code != NRF_SUCCESS) { - // return err_code; - // } + if (extended) { + 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; + } - // ble_gap_adv_params_t adv_params = { - // .interval = SEC_TO_UNITS(interval, UNIT_0_625_MS), - // .properties.type = adv_type, - // .duration = SEC_TO_UNITS(timeout, UNIT_10_MS), - // .filter_policy = BLE_GAP_ADV_FP_ANY, - // .primary_phy = BLE_GAP_PHY_1MBPS, - // }; + // Advertising interval. + uint32_t interval_units = SEC_TO_UNITS(interval, UNIT_0_625_MS); + + check_hci_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 }; + check_hci_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; + } - // const ble_gap_adv_data_t ble_gap_adv_data = { - // .adv_data.p_data = advertising_data, - // .adv_data.len = advertising_data_len, - // .scan_rsp_data.p_data = scan_response_data_len > 0 ? scan_response_data : NULL, - // .scan_rsp_data.len = scan_response_data_len, - // }; + // Advertising interval. + uint16_t interval_units = SEC_TO_UNITS(interval, UNIT_0_625_MS); + + check_hci_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 31 octets, even though the actual data length may be shorter. + uint8_t full_data[31] = { 0 }; + memcpy(full_data, advertising_data, MIN(sizeof(full_data), advertising_data_len)); + check_hci_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, advertising_data, MIN(sizeof(full_data), scan_response_data_len)); + check_hci_error(hci_le_set_scan_response_data(scan_response_data_len, full_data)); + } - // err_code = sd_ble_gap_adv_set_configure(&adv_handle, &ble_gap_adv_data, &adv_params); - // if (err_code != NRF_SUCCESS) { - // return err_code; - // } + // 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(); - // ble_drv_add_event_handler(advertising_on_ble_evt, self); + // Start advertising. + check_hci_error(hci_le_set_advertising_enable(BT_HCI_LE_ADV_ENABLE)); + self->extended_advertising = false; + } // end legacy advertising setup - // vm_used_ble = true; - // err_code = sd_ble_gap_adv_start(adv_handle, BLE_CONN_CFG_TAG_CUSTOM); - // if (err_code != NRF_SUCCESS) { - // return err_code; - // } - // self->current_advertising_data = advertising_data; - // return NRF_SUCCESS; + 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) { - if (self->current_advertising_data != NULL && self->current_advertising_data == self->advertising_data) { - mp_raise_bleio_BluetoothError(translate("Already advertising.")); - } // interval value has already been validated. check_data_fit(advertising_data_bufinfo->len, connectable); @@ -536,58 +617,38 @@ void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool // 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) { - //FIX if (anonymous) { - // // The Nordic macro is in units of 10ms. Convert to seconds. - // uint32_t adv_timeout_max_secs = UNITS_TO_SEC(BLE_GAP_ADV_TIMEOUT_LIMITED_MAX, UNIT_10_MS); - // uint32_t rotate_timeout_max_secs = BLE_GAP_DEFAULT_PRIVATE_ADDR_CYCLE_INTERVAL_S; - // timeout = MIN(adv_timeout_max_secs, rotate_timeout_max_secs); - // } - // else { - // timeout = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED; - // } + if (timeout == 0 && anonymous) { + timeout = MAX_ANONYMOUS_ADV_TIMEOUT_SECS; } else { - //FIX if (SEC_TO_UNITS(timeout, UNIT_10_MS) > BLE_GAP_ADV_TIMEOUT_LIMITED_MAX) { - // mp_raise_bleio_BluetoothError(translate("Timeout is too long: Maximum timeout length is %d seconds"), - // UNITS_TO_SEC(BLE_GAP_ADV_TIMEOUT_LIMITED_MAX, UNIT_10_MS)); - // } + 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); + } } - // The advertising data buffers must not move, because the SoftDevice depends on them. - // So make them long-lived and reuse them onwards. - //FIX GET CORRECT SIZE - // if (self->advertising_data == NULL) { - // self->advertising_data = (uint8_t *) gc_alloc(BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_MAX_SUPPORTED * sizeof(uint8_t), false, true); - // } - // if (self->scan_response_data == NULL) { - // self->scan_response_data = (uint8_t *) gc_alloc(BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_MAX_SUPPORTED * sizeof(uint8_t), false, true); - // } + 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); - memcpy(self->advertising_data, advertising_data_bufinfo->buf, advertising_data_bufinfo->len); - memcpy(self->scan_response_data, scan_response_data_bufinfo->buf, scan_response_data_bufinfo->len); - - // check_nrf_error(_common_hal_bleio_adapter_start_advertising(self, connectable, anonymous, timeout, interval, - // self->advertising_data, - // advertising_data_bufinfo->len, - // self->scan_response_data, - // 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) { - // if (adv_handle == BLE_GAP_ADV_SET_HANDLE_NOT_SET) - // return; - - // // TODO: Don't actually stop. Switch to advertising CircuitPython if we don't already have a connection. - // const uint32_t err_code = sd_ble_gap_adv_stop(adv_handle); - // self->current_advertising_data = NULL; - - // if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_INVALID_STATE)) { - // check_nrf_error(err_code); - // } + self->now_advertising = false; + self->extended_advertising = false; + self->circuitpython_advertising = false; + check_hci_error(hci_le_set_advertising_enable(BT_HCI_LE_ADV_DISABLE)); + //TODO startup CircuitPython advertising again. } bool common_hal_bleio_adapter_get_advertising(bleio_adapter_obj_t *self) { - return self->current_advertising_data != NULL; + return self->now_advertising; } bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self) { @@ -631,7 +692,7 @@ void bleio_adapter_gc_collect(bleio_adapter_obj_t* adapter) { void bleio_adapter_reset(bleio_adapter_obj_t* adapter) { common_hal_bleio_adapter_stop_scan(adapter); - if (adapter->current_advertising_data != NULL) { + if (adapter->now_advertising) { common_hal_bleio_adapter_stop_advertising(adapter); } @@ -646,3 +707,11 @@ void bleio_adapter_reset(bleio_adapter_obj_t* adapter) { connection->connection_obj = mp_const_none; } } + +void bleio_adapter_background(bleio_adapter_obj_t* adapter) { + 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); + } +} diff --git a/devices/ble_hci/common-hal/_bleio/Adapter.h b/devices/ble_hci/common-hal/_bleio/Adapter.h index dbec03bd8..8e34f8663 100644 --- a/devices/ble_hci/common-hal/_bleio/Adapter.h +++ b/devices/ble_hci/common-hal/_bleio/Adapter.h @@ -43,20 +43,32 @@ extern bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT]; + + typedef struct _bleio_adapter_obj_t { mp_obj_base_t base; - uint8_t* advertising_data; - uint8_t* scan_response_data; - uint8_t* current_advertising_data; 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 now_advertising; + bool extended_advertising; + bool circuitpython_advertising; bool enabled; + + // Used to monitor advertising timeout for legacy avertising. + uint64_t advertising_start_ticks; + uint64_t advertising_timeout_msecs; // If zero, do not check. + + uint16_t max_acl_buffer_len; + uint16_t max_acl_num_buffers; + uint16_t max_adv_data_len; + } bleio_adapter_obj_t; +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); diff --git a/devices/ble_hci/common-hal/_bleio/__init__.c b/devices/ble_hci/common-hal/_bleio/__init__.c index e32ca55ec..07aaee747 100644 --- a/devices/ble_hci/common-hal/_bleio/__init__.c +++ b/devices/ble_hci/common-hal/_bleio/__init__.c @@ -263,3 +263,10 @@ void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buff void common_hal_bleio_gc_collect(void) { bleio_adapter_gc_collect(&common_hal_bleio_adapter_obj); } + + +void bleio_background(void) { + supervisor_bluetooth_background(); + bleio_adapter_background(&common_hal_bleio_adapter_obj); + //FIX bonding_background(); +} diff --git a/devices/ble_hci/common-hal/_bleio/__init__.h b/devices/ble_hci/common-hal/_bleio/__init__.h index 00f5e0c68..0d1c2785f 100644 --- a/devices/ble_hci/common-hal/_bleio/__init__.h +++ b/devices/ble_hci/common-hal/_bleio/__init__.h @@ -31,6 +31,7 @@ #include "hci_api.h" +void bleio_background(void); void bleio_reset(void); typedef struct { diff --git a/devices/ble_hci/common-hal/_bleio/hci_api.c b/devices/ble_hci/common-hal/_bleio/hci_api.c index a82c0c93c..4901ffeed 100644 --- a/devices/ble_hci/common-hal/_bleio/hci_api.c +++ b/devices/ble_hci/common-hal/_bleio/hci_api.c @@ -215,7 +215,7 @@ STATIC void process_evt_pkt(size_t pkt_len, uint8_t pkt[]) //FIX // ATT.removeConnection(disconn_complete->handle, disconn_complete->reason); // L2CAPSignaling.removeConnection(disconn_complete->handle, disconn_complete->reason); - hci_le_set_advertise_enable(0x01); + hci_le_set_advertising_enable(0x01); break; } @@ -365,7 +365,7 @@ hci_result_t hci_poll_for_incoming_pkt(void) { // Stop incoming data while processing packet. common_hal_digitalio_digitalinout_set_value(adapter->rts_digitalinout, true); size_t pkt_len = rx_idx; - // Reset for next pack + // Reset for next packet. rx_idx = 0; switch (rx_buffer[0]) { @@ -395,7 +395,6 @@ hci_result_t hci_poll_for_incoming_pkt(void) { } -// Returns 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(); @@ -555,7 +554,7 @@ hci_result_t hci_set_evt_mask(uint64_t event_mask) { return send_command(BT_HCI_OP_SET_EVENT_MASK, sizeof(event_mask), &event_mask); } -hci_result_t hci_read_le_buffer_size(uint16_t *le_max_len, uint8_t *le_max_num) { +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 = @@ -567,6 +566,20 @@ hci_result_t hci_read_le_buffer_size(uint16_t *le_max_len, uint8_t *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); } @@ -587,7 +600,30 @@ hci_result_t hci_le_set_advertising_parameters(uint16_t min_interval, uint16_t m return send_command(BT_HCI_OP_LE_SET_ADV_PARAM, sizeof(params), ¶ms); } -hci_result_t hci_le_read_maximum_advertising_data_length(int *max_adv_data_len) { +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 = @@ -625,10 +661,25 @@ hci_result_t hci_le_set_scan_response_data(uint8_t len, uint8_t data[]) { return send_command(BT_HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(params), ¶ms); } -hci_result_t hci_le_set_advertise_enable(uint8_t enable) { +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, diff --git a/devices/ble_hci/common-hal/_bleio/hci_api.h b/devices/ble_hci/common-hal/_bleio/hci_api.h index 303f26ba5..23e45375c 100644 --- a/devices/ble_hci/common-hal/_bleio/hci_api.h +++ b/devices/ble_hci/common-hal/_bleio/hci_api.h @@ -45,11 +45,16 @@ 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_maximum_advertising_data_length(int *max_adv_data_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_set_advertise_enable(uint8_t enable); 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_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); @@ -58,7 +63,7 @@ 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_le_buffer_size(uint16_t *le_max_len, uint8_t *le_max_num); +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); diff --git a/devices/ble_hci/common-hal/_bleio/hci_include/hci.h b/devices/ble_hci/common-hal/_bleio/hci_include/hci.h index dbe233fef..2de58b3d8 100644 --- a/devices/ble_hci/common-hal/_bleio/hci_include/hci.h +++ b/devices/ble_hci/common-hal/_bleio/hci_include/hci.h @@ -14,6 +14,8 @@ #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 diff --git a/ports/atmel-samd/background.c b/ports/atmel-samd/background.c index 767c7f3b6..0608cb9bd 100644 --- a/ports/atmel-samd/background.c +++ b/ports/atmel-samd/background.c @@ -35,7 +35,11 @@ #include "supervisor/shared/stack.h" #include "supervisor/port.h" -#ifdef CIRCUITPY_DISPLAYIO +#if CIRCUITPY_BLEIO +#include "common-hal/_bleio/__init__.h" +#endif + +#if CIRCUITPY_DISPLAYIO #include "shared-module/displayio/__init__.h" #endif @@ -77,16 +81,22 @@ void run_background_tasks(void) { assert_heap_ok(); running_background_tasks = true; - #if CIRCUITPY_AUDIOIO || CIRCUITPY_AUDIOBUSIO +#if CIRCUITPY_AUDIOIO || CIRCUITPY_AUDIOBUSIO audio_dma_background(); - #endif - #if CIRCUITPY_DISPLAYIO +#endif + +#if CIRCUITPY_BLEIO + bleio_background(); +#endif + +#if CIRCUITPY_DISPLAYIO displayio_background(); - #endif +#endif - #if CIRCUITPY_NETWORK +#if CIRCUITPY_NETWORK network_module_background(); - #endif +#endif + filesystem_background(); usb_background(); running_background_tasks = false; diff --git a/ports/cxd56/background.c b/ports/cxd56/background.c index ade257dd2..af0957bd0 100644 --- a/ports/cxd56/background.c +++ b/ports/cxd56/background.c @@ -45,6 +45,10 @@ void run_background_tasks(void) { assert_heap_ok(); running_background_tasks = true; +#if CIRCUITPY_BLEIO + bleio_background(); +#endif + usb_background(); filesystem_background(); diff --git a/ports/esp32s2/background.c b/ports/esp32s2/background.c index e22cf4aac..81ebf960f 100644 --- a/ports/esp32s2/background.c +++ b/ports/esp32s2/background.c @@ -54,6 +54,10 @@ void run_background_tasks(void) { running_background_tasks = true; filesystem_background(); +#if CIRCUITPY_BLEIO + bleio_background(); +#endif + // #if CIRCUITPY_DISPLAYIO // displayio_background(); // #endif diff --git a/ports/litex/background.c b/ports/litex/background.c index 8c1897043..b1b765536 100644 --- a/ports/litex/background.c +++ b/ports/litex/background.c @@ -47,13 +47,18 @@ void run_background_tasks(void) { running_background_tasks = true; filesystem_background(); - #if USB_AVAILABLE +#if USB_AVAILABLE usb_background(); - #endif +#endif + +#if CIRCUITPY_BLEIO + bleio_background(); +#endif - #if CIRCUITPY_DISPLAYIO +#if CIRCUITPY_DISPLAYIO displayio_background(); - #endif +#endif + running_background_tasks = false; assert_heap_ok(); diff --git a/ports/mimxrt10xx/background.c b/ports/mimxrt10xx/background.c index ff53ea44f..550009473 100644 --- a/ports/mimxrt10xx/background.c +++ b/ports/mimxrt10xx/background.c @@ -58,16 +58,22 @@ void PLACE_IN_ITCM(run_background_tasks)(void) { assert_heap_ok(); running_background_tasks = true; - #if CIRCUITPY_AUDIOIO || CIRCUITPY_AUDIOBUSIO +#if CIRCUITPY_AUDIOIO || CIRCUITPY_AUDIOBUSIO audio_dma_background(); - #endif - #if CIRCUITPY_DISPLAYIO +#endif + +#if CIRCUITPY_BLEIO + bleio_background(); +#endif + +#if CIRCUITPY_DISPLAYIO displayio_background(); - #endif +#endif - #if CIRCUITPY_NETWORK +#if CIRCUITPY_NETWORK network_module_background(); - #endif +#endif + filesystem_background(); usb_background(); running_background_tasks = false; diff --git a/ports/nrf/background.c b/ports/nrf/background.c index 966c56e0b..faaf80b6c 100644 --- a/ports/nrf/background.c +++ b/ports/nrf/background.c @@ -68,8 +68,7 @@ void run_background_tasks(void) { #endif #if CIRCUITPY_BLEIO - supervisor_bluetooth_background(); - bonding_background(); + bleio_background(); #endif #if CIRCUITPY_DISPLAYIO diff --git a/ports/nrf/common-hal/_bleio/__init__.c b/ports/nrf/common-hal/_bleio/__init__.c index e84bba662..9ac26aee3 100644 --- a/ports/nrf/common-hal/_bleio/__init__.c +++ b/ports/nrf/common-hal/_bleio/__init__.c @@ -244,3 +244,8 @@ void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buff void common_hal_bleio_gc_collect(void) { bleio_adapter_gc_collect(&common_hal_bleio_adapter_obj); } + +void bleio_background(void) { + supervisor_bluetooth_background(); + bonding_background(); +} diff --git a/ports/nrf/common-hal/_bleio/__init__.h b/ports/nrf/common-hal/_bleio/__init__.h index e216795fc..0b2c5334b 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/stm/background.c b/ports/stm/background.c index 8c1897043..b1b765536 100644 --- a/ports/stm/background.c +++ b/ports/stm/background.c @@ -47,13 +47,18 @@ void run_background_tasks(void) { running_background_tasks = true; filesystem_background(); - #if USB_AVAILABLE +#if USB_AVAILABLE usb_background(); - #endif +#endif + +#if CIRCUITPY_BLEIO + bleio_background(); +#endif - #if CIRCUITPY_DISPLAYIO +#if CIRCUITPY_DISPLAYIO displayio_background(); - #endif +#endif + running_background_tasks = false; assert_heap_ok(); diff --git a/shared-bindings/_bleio/Adapter.c b/shared-bindings/_bleio/Adapter.c index 13b84bbac..867304416 100644 --- a/shared-bindings/_bleio/Adapter.c +++ b/shared-bindings/_bleio/Adapter.c @@ -47,6 +47,12 @@ #define INTERVAL_MAX_STRING "40.959375" #define WINDOW_DEFAULT (0.1f) +STATIC void check_enabled(bleio_adapter_obj_t *self) { + if (!common_hal_bleio_adapter_get_enabled(self)) { + mp_raise_bleio_BluetoothError(translate("Adapter not enabled")); + } +} + //| class Adapter: //| """BLE adapter //| @@ -102,6 +108,7 @@ mp_obj_t bleio_adapter_hci_uart_init(mp_uint_t n_args, const mp_obj_t *pos_args, !MP_OBJ_IS_TYPE(cts, &digitalio_digitalinout_type)) { mp_raise_ValueError(translate("Expected a DigitalInOut")); } + check_enabled(self); common_hal_bleio_adapter_hci_uart_init(self, uart, rts, cts); common_hal_bleio_adapter_set_enabled(self, true); @@ -238,6 +245,7 @@ STATIC mp_obj_t bleio_adapter_start_advertising(mp_uint_t n_args, const mp_obj_t mp_raise_bleio_BluetoothError(translate("Cannot have scan responses for extended, connectable advertisements.")); } + check_enabled(self); common_hal_bleio_adapter_start_advertising(self, connectable, anonymous, timeout, interval, &data_bufinfo, &scan_response_bufinfo); @@ -252,6 +260,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_adapter_start_advertising_obj, 2, bleio_ STATIC mp_obj_t bleio_adapter_stop_advertising(mp_obj_t self_in) { bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_enabled(self); common_hal_bleio_adapter_stop_advertising(self); return mp_const_none; @@ -327,6 +336,7 @@ STATIC mp_obj_t bleio_adapter_start_scan(size_t n_args, const mp_obj_t *pos_args } } + check_enabled(self); return common_hal_bleio_adapter_start_scan(self, prefix_bufinfo.buf, prefix_bufinfo.len, args[ARG_extended].u_bool, args[ARG_buffer_size].u_int, timeout, interval, window, args[ARG_minimum_rssi].u_int, args[ARG_active].u_bool); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_adapter_start_scan_obj, 1, bleio_adapter_start_scan); @@ -338,6 +348,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_adapter_start_scan_obj, 1, bleio_adapter STATIC mp_obj_t bleio_adapter_stop_scan(mp_obj_t self_in) { bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_enabled(self); common_hal_bleio_adapter_stop_scan(self); return mp_const_none; @@ -365,6 +376,7 @@ const mp_obj_property_t bleio_adapter_advertising_obj = { //| connection. (read-only)""" //| STATIC mp_obj_t bleio_adapter_get_connected(mp_obj_t self) { + check_enabled(self); return mp_obj_new_bool(common_hal_bleio_adapter_get_connected(self)); } @@ -382,6 +394,7 @@ const mp_obj_property_t bleio_adapter_connected_obj = { //| :py:meth:`_bleio.Adapter.connect`. (read-only)""" //| STATIC mp_obj_t bleio_adapter_get_connections(mp_obj_t self) { + check_enabled(self); return common_hal_bleio_adapter_get_connections(self); } MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_connections_obj, bleio_adapter_get_connections); @@ -419,6 +432,7 @@ STATIC mp_obj_t bleio_adapter_connect(mp_uint_t n_args, const mp_obj_t *pos_args bleio_address_obj_t *address = MP_OBJ_TO_PTR(args[ARG_address].u_obj); mp_float_t timeout = mp_obj_get_float(args[ARG_timeout].u_obj); + check_enabled(self); return common_hal_bleio_adapter_connect(self, address, timeout); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_adapter_connect_obj, 2, bleio_adapter_connect); diff --git a/supervisor/shared/bluetooth.c b/supervisor/shared/bluetooth.c index d2ff55377..56bf32117 100644 --- a/supervisor/shared/bluetooth.c +++ b/supervisor/shared/bluetooth.c @@ -214,7 +214,6 @@ STATIC void close_current_file(void) { uint32_t current_command[1024 / sizeof(uint32_t)]; volatile size_t current_offset; - void supervisor_bluetooth_background(void) { if (!run_ble_background) { return; diff --git a/supervisor/shared/bluetooth.h b/supervisor/shared/bluetooth.h index aa5ae60bf..4c40c65d2 100644 --- a/supervisor/shared/bluetooth.h +++ b/supervisor/shared/bluetooth.h @@ -27,7 +27,8 @@ #ifndef MICROPY_INCLUDED_SUPERVISOR_SHARED_BLUETOOTH_H #define MICROPY_INCLUDED_SUPERVISOR_SHARED_BLUETOOTH_H -void supervisor_start_bluetooth(void); +void bleio_background(void); void supervisor_bluetooth_background(void); +void supervisor_start_bluetooth(void); #endif // MICROPY_INCLUDED_SUPERVISOR_SHARED_BLUETOOTH_H -- cgit v1.2.3 From 6494bbdc64f1633b5935c8b314139c19945328ba Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Thu, 16 Jul 2020 23:14:49 -0400 Subject: snapshot --- devices/ble_hci/common-hal/_bleio/Adapter.c | 9 +- devices/ble_hci/common-hal/_bleio/Characteristic.c | 10 +- devices/ble_hci/common-hal/_bleio/UUID.c | 58 +++----- devices/ble_hci/common-hal/_bleio/UUID.h | 12 +- devices/ble_hci/common-hal/_bleio/hci_api.c | 165 ++++++++++++--------- devices/ble_hci/common-hal/_bleio/hci_api.h | 1 + ports/nrf/common-hal/_bleio/UUID.c | 2 +- shared-bindings/_bleio/UUID.h | 2 +- 8 files changed, 131 insertions(+), 128 deletions(-) (limited to 'ports') diff --git a/devices/ble_hci/common-hal/_bleio/Adapter.c b/devices/ble_hci/common-hal/_bleio/Adapter.c index 92eb42ee0..17b66899a 100644 --- a/devices/ble_hci/common-hal/_bleio/Adapter.c +++ b/devices/ble_hci/common-hal/_bleio/Adapter.c @@ -633,7 +633,12 @@ void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self) { self->now_advertising = false; self->extended_advertising = false; self->circuitpython_advertising = false; - check_hci_error(hci_le_set_advertising_enable(BT_HCI_LE_ADV_DISABLE)); + int result = hci_le_set_advertising_enable(BT_HCI_LE_ADV_DISABLE); + // OK if we're already stopped. + if (result != BT_HCI_ERR_CMD_DISALLOWED) { + check_hci_error(result); + } + //TODO startup CircuitPython advertising again. } @@ -704,4 +709,6 @@ void bleio_adapter_background(bleio_adapter_obj_t* adapter) { adapter->advertising_timeout_msecs = 0; common_hal_bleio_adapter_stop_advertising(adapter); } + + hci_poll_for_incoming_pkt(); } diff --git a/devices/ble_hci/common-hal/_bleio/Characteristic.c b/devices/ble_hci/common-hal/_bleio/Characteristic.c index ff08bf15c..74cbede0e 100644 --- a/devices/ble_hci/common-hal/_bleio/Characteristic.c +++ b/devices/ble_hci/common-hal/_bleio/Characteristic.c @@ -91,12 +91,10 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, self->write_perm = write_perm; self->descriptor_list = NULL; - //FIX - // 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"); - // } + 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; diff --git a/devices/ble_hci/common-hal/_bleio/UUID.c b/devices/ble_hci/common-hal/_bleio/UUID.c index 3f5fbe4fe..d86878e47 100644 --- a/devices/ble_hci/common-hal/_bleio/UUID.c +++ b/devices/ble_hci/common-hal/_bleio/UUID.c @@ -36,55 +36,35 @@ // 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[]) { - //FIX self->nrf_ble_uuid.uuid = uuid16; - // if (uuid128 == NULL) { - // self->nrf_ble_uuid.type = BLE_UUID_TYPE_BLE; - // } else { - // ble_uuid128_t vs_uuid; - // memcpy(vs_uuid.uuid128, uuid128, sizeof(vs_uuid.uuid128)); - - // // Register this vendor-specific UUID. Bytes 12 and 13 will be zero. - // check_nrf_error(sd_ble_uuid_vs_add(&vs_uuid, &self->nrf_ble_uuid.type)); - // vm_used_ble = true; - // } +void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, uint32_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) { - //FIX return self->nrf_ble_uuid.type == BLE_UUID_TYPE_BLE ? 16 : 128; - return 0; + return self->size; } uint32_t common_hal_bleio_uuid_get_uuid16(bleio_uuid_obj_t *self) { - //FIX return self->nrf_ble_uuid.uuid; - return 0; + return self->uuid16; } void common_hal_bleio_uuid_get_uuid128(bleio_uuid_obj_t *self, uint8_t uuid128[16]) { - //FIX uint8_t length; - //FIX check_nrf_error(sd_ble_uuid_encode(&self->nrf_ble_uuid, &length, uuid128)); + memcpy(uuid128, self->uuid128, 16); } void common_hal_bleio_uuid_pack_into(bleio_uuid_obj_t *self, uint8_t* buf) { - //FIX if (self->nrf_ble_uuid.type == BLE_UUID_TYPE_BLE) { - // buf[0] = self->nrf_ble_uuid.uuid & 0xff; - // buf[1] = self->nrf_ble_uuid.uuid >> 8; - // } else { - // common_hal_bleio_uuid_get_uuid128(self, buf); - // } + if (self->size == 16) { + buf[0] = self->uuid16 & 0xff; + buf[1] = self->uuid16 >> 8; + } else { + common_hal_bleio_uuid_get_uuid128(self, buf); + } } - -//FIX -// void bleio_uuid_construct_from_nrf_ble_uuid(bleio_uuid_obj_t *self, ble_uuid_t *nrf_ble_uuid) { -// if (nrf_ble_uuid->type == BLE_UUID_TYPE_UNKNOWN) { -// mp_raise_bleio_BluetoothError(translate("Unexpected nrfx uuid type")); -// } -// self->nrf_ble_uuid.uuid = nrf_ble_uuid->uuid; -// self->nrf_ble_uuid.type = nrf_ble_uuid->type; -// } - -// // Fill in a ble_uuid_t from my values. -// void bleio_uuid_convert_to_nrf_ble_uuid(bleio_uuid_obj_t *self, ble_uuid_t *nrf_ble_uuid) { -// nrf_ble_uuid->uuid = self->nrf_ble_uuid.uuid; -// nrf_ble_uuid->type = self->nrf_ble_uuid.type; -// } diff --git a/devices/ble_hci/common-hal/_bleio/UUID.h b/devices/ble_hci/common-hal/_bleio/UUID.h index 4a72d38ac..deaf76d5c 100644 --- a/devices/ble_hci/common-hal/_bleio/UUID.h +++ b/devices/ble_hci/common-hal/_bleio/UUID.h @@ -33,15 +33,9 @@ typedef struct { mp_obj_base_t base; - //FIX Use the native way of storing UUID's: - // - ble_uuid_t.uuid is a 16-bit uuid. - // - ble_uuid_t.type is BLE_UUID_TYPE_BLE if it's a 16-bit Bluetooth SIG UUID. - // or is BLE_UUID_TYPE_VENDOR_BEGIN and higher, which indexes into a table of registered - // 128-bit UUIDs. - // ble_uuid_t nrf_ble_uuid; + uint8_t size; + uint16_t uuid16; + uint8_t uuid128[16]; } bleio_uuid_obj_t; -// void bleio_uuid_construct_from_nrf_ble_uuid(bleio_uuid_obj_t *self, ble_uuid_t *nrf_uuid); -// void bleio_uuid_convert_to_nrf_ble_uuid(bleio_uuid_obj_t *self, ble_uuid_t *nrf_uuid); - #endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_UUID_H diff --git a/devices/ble_hci/common-hal/_bleio/hci_api.c b/devices/ble_hci/common-hal/_bleio/hci_api.c index ece06f169..8155bca56 100644 --- a/devices/ble_hci/common-hal/_bleio/hci_api.c +++ b/devices/ble_hci/common-hal/_bleio/hci_api.c @@ -25,6 +25,7 @@ #include "supervisor/shared/tick.h" #include "shared-bindings/_bleio/__init__.h" #include "common-hal/_bleio/Adapter.h" +#include "shared-bindings/microcontroller/__init__.h" // HCI H4 protocol packet types: first byte in the packet. #define H4_CMD 0x01 @@ -61,44 +62,61 @@ STATIC uint8_t* cmd_response_data; //FIX STATIC uint8_t acl_pkt_buffer[ACL_PKT_BUFFER_SIZE]; +STATIC volatile bool hci_poll_in_progress = false; + STATIC bool debug = true; // 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; -} h4_hci_cmd_hdr_t; + uint8_t pkt_type; + uint16_t opcode; + uint8_t param_len; + uint8_t params[]; +} h4_hci_cmd_pkt_t; + +#define ACLDATA_PB_FIRST_NON_FLUSH 0 +#define ACLDATA_HCI_PB_MIDDLE 1 +#define ACLDATA_PB_FIRST_FLUSH 2 +#define ACLDATA_PB_FULL 3 typedef struct __attribute__ ((packed)) { uint8_t pkt_type; - uint16_t handle; - uint16_t total_data_len; - uint16_t acl_data_len; - uint16_t cid; -} h4_hci_acl_hdr_t; + uint16_t handle : 12; + uint8_t pb: 2; // Packet boundary flag: ACLDATA_PB values. + uint8_t bc: 2; // Broadcast flag: always 0b00 for BLE. + uint16_t data_len; // Total data length, including acl_data header. + uint8_t data[]; // Data following the header +} h4_hci_acl_pkt_t; + +// L2CAP data, which is in h4_hci_acl_pkt_t.data +typedef struct __attribute__ ((packed)) { + uint16_t l2cap_data_len; // Length of acl_data. Does not include this header. + uint16_t cid; // Channel ID. + uint8_t l2cap_data[]; +} l2cap_data_t; + typedef struct __attribute__ ((packed)) { uint8_t pkt_type; uint8_t evt; uint8_t param_len; -} h4_hci_evt_hdr_t; + uint8_t params[]; +} h4_hci_evt_pkt_t; STATIC void dump_cmd_pkt(bool tx, uint8_t pkt_len, uint8_t pkt_data[]) { if (debug) { - h4_hci_cmd_hdr_t *pkt = (h4_hci_cmd_hdr_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) opcode: %04x, len: %d, data: ", tx ? "TX->" : "RX<-", pkt->pkt_type, pkt->opcode, pkt->param_len); - uint8_t i; - for (i = sizeof(h4_hci_cmd_hdr_t); i < pkt_len; i++) { - mp_printf(&mp_plat_print, "%02x ", pkt_data[i]); + for (size_t i = 0; i < pkt->param_len; i++) { + mp_printf(&mp_plat_print, "%02x ", pkt->params[i]); } - if (i != pkt->param_len + sizeof(h4_hci_cmd_hdr_t)) { + if (pkt_len != sizeof(h4_hci_cmd_pkt_t) + pkt->param_len) { mp_printf(&mp_plat_print, " LENGTH MISMATCH"); } mp_printf(&mp_plat_print, "\n"); @@ -107,16 +125,16 @@ STATIC void dump_cmd_pkt(bool tx, uint8_t pkt_len, uint8_t pkt_data[]) { STATIC void dump_acl_pkt(bool tx, uint8_t pkt_len, uint8_t pkt_data[]) { if (debug) { - h4_hci_acl_hdr_t *pkt = (h4_hci_acl_hdr_t *) pkt_data; + h4_hci_acl_pkt_t *pkt = (h4_hci_acl_pkt_t *) pkt_data; + l2cap_data_t *l2cap = (l2cap_data_t *) pkt->data; mp_printf(&mp_plat_print, - "%s HCI ACLDATA (%x) handle: %04x, total_data_len: %d, acl_data_len: %d, cid: %04x, data: ", + "%s HCI ACLDATA (%x) handle: %04x, pb: %d, bc: %d, data_len: %d, l2cap_data_len: %d, cid: %04x, l2cap_data: ", tx ? "TX->" : "RX<-", - pkt->pkt_type, pkt->handle, pkt->total_data_len, pkt->acl_data_len, pkt->cid); - uint8_t i; - for (i = sizeof(h4_hci_acl_hdr_t); i < pkt_len; i++) { - mp_printf(&mp_plat_print, "%02x ", pkt_data[i]); + pkt->pkt_type, pkt->handle, pkt->data_len, l2cap->l2cap_data_len, l2cap->cid); + for (size_t i = 0; i < l2cap->l2cap_data_len; i++) { + mp_printf(&mp_plat_print, "%02x ", l2cap->l2cap_data[i]); } - if (i != pkt->acl_data_len + sizeof(h4_hci_acl_hdr_t)) { + if (pkt_len != sizeof(h4_hci_acl_pkt_t) + pkt->data_len) { mp_printf(&mp_plat_print, " LENGTH MISMATCH"); } mp_printf(&mp_plat_print, "\n"); @@ -125,16 +143,15 @@ STATIC void dump_acl_pkt(bool tx, uint8_t pkt_len, uint8_t pkt_data[]) { STATIC void dump_evt_pkt(bool tx, uint8_t pkt_len, uint8_t pkt_data[]) { if (debug) { - h4_hci_evt_hdr_t *pkt = (h4_hci_evt_hdr_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: %02x, param_len: %d, data: ", tx ? "TX->" : "RX<-", pkt->pkt_type, pkt->evt, pkt->param_len); - uint8_t i; - for (i = sizeof(h4_hci_evt_hdr_t); i < pkt_len; i++) { - mp_printf(&mp_plat_print, "%02x ", pkt_data[i]); + for (size_t i = 0; i < pkt->param_len; i++) { + mp_printf(&mp_plat_print, "%02x ", pkt->params[i]); } - if (i != pkt->param_len + sizeof(h4_hci_evt_hdr_t)) { + if (pkt_len != sizeof(h4_hci_evt_pkt_t) + pkt->param_len) { mp_printf(&mp_plat_print, " LENGTH MISMATCH"); } mp_printf(&mp_plat_print, "\n"); @@ -143,7 +160,7 @@ STATIC void dump_evt_pkt(bool tx, uint8_t pkt_len, uint8_t pkt_data[]) { STATIC void process_acl_data_pkt(uint8_t pkt_len, uint8_t pkt_data[]) { //FIX pkt_len is +1 than before, because it includes the pkt_type. - // h4_hci_acl_hdr_t *aclHdr = (h4_hci_acl_hdr_t*)pkt_data; + // h4_hci_acl_pkt_t *aclHdr = (h4_hci_acl_pkt_t*)pkt_data; // uint16_t aclFlags = (aclHdr->handle & 0xf000) >> 12; @@ -202,15 +219,14 @@ STATIC void process_num_comp_pkts(uint16_t handle, uint16_t num_pkts) { } } -STATIC void process_evt_pkt(size_t pkt_len, uint8_t pkt[]) +STATIC void process_evt_pkt(size_t pkt_len, uint8_t pkt_data[]) { - h4_hci_evt_hdr_t *evt_hdr = (h4_hci_evt_hdr_t*) pkt; - // The data itself, after the header. - uint8_t *evt_data = pkt + sizeof(h4_hci_evt_hdr_t); + h4_hci_evt_pkt_t *pkt = (h4_hci_evt_pkt_t*) pkt_data; - switch (evt_hdr->evt) { + switch (pkt->evt) { case BT_HCI_EVT_DISCONN_COMPLETE: { - struct bt_hci_evt_disconn_complete *disconn_complete = (struct bt_hci_evt_disconn_complete*) evt_data; + struct bt_hci_evt_disconn_complete *disconn_complete = + (struct bt_hci_evt_disconn_complete*) pkt->params; (void) disconn_complete; //FIX // ATT.removeConnection(disconn_complete->handle, disconn_complete->reason); @@ -226,7 +242,7 @@ STATIC void process_evt_pkt(size_t pkt_len, uint8_t pkt[]) struct bt_hci_evt_cc_status cc_status; } __packed; - struct cmd_complete_with_status *evt = (struct cmd_complete_with_status *) evt_data; + struct cmd_complete_with_status *evt = (struct cmd_complete_with_status *) pkt->params; num_command_packets_allowed = evt->cmd_complete.ncmd; @@ -235,15 +251,15 @@ STATIC void process_evt_pkt(size_t pkt_len, uint8_t pkt[]) 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 = &evt_data[sizeof_field(struct cmd_complete_with_status, cmd_complete)]; + cmd_response_data = (uint8_t *) &evt->cc_status; // Includes status byte. - cmd_response_len = evt_hdr->param_len - sizeof_field(struct cmd_complete_with_status, cmd_complete); + 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 *) evt_data; + struct bt_hci_evt_cmd_status *evt = (struct bt_hci_evt_cmd_status *) pkt->params; num_command_packets_allowed = evt->ncmd; @@ -257,7 +273,8 @@ STATIC void process_evt_pkt(size_t pkt_len, uint8_t pkt[]) } case BT_HCI_EVT_NUM_COMPLETED_PACKETS: { - struct bt_hci_evt_num_completed_packets *evt = (struct bt_hci_evt_num_completed_packets *) evt_data; + 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]); @@ -269,15 +286,14 @@ STATIC void process_evt_pkt(size_t pkt_len, uint8_t pkt[]) } case BT_HCI_EVT_LE_META_EVENT: { - struct bt_hci_evt_le_meta_event *meta_evt = (struct bt_hci_evt_le_meta_event *) evt_data; - // Start of the encapsulated LE event. - uint8_t *le_evt = evt_data + sizeof (struct 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) { struct bt_hci_evt_le_conn_complete *le_conn_complete = (struct bt_hci_evt_le_conn_complete *) le_evt; - if (le_conn_complete->status == 0x00) { + if (le_conn_complete->status == BT_HCI_ERR_SUCCESS) { // ATT.addConnection(le_conn_complete->handle, // le_conn_complete->role, // le_conn_complete->peer_addr //FIX struct @@ -286,13 +302,6 @@ STATIC void process_evt_pkt(size_t pkt_len, uint8_t pkt[]) // le_conn_complete->supv_timeout // le_conn_complete->clock_accuracy); - // L2CAPSignaling.addConnection(le_conn_complete->handle, - // le_conn_complete->role, - // le_conn_complete->peer_addr, //FIX struct - // 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 = @@ -319,9 +328,19 @@ STATIC void process_evt_pkt(size_t pkt_len, uint8_t pkt[]) void hci_init(void) { rx_idx = 0; pending_pkt = 0; + hci_poll_in_progress = false; } hci_result_t hci_poll_for_incoming_pkt(void) { + if (hci_poll_in_progress) { + return HCI_OK; + } + common_hal_mcu_disable_interrupts(); + if (!hci_poll_in_progress) { + 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(adapter->rts_digitalinout, false); @@ -332,21 +351,22 @@ hci_result_t hci_poll_for_incoming_pkt(void) { while (common_hal_busio_uart_rx_characters_available(adapter->hci_uart)) { common_hal_busio_uart_read(adapter->hci_uart, rx_buffer + rx_idx, 1, &errcode); if (errcode) { + hci_poll_in_progress = false; return HCI_READ_ERROR; } rx_idx++; switch (rx_buffer[0]) { case H4_ACL: - if (rx_idx > sizeof(h4_hci_acl_hdr_t) && - rx_idx >= sizeof(h4_hci_acl_hdr_t) + ((h4_hci_acl_hdr_t *) rx_buffer)->total_data_len) { + if (rx_idx > sizeof(h4_hci_acl_pkt_t) && + rx_idx >= sizeof(h4_hci_acl_pkt_t) + ((h4_hci_acl_pkt_t *) rx_buffer)->data_len) { packet_is_complete = true; } break; case H4_EVT: - if (rx_idx > sizeof(h4_hci_evt_hdr_t) && - rx_idx >= sizeof(h4_hci_evt_hdr_t) + ((h4_hci_evt_hdr_t *) rx_buffer)->param_len) { + if (rx_idx > sizeof(h4_hci_evt_pkt_t) && + rx_idx >= sizeof(h4_hci_evt_pkt_t) + ((h4_hci_evt_pkt_t *) rx_buffer)->param_len) { packet_is_complete = true; } break; @@ -359,6 +379,7 @@ hci_result_t hci_poll_for_incoming_pkt(void) { } if (!packet_is_complete) { + hci_poll_in_progress = false; return HCI_OK; } @@ -391,6 +412,7 @@ hci_result_t hci_poll_for_incoming_pkt(void) { common_hal_digitalio_digitalinout_set_value(adapter->rts_digitalinout, true); + hci_poll_in_progress = false; return HCI_OK; } @@ -416,22 +438,22 @@ STATIC hci_result_t write_pkt(uint8_t *buffer, size_t len) { } STATIC hci_result_t send_command(uint16_t opcode, uint8_t params_len, void* params) { - uint8_t tx_buffer[sizeof(h4_hci_cmd_hdr_t) + params_len]; + 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_hdr_t *cmd_hdr = (h4_hci_cmd_hdr_t *) tx_buffer; - cmd_hdr->pkt_type = H4_CMD; - cmd_hdr->opcode = opcode; - cmd_hdr->param_len = params_len; + 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; - // Copy the params data into the space after the header. - memcpy(&tx_buffer[sizeof(h4_hci_cmd_hdr_t)], params, params_len); + memcpy(cmd_pkt->params, params, params_len); if (debug) { dump_cmd_pkt(true, sizeof(tx_buffer), tx_buffer); } - int result = write_pkt(tx_buffer, sizeof(h4_hci_cmd_hdr_t) + params_len); + int result = write_pkt(tx_buffer, cmd_pkt_len); if (result != HCI_OK) { return result; } @@ -477,19 +499,20 @@ STATIC int __attribute__((unused)) send_acl_pkt(uint16_t handle, uint8_t cid, vo } // data_len does not include cid. - const size_t cid_len = sizeof_field(h4_hci_acl_hdr_t, cid); + const size_t cid_len = sizeof_field(l2cap_data_t, cid); // buf_len is size of entire packet including header. - const size_t buf_len = sizeof(h4_hci_acl_hdr_t) + cid_len + data_len; + const size_t buf_len = sizeof(h4_hci_acl_pkt_t) + cid_len + data_len; uint8_t tx_buffer[buf_len]; - h4_hci_acl_hdr_t *acl_hdr = (h4_hci_acl_hdr_t *) tx_buffer; - acl_hdr->pkt_type = H4_ACL; - acl_hdr->handle = handle; - acl_hdr->total_data_len = (uint8_t)(cid_len + data_len); - acl_hdr->acl_data_len = (uint8_t) data_len; - acl_hdr->cid = cid; + h4_hci_acl_pkt_t *acl_pkt = (h4_hci_acl_pkt_t *) tx_buffer; + l2cap_data_t *l2cap = (l2cap_data_t *) acl_pkt->data; + acl_pkt->pkt_type = H4_ACL; + acl_pkt->handle = handle; + acl_pkt->data_len = (uint8_t)(cid_len + data_len); + l2cap->l2cap_data_len = (uint8_t) data_len; + l2cap->cid = cid; - memcpy(&tx_buffer[sizeof(h4_hci_acl_hdr_t)], data, data_len); + memcpy(&tx_buffer[sizeof(h4_hci_acl_pkt_t)], data, data_len); if (debug) { dump_acl_pkt(true, buf_len, tx_buffer); diff --git a/devices/ble_hci/common-hal/_bleio/hci_api.h b/devices/ble_hci/common-hal/_bleio/hci_api.h index 3e53a3775..f6d96d48f 100644 --- a/devices/ble_hci/common-hal/_bleio/hci_api.h +++ b/devices/ble_hci/common-hal/_bleio/hci_api.h @@ -23,6 +23,7 @@ #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; diff --git a/ports/nrf/common-hal/_bleio/UUID.c b/ports/nrf/common-hal/_bleio/UUID.c index 6a3d64305..f80352ccb 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, uint32_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/shared-bindings/_bleio/UUID.h b/shared-bindings/_bleio/UUID.h index 1490737a7..178b0ca96 100644 --- a/shared-bindings/_bleio/UUID.h +++ b/shared-bindings/_bleio/UUID.h @@ -34,7 +34,7 @@ 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 uint32_t common_hal_bleio_uuid_get_size(bleio_uuid_obj_t *self); -- cgit v1.2.3 From d37326326dba329392964d283eb13507643bfbec Mon Sep 17 00:00:00 2001 From: sabas1080 Date: Tue, 28 Jul 2020 00:56:37 -0500 Subject: init bastwifi --- .../esp32s2/boards/electroniccats_bastwifi/board.c | 47 ++++++++++++++++++++++ .../boards/electroniccats_bastwifi/mpconfigboard.h | 32 +++++++++++++++ .../electroniccats_bastwifi/mpconfigboard.mk | 19 +++++++++ .../esp32s2/boards/electroniccats_bastwifi/pins.c | 46 +++++++++++++++++++++ .../boards/electroniccats_bastwifi/sdkconfig | 0 5 files changed, 144 insertions(+) create mode 100644 ports/esp32s2/boards/electroniccats_bastwifi/board.c create mode 100644 ports/esp32s2/boards/electroniccats_bastwifi/mpconfigboard.h create mode 100644 ports/esp32s2/boards/electroniccats_bastwifi/mpconfigboard.mk create mode 100644 ports/esp32s2/boards/electroniccats_bastwifi/pins.c create mode 100644 ports/esp32s2/boards/electroniccats_bastwifi/sdkconfig (limited to 'ports') diff --git a/ports/esp32s2/boards/electroniccats_bastwifi/board.c b/ports/esp32s2/boards/electroniccats_bastwifi/board.c new file mode 100644 index 000000000..9f708874b --- /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 000000000..ed3f23a3c --- /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 000000000..4a2e8ecd8 --- /dev/null +++ b/ports/esp32s2/boards/electroniccats_bastwifi/mpconfigboard.mk @@ -0,0 +1,19 @@ +USB_VID = 0x239A +USB_PID = 0x80A6 +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 000000000..1d4e2c4eb --- /dev/null +++ b/ports/esp32s2/boards/electroniccats_bastwifi/pins.c @@ -0,0 +1,46 @@ +#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_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 000000000..e69de29bb -- cgit v1.2.3 From fea1cad02cba369f3b9c0da8da5829a5066fc318 Mon Sep 17 00:00:00 2001 From: sabas1080 Date: Sat, 1 Aug 2020 17:51:45 -0500 Subject: add support for Bast Wifi Electronic Cats --- .github/workflows/build.yml | 1 + ports/esp32s2/boards/electroniccats_bastwifi/pins.c | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) (limited to 'ports') diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 406f6c43b..aa743f87b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -384,6 +384,7 @@ jobs: - "espressif_saola_1_wroom" - "espressif_saola_1_wrover" - "unexpectedmaker_feathers2" + - "electroniccats_bastwifi" steps: - name: Set up Python 3.8 diff --git a/ports/esp32s2/boards/electroniccats_bastwifi/pins.c b/ports/esp32s2/boards/electroniccats_bastwifi/pins.c index 1d4e2c4eb..0b1934645 100644 --- a/ports/esp32s2/boards/electroniccats_bastwifi/pins.c +++ b/ports/esp32s2/boards/electroniccats_bastwifi/pins.c @@ -2,12 +2,19 @@ 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) }, @@ -18,6 +25,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { 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) }, @@ -31,6 +40,14 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { 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) }, @@ -42,5 +59,9 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { 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); -- cgit v1.2.3 From b074f8a1618e765307f01ac99bd7a37f0663cf68 Mon Sep 17 00:00:00 2001 From: sabas1080 Date: Sun, 2 Aug 2020 00:42:36 -0500 Subject: update for build test --- .github/workflows/build.yml | 2 +- ports/esp32s2/boards/electroniccats_bastwifi/pins.c | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'ports') diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index aa743f87b..435dae2bb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -381,10 +381,10 @@ jobs: fail-fast: false matrix: board: + - "electroniccats_bastwifi" - "espressif_saola_1_wroom" - "espressif_saola_1_wrover" - "unexpectedmaker_feathers2" - - "electroniccats_bastwifi" steps: - name: Set up Python 3.8 diff --git a/ports/esp32s2/boards/electroniccats_bastwifi/pins.c b/ports/esp32s2/boards/electroniccats_bastwifi/pins.c index 0b1934645..2f9987b0e 100644 --- a/ports/esp32s2/boards/electroniccats_bastwifi/pins.c +++ b/ports/esp32s2/boards/electroniccats_bastwifi/pins.c @@ -40,14 +40,11 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { 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) }, -- cgit v1.2.3 From 0e30fe1cc56ae48b1e1ea4b4ef07ffdfdf928fc4 Mon Sep 17 00:00:00 2001 From: sabas1080 Date: Sun, 2 Aug 2020 19:54:11 -0500 Subject: Update VID & PID codes --- ports/esp32s2/boards/electroniccats_bastwifi/mpconfigboard.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ports') diff --git a/ports/esp32s2/boards/electroniccats_bastwifi/mpconfigboard.mk b/ports/esp32s2/boards/electroniccats_bastwifi/mpconfigboard.mk index 4a2e8ecd8..6a6ae7937 100644 --- a/ports/esp32s2/boards/electroniccats_bastwifi/mpconfigboard.mk +++ b/ports/esp32s2/boards/electroniccats_bastwifi/mpconfigboard.mk @@ -1,5 +1,5 @@ -USB_VID = 0x239A -USB_PID = 0x80A6 +USB_VID = 0x1209 +USB_PID = 0xBAB0 USB_PRODUCT = "Bast WiFi" USB_MANUFACTURER = "ElectronicCats" -- cgit v1.2.3 From a995a5c58fa4c231fcfb8c5e0eb6a3847faabbcc Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 3 Aug 2020 21:02:57 -0400 Subject: wip: partial discovery responses; compiles; not tested --- devices/ble_hci/common-hal/_bleio/Adapter.c | 60 +++++ devices/ble_hci/common-hal/_bleio/Attribute.c | 2 +- devices/ble_hci/common-hal/_bleio/Attribute.h | 4 +- devices/ble_hci/common-hal/_bleio/att.c | 127 +++++----- devices/ble_hci/common-hal/_bleio/hci.c | 123 +++------- devices/ble_hci/common-hal/_bleio/hci_debug.c | 335 ++++++++++++++++++++++++++ ports/atmel-samd/Makefile | 2 +- 7 files changed, 501 insertions(+), 152 deletions(-) create mode 100644 devices/ble_hci/common-hal/_bleio/hci_debug.c (limited to 'ports') diff --git a/devices/ble_hci/common-hal/_bleio/Adapter.c b/devices/ble_hci/common-hal/_bleio/Adapter.c index 3acae9beb..c8147fbc1 100644 --- a/devices/ble_hci/common-hal/_bleio/Adapter.c +++ b/devices/ble_hci/common-hal/_bleio/Adapter.c @@ -43,6 +43,8 @@ #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" @@ -70,6 +72,12 @@ bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT]; +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; @@ -232,6 +240,14 @@ void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enable 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(); + } + // Stop any current activity; reset to known state. check_hci_error(hci_reset()); self->now_advertising = false; @@ -253,6 +269,8 @@ bool common_hal_bleio_adapter_get_enabled(bleio_adapter_obj_t *self) { } bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_obj_t *self) { + check_enabled(self); + bt_addr_t addr; check_hci_error(hci_read_bd_addr(&addr)); @@ -306,6 +324,8 @@ void common_hal_bleio_adapter_set_name(bleio_adapter_obj_t *self, const char* na // } 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) { + 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.")); @@ -350,6 +370,8 @@ mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t* } void common_hal_bleio_adapter_stop_scan(bleio_adapter_obj_t *self) { + check_enabled(self); + check_hci_error(hci_le_set_scan_enable(BT_HCI_LE_SCAN_DISABLE, BT_HCI_LE_SCAN_FILTER_DUP_DISABLE)); shared_module_bleio_scanresults_set_done(self->scan_results, true); self->scan_results = NULL; @@ -385,6 +407,8 @@ void common_hal_bleio_adapter_stop_scan(bleio_adapter_obj_t *self) { mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout) { + check_enabled(self); + // ble_gap_addr_t addr; // addr.addr_type = address->type; @@ -482,6 +506,8 @@ STATIC void check_data_fit(size_t data_len, bool connectable) { // } 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); @@ -603,6 +629,8 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, } 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); @@ -638,6 +666,8 @@ void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool } 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; @@ -651,10 +681,14 @@ void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self) { } 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) { @@ -665,6 +699,8 @@ bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self) { } mp_obj_t common_hal_bleio_adapter_get_connections(bleio_adapter_obj_t *self) { + check_enabled(self); + if (self->connection_objs != NULL) { return self->connection_objs; } @@ -685,17 +721,31 @@ mp_obj_t common_hal_bleio_adapter_get_connections(bleio_adapter_obj_t *self) { } void common_hal_bleio_adapter_erase_bonding(bleio_adapter_obj_t *self) { + 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; } @@ -703,6 +753,8 @@ mp_obj_t* bleio_adapter_get_attribute(bleio_adapter_obj_t *adapter, uint16_t han } uint16_t bleio_adapter_max_attribute_handle(bleio_adapter_obj_t *adapter) { + check_enabled(adapter); + return adapter->attributes->len - 1; } @@ -713,6 +765,10 @@ void bleio_adapter_gc_collect(bleio_adapter_obj_t* adapter) { } void bleio_adapter_reset(bleio_adapter_obj_t* adapter) { + if (!common_hal_bleio_adapter_get_enabled(adapter)) { + return; + } + common_hal_bleio_adapter_stop_scan(adapter); if (adapter->now_advertising) { common_hal_bleio_adapter_stop_advertising(adapter); @@ -731,6 +787,10 @@ void bleio_adapter_reset(bleio_adapter_obj_t* adapter) { } 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; diff --git a/devices/ble_hci/common-hal/_bleio/Attribute.c b/devices/ble_hci/common-hal/_bleio/Attribute.c index 0c56c08a8..d32ed1167 100644 --- a/devices/ble_hci/common-hal/_bleio/Attribute.c +++ b/devices/ble_hci/common-hal/_bleio/Attribute.c @@ -30,7 +30,7 @@ #include "shared-bindings/_bleio/Service.h" // Return the type of the attribute. -ble_attribute_type bleio_attribute_type_uuid(mp_obj_t *attribute) { +ble_attribute_type_uuid bleio_attribute_type_uuid(mp_obj_t *attribute) { if (MP_OBJ_IS_TYPE(attribute, &bleio_characteristic_type)) { return BLE_TYPE_CHARACTERISTIC; } diff --git a/devices/ble_hci/common-hal/_bleio/Attribute.h b/devices/ble_hci/common-hal/_bleio/Attribute.h index 4301614fc..47327437b 100644 --- a/devices/ble_hci/common-hal/_bleio/Attribute.h +++ b/devices/ble_hci/common-hal/_bleio/Attribute.h @@ -36,7 +36,7 @@ typedef enum { BLE_TYPE_SECONDARY_SERVICE = 0x2801, BLE_TYPE_CHARACTERISTIC = 0x2803, BLE_TYPE_DESCRIPTOR = 0x2900 -} ble_attribute_type; +} ble_attribute_type_uuid; // typedef struct // { @@ -45,6 +45,6 @@ typedef enum { // } ble_gap_conn_sec_mode_t; -// extern void bleio_attribute_gatts_set_security_mode(ble_gap_conn_sec_mode_t *perm, bleio_attribute_security_mode_t security_mode); +ble_attribute_type_uuid bleio_attribute_type_uuid(mp_obj_t *attribute); #endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_ATTRIBUTE_H diff --git a/devices/ble_hci/common-hal/_bleio/att.c b/devices/ble_hci/common-hal/_bleio/att.c index 2982861f7..08324c37e 100644 --- a/devices/ble_hci/common-hal/_bleio/att.c +++ b/devices/ble_hci/common-hal/_bleio/att.c @@ -33,6 +33,7 @@ #include "common-hal/_bleio/Attribute.h" #include "shared-bindings/_bleio/__init__.h" #include "shared-bindings/_bleio/Characteristic.h" +#include "shared-bindings/_bleio/UUID.h" #include "supervisor/shared/tick.h" STATIC uint16_t max_mtu = BT_ATT_DEFAULT_LE_MTU; // 23 @@ -685,6 +686,7 @@ bool att_indicate(uint16_t handle, const uint8_t* value, int length) { 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; @@ -700,7 +702,8 @@ STATIC void process_error(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) { 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(req)) { + + 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; } @@ -720,7 +723,7 @@ STATIC void process_mtu_req(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) struct __packed { struct bt_att_hdr h; - struct bt_att_exchange_mtu_req r; + struct bt_att_exchange_mtu_rsp r; } rsp = { { .code = BT_ATT_OP_MTU_RSP, }, { @@ -732,12 +735,12 @@ STATIC void process_mtu_req(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) } 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; } - struct bt_att_exchange_mtu_rsp *rsp = (struct bt_att_exchange_mtu_rsp *) data; - 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; @@ -879,69 +882,82 @@ STATIC void process_find_by_type_req(uint16_t conn_handle, uint16_t mtu, uint8_t void process_read_by_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 uuid = req->uuid[0] | (req->uuid[1] << 8); + uint16_t type_uuid = req->uuid[0] | (req->uuid[1] << 8); - if (dlen != sizeof(struct bt_att_find_type_req) || - (uuid != BLE_TYPE_PRIMARY_SERVICE && - uuid != BLE_TYPE_SECONDARY_SERVICE)) { + if (dlen != sizeof(struct bt_att_read_group_req) + sizeof(type_uuid) || + (type_uuid != BLE_TYPE_PRIMARY_SERVICE && + type_uuid != BLE_TYPE_SECONDARY_SERVICE)) { send_error(conn_handle, BT_ATT_OP_READ_GROUP_REQ, req->start_handle, BT_ATT_ERR_UNSUPPORTED_GROUP_TYPE); return; } - uint8_t response[mtu]; - uint16_t response_length; - - response[0] = BT_ATT_OP_READ_GROUP_RSP; - response[1] = 0x00; - response_length = 2; - - // FIX - // for (uint16_t i = (readByGroupReq->start_handle - 1); i < GATT.attributeCount() && i <= (readByGroupReq->end_handle - 1); i++) { - //FIX - // BLELocalAttribute* attribute = GATT.attribute(i); - - // if (readByGroupReq->uuid != attribute->type()) { - // // not the type - // continue; - // } - - // int uuidLen = attribute->uuidLength(); - // size_t infoSize = (uuidLen == 2) ? 6 : 20; - - // if (response[1] == 0) { - // response[1] = infoSize; - // } + 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 fo the first one to make sure. + size_t sizeof_first_service_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++) { + no_data = false; + + mp_obj_t *attribute_obj = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, handle); + if (type_uuid != bleio_attribute_type_uuid(attribute_obj)) { + // Not a primary or secondary service. + continue; + } + // Now we know it's a service. + 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 uint8_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; + } else if (sizeof_first_service_uuid != sizeof_service_uuid) { + // Mismatched sizes. Transmit just what we have so far in this batch. + break; + } - // if (response[1] != infoSize) { - // // different size - // break; - // } + // Size of bt_att_group_data chunk with uuid. + const uint16_t data_length = sizeof(struct bt_att_group_data) + sizeof_service_uuid; - // BLELocalService* service = (BLELocalService*)attribute; + if (rsp_length + data_length > mtu) { + // No room for another bt_att_group_data chunk. + break; + } - // // 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); + // Pass the length of ONE bt_att_group_data chunk. There may be multiple ones in this transmission. + rsp->r.len = data_length; - // // 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); + uint8_t group_data_bytes[data_length]; + struct bt_att_group_data *group_data = (struct bt_att_group_data *) group_data_bytes; - // // add the UUID - // memcpy(&response[response_length], service->uuidData(), uuidLen); - // response_length += uuidLen; + 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); - // if ((response_length + infoSize) > mtu) { - // break; - // } - // } + rsp_length += data_length; + } - if (response_length == 2) { + 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, response_length, response); + hci_send_acl_pkt(conn_handle, BT_L2CAP_CID_ATT, rsp_length, rsp_bytes); } } @@ -986,7 +1002,7 @@ STATIC void process_read_or_read_blob_req(uint16_t conn_handle, uint16_t mtu, ui handle = req->handle; response_opcode = BT_ATT_OP_READ_RSP; - } else { + } 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; @@ -996,8 +1012,11 @@ STATIC void process_read_or_read_blob_req(uint16_t conn_handle, uint16_t mtu, ui handle = req->handle; offset = req->offset; response_opcode = BT_ATT_OP_READ_BLOB_RSP; + } else { + return; } + //FIX (void) offset; (void) handle; diff --git a/devices/ble_hci/common-hal/_bleio/hci.c b/devices/ble_hci/common-hal/_bleio/hci.c index 9c8d7f692..7b4adaa79 100644 --- a/devices/ble_hci/common-hal/_bleio/hci.c +++ b/devices/ble_hci/common-hal/_bleio/hci.c @@ -95,7 +95,6 @@ STATIC uint8_t acl_data_buffer[ACL_DATA_BUFFER_SIZE]; STATIC size_t acl_data_len; STATIC size_t num_command_packets_allowed; -STATIC size_t max_pkt; STATIC size_t pending_pkt; // Results from parsing a command response packet. @@ -107,77 +106,13 @@ STATIC uint8_t* cmd_response_data; STATIC volatile bool hci_poll_in_progress = false; -STATIC bool debug = true; +#define DEBUG_HCI 1 ////////////////////////////////////////////////////////////////////// -STATIC void dump_cmd_pkt(bool tx, uint8_t pkt_len, uint8_t pkt_data[]) { - if (debug) { - h4_hci_cmd_pkt_t *pkt = (h4_hci_cmd_pkt_t *) pkt_data; - mp_printf(&mp_plat_print, - "%s HCI COMMAND (%x) opcode: %04x, len: %d, data: ", - tx ? "TX->" : "RX<-", - pkt->pkt_type, 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"); - } - mp_printf(&mp_plat_print, "\n"); - } -} - -STATIC void dump_acl_pkt(bool tx, uint8_t pkt_len, uint8_t pkt_data[]) { - if (debug) { - // mp_printf(&mp_plat_print, "\\ PKT_DATA: "); - // for (size_t i = 0; i < pkt_len; i++) { - // mp_printf(&mp_plat_print, "%02x ", pkt_data[i]); - // } - // mp_printf(&mp_plat_print, "\n"); - h4_hci_acl_pkt_t *pkt = (h4_hci_acl_pkt_t *) pkt_data; - mp_printf(&mp_plat_print, - "%s HCI ACLDATA (%x) handle: %04x, pb: %d, bc: %d, data_len: %d, ", - tx ? "TX->" : "RX<-", pkt->pkt_type, 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. - acl_data_t *acl = (acl_data_t *) pkt->data; - 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"); - } - mp_printf(&mp_plat_print, "\n"); - } -} - -STATIC void dump_evt_pkt(bool tx, uint8_t pkt_len, uint8_t pkt_data[]) { - if (debug) { - h4_hci_evt_pkt_t *pkt = (h4_hci_evt_pkt_t *) pkt_data; - mp_printf(&mp_plat_print, - "%s HCI EVENT (%x) evt: %02x, param_len: %d, data: ", - tx ? "TX->" : "RX<-", - pkt->pkt_type, 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"); - } - mp_printf(&mp_plat_print, "\n"); - } -} +#if DEBUG_HCI +#include "hci_debug.c" +#endif // DEBUG_HCI 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; @@ -194,7 +129,7 @@ STATIC void process_acl_data_pkt(uint8_t pkt_len, uint8_t pkt_data[]) { } acl_data_t *acl = (acl_data_t *) &acl_data_buffer; - if (acl_data_len != acl->acl_data_len) { + if (acl_data_len != sizeof(acl) + acl->acl_data_len) { // We don't have the full packet yet. return; } @@ -330,9 +265,9 @@ STATIC void process_evt_pkt(size_t pkt_len, uint8_t pkt_data[]) } default: - if (debug) { - mp_printf(&mp_plat_print, "process_evt_pkt: Unknown event: %02x\n"); - } +#if DEBUG_HCI + mp_printf(&mp_plat_print, "process_evt_pkt: Unknown event: %02x\n"); +#endif break; } } @@ -374,7 +309,8 @@ hci_result_t hci_poll_for_incoming_pkt(void) { bool packet_is_complete = false; // Read bytes until we run out, or accumulate a complete packet. - while (common_hal_busio_uart_rx_characters_available(common_hal_bleio_adapter_obj.hci_uart)) { + while (!packet_is_complete && + common_hal_busio_uart_rx_characters_available(common_hal_bleio_adapter_obj.hci_uart)) { common_hal_busio_uart_read(common_hal_bleio_adapter_obj.hci_uart, rx_buffer + rx_idx, 1, &errcode); if (errcode) { hci_poll_in_progress = false; @@ -417,25 +353,25 @@ hci_result_t hci_poll_for_incoming_pkt(void) { switch (rx_buffer[0]) { case H4_ACL: - if (debug) { - dump_acl_pkt(false, pkt_len, rx_buffer); - } +#if DEBUG_HCI + dump_acl_pkt(false, pkt_len, rx_buffer); +#endif process_acl_data_pkt(pkt_len, rx_buffer); break; case H4_EVT: - if (debug) { - dump_evt_pkt(false, pkt_len, rx_buffer); - } +#if DEBUG_HCI + dump_evt_pkt(false, pkt_len, rx_buffer); +#endif process_evt_pkt(pkt_len, rx_buffer); break; default: - if (debug) { - mp_printf(&mp_plat_print, "Unknown HCI packet type: %d\n", rx_buffer[0]); - } +#if DEBUG_HCI + mp_printf(&mp_plat_print, "Unknown HCI packet type: %d\n", rx_buffer[0]); +#endif break; } @@ -478,9 +414,9 @@ STATIC hci_result_t send_command(uint16_t opcode, uint8_t params_len, void* para memcpy(cmd_pkt->params, params, params_len); - if (debug) { +#if DEBUG_HCI dump_cmd_pkt(true, sizeof(tx_buffer), tx_buffer); - } +#endif int result = write_pkt(tx_buffer, cmd_pkt_len); if (result != HCI_OK) { @@ -519,32 +455,31 @@ STATIC hci_result_t send_command(uint16_t opcode, uint8_t params_len, void* para hci_result_t hci_send_acl_pkt(uint16_t handle, uint8_t cid, uint8_t data_len, uint8_t *data) { int result; - while (pending_pkt >= max_pkt) { + while (pending_pkt >= common_hal_bleio_adapter_obj.max_acl_num_buffers) { result = hci_poll_for_incoming_pkt(); if (result != HCI_OK) { return result; } } - // data_len does not include cid - const size_t cid_len = sizeof_field(acl_data_t, cid); // buf_len is size of entire packet including header. - const size_t buf_len = sizeof(h4_hci_acl_pkt_t) + cid_len + data_len; + 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->data_len = (uint8_t)(cid_len + data_len); - acl_data->acl_data_len = (uint8_t) data_len; + acl_pkt->pb = ACL_DATA_PB_FIRST_FLUSH; + acl_pkt->data_len = (uint8_t)(sizeof(acl_data_t) + data_len); + acl_data->acl_data_len = data_len; acl_data->cid = cid; - memcpy(&tx_buffer[sizeof(h4_hci_acl_pkt_t)], data, data_len); + memcpy(&acl_data->acl_data, data, data_len); - if (debug) { +#if DEBUG_HCI dump_acl_pkt(true, buf_len, tx_buffer); - } +#endif pending_pkt++; 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 000000000..8231bc5cc --- /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, ", att_opcode_name(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/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index f63698eba..db26df570 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -112,7 +112,7 @@ CFLAGS += $(OPTIMIZATION_FLAGS) -DNDEBUG $(echo PERIPHERALS_CHIP_FAMILY=$(PERIPHERALS_CHIP_FAMILY)) #Debugging/Optimization ifeq ($(DEBUG), 1) - CFLAGS += -ggdb + CFLAGS += -ggdb -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. -- cgit v1.2.3 From ac95106b8867072cb40043a1a4298aa0317f101c Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Tue, 4 Aug 2020 18:24:37 -0400 Subject: service discovery works; need to work on char and descriptor discovery --- devices/ble_hci/common-hal/_bleio/Characteristic.c | 2 ++ devices/ble_hci/common-hal/_bleio/Service.c | 8 ++++- devices/ble_hci/common-hal/_bleio/Service.h | 2 +- devices/ble_hci/common-hal/_bleio/__init__.c | 4 +++ devices/ble_hci/common-hal/_bleio/__init__.h | 2 +- devices/ble_hci/common-hal/_bleio/att.c | 36 +++++++++++++--------- devices/ble_hci/common-hal/_bleio/att.h | 2 ++ devices/ble_hci/common-hal/_bleio/hci.c | 8 +++-- devices/ble_hci/common-hal/_bleio/hci.h | 2 +- main.c | 8 +++++ ports/atmel-samd/Makefile | 2 +- 11 files changed, 53 insertions(+), 23 deletions(-) (limited to 'ports') diff --git a/devices/ble_hci/common-hal/_bleio/Characteristic.c b/devices/ble_hci/common-hal/_bleio/Characteristic.c index e2cdac08c..2f4a81f9a 100644 --- a/devices/ble_hci/common-hal/_bleio/Characteristic.c +++ b/devices/ble_hci/common-hal/_bleio/Characteristic.c @@ -149,6 +149,8 @@ void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t * } descriptor->handle = bleio_adapter_add_attribute(&common_hal_bleio_adapter_obj, MP_OBJ_TO_PTR(descriptor)); + // Include this desriptor in the service handles range. + self->service->end_handle = descriptor->handle; // Link together all the descriptors for this characteristic. descriptor->next = self->descriptor_list; diff --git a/devices/ble_hci/common-hal/_bleio/Service.c b/devices/ble_hci/common-hal/_bleio/Service.c index c68355791..abccfd5c4 100644 --- a/devices/ble_hci/common-hal/_bleio/Service.c +++ b/devices/ble_hci/common-hal/_bleio/Service.c @@ -42,6 +42,8 @@ uint32_t _common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uu 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; } @@ -90,10 +92,12 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, } characteristic->decl_handle = bleio_adapter_add_attribute( &common_hal_bleio_adapter_obj, MP_OBJ_TO_PTR(characteristic)); - // This is the value handle + // 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. bleio_descriptor_obj_t *cccd = m_new_obj(bleio_descriptor_obj_t); @@ -107,6 +111,8 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, cccd->handle = cccd_handle; characteristic->cccd_handle = cccd_handle; common_hal_bleio_characteristic_add_descriptor(characteristic, cccd); + + self->end_handle = cccd_handle; } // #if CIRCUITPY_VERBOSE_BLE diff --git a/devices/ble_hci/common-hal/_bleio/Service.h b/devices/ble_hci/common-hal/_bleio/Service.h index bb8bc61ed..11e7d1c96 100644 --- a/devices/ble_hci/common-hal/_bleio/Service.h +++ b/devices/ble_hci/common-hal/_bleio/Service.h @@ -43,7 +43,7 @@ typedef struct bleio_service_obj { // A local service doesn't know the connection. mp_obj_t connection; mp_obj_list_t *characteristic_list; - // Range of attribute handles of this remote service. + // Range of attribute handles of this service. uint16_t start_handle; uint16_t end_handle; struct bleio_service_obj* next; diff --git a/devices/ble_hci/common-hal/_bleio/__init__.c b/devices/ble_hci/common-hal/_bleio/__init__.c index 7139e6193..ee953cfeb 100644 --- a/devices/ble_hci/common-hal/_bleio/__init__.c +++ b/devices/ble_hci/common-hal/_bleio/__init__.c @@ -38,6 +38,8 @@ #include "shared-bindings/_bleio/UUID.h" #include "supervisor/shared/bluetooth.h" +bool vm_used_ble; + void check_hci_error(hci_result_t result) { switch (result) { case HCI_OK: @@ -110,6 +112,8 @@ void check_hci_error(hci_result_t result) { // Turn off BLE on a reset or reload. void bleio_reset() { + bleio_hci_reset(); + if (!common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) { return; } diff --git a/devices/ble_hci/common-hal/_bleio/__init__.h b/devices/ble_hci/common-hal/_bleio/__init__.h index 18b4289e9..5873675af 100644 --- a/devices/ble_hci/common-hal/_bleio/__init__.h +++ b/devices/ble_hci/common-hal/_bleio/__init__.h @@ -57,6 +57,6 @@ void check_gatt_status(uint16_t gatt_status); void check_sec_status(uint8_t sec_status); // Track if the user code modified the BLE state to know if we need to undo it on reload. -bool vm_used_ble; +extern bool vm_used_ble; #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 index 08324c37e..ba6c7c3d0 100644 --- a/devices/ble_hci/common-hal/_bleio/att.c +++ b/devices/ble_hci/common-hal/_bleio/att.c @@ -116,7 +116,7 @@ STATIC void check_and_save_expected_rsp(uint16_t conn_handle, uint8_t opcode, ui } } -void att_init(void) { +void bleio_att_reset(void) { max_mtu = BT_ATT_DEFAULT_LE_MTU; timeout = 5000; long_write_handle = BLE_GATT_HANDLE_INVALID; @@ -884,6 +884,8 @@ void process_read_by_group_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen, 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_TYPE_PRIMARY_SERVICE && type_uuid != BLE_TYPE_SECONDARY_SERVICE)) { @@ -897,7 +899,7 @@ void process_read_by_group_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen, } rsp_t; uint8_t rsp_bytes[mtu]; - rsp_t *rsp = (rsp_t *) &rsp_bytes; + rsp_t *rsp = (rsp_t *) rsp_bytes; rsp->h.code = BT_ATT_OP_READ_GROUP_RSP; rsp->r.len = 0; @@ -907,13 +909,22 @@ void process_read_by_group_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen, bool no_data = true; // All the data chunks must have uuid's that are the same size. - // Keep track fo the first one to make sure. + // 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++) { - no_data = false; + + 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 (type_uuid != bleio_attribute_type_uuid(attribute_obj)) { @@ -925,33 +936,28 @@ void process_read_by_group_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen, // Is this a 16-bit or a 128-bit uuid? It must match in size with any previous attribute // in this transmission. - const uint8_t sizeof_service_uuid = common_hal_bleio_uuid_get_size(service->uuid) / 8; + 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. Transmit just what we have so far in this batch. + // Mismatched sizes, which can't be in the same batch. + // Transmit just what we have so far in this batch. break; } - // Size of bt_att_group_data chunk with uuid. - const uint16_t data_length = sizeof(struct bt_att_group_data) + sizeof_service_uuid; - - if (rsp_length + data_length > mtu) { - // No room for another bt_att_group_data chunk. - break; - } // Pass the length of ONE bt_att_group_data chunk. There may be multiple ones in this transmission. rsp->r.len = data_length; - uint8_t group_data_bytes[data_length]; - struct bt_att_group_data *group_data = (struct bt_att_group_data *) group_data_bytes; + 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) { diff --git a/devices/ble_hci/common-hal/_bleio/att.h b/devices/ble_hci/common-hal/_bleio/att.h index 6cf9b305b..48f7836e0 100644 --- a/devices/ble_hci/common-hal/_bleio/att.h +++ b/devices/ble_hci/common-hal/_bleio/att.h @@ -30,6 +30,8 @@ #include "hci_include/att.h" #include "hci_include/att_internal.h" +void bleio_att_reset(void); + //FIX BLEDevice att_central(void); //FIX BLERemoteDevice* att_device(uint8_t address_type, const uint8_t address[6]); //FIX void att_set_event_handler(BLEDeviceEvent event, BLEDeviceEventHandler eventHandler); diff --git a/devices/ble_hci/common-hal/_bleio/hci.c b/devices/ble_hci/common-hal/_bleio/hci.c index 7b4adaa79..52452a26d 100644 --- a/devices/ble_hci/common-hal/_bleio/hci.c +++ b/devices/ble_hci/common-hal/_bleio/hci.c @@ -272,18 +272,20 @@ STATIC void process_evt_pkt(size_t pkt_len, uint8_t pkt_data[]) } } -void hci_init(void) { +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_timeout(uint32_t timeout_msecs) { uint64_t start = supervisor_ticks_ms64(); - hci_result_t result; + hci_result_t result = HCI_OK; - while (supervisor_ticks_ms64() -start < timeout_msecs) { + while (supervisor_ticks_ms64() - start < timeout_msecs) { result = hci_poll_for_incoming_pkt(); RUN_BACKGROUND_TASKS; } diff --git a/devices/ble_hci/common-hal/_bleio/hci.h b/devices/ble_hci/common-hal/_bleio/hci.h index 89a2b3304..d907a84b7 100644 --- a/devices/ble_hci/common-hal/_bleio/hci.h +++ b/devices/ble_hci/common-hal/_bleio/hci.h @@ -39,7 +39,7 @@ typedef int hci_result_t; #define HCI_WRITE_ERROR (-5) #define HCI_ATT_ERROR (-6) -void hci_init(void); +void bleio_hci_reset(void); hci_result_t hci_disconnect(uint16_t handle); diff --git a/main.c b/main.c index 8c5c9ac37..4dd93374e 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(); @@ -459,6 +465,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 db26df570..038585fc3 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -112,7 +112,7 @@ CFLAGS += $(OPTIMIZATION_FLAGS) -DNDEBUG $(echo PERIPHERALS_CHIP_FAMILY=$(PERIPHERALS_CHIP_FAMILY)) #Debugging/Optimization ifeq ($(DEBUG), 1) - CFLAGS += -ggdb -Og + 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. -- cgit v1.2.3 From 0f4b969d62b5eb933a674a23a338d9d420cf61b4 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sat, 8 Aug 2020 00:29:37 -0400 Subject: discovery of Nordic UART service working --- devices/ble_hci/common-hal/_bleio/Attribute.c | 49 +-- devices/ble_hci/common-hal/_bleio/Attribute.h | 26 +- devices/ble_hci/common-hal/_bleio/Characteristic.c | 2 +- devices/ble_hci/common-hal/_bleio/Service.c | 32 +- devices/ble_hci/common-hal/_bleio/UUID.c | 2 +- devices/ble_hci/common-hal/_bleio/__init__.c | 8 + devices/ble_hci/common-hal/_bleio/__init__.h | 5 + devices/ble_hci/common-hal/_bleio/att.c | 454 +++++++++++++-------- ports/nrf/common-hal/_bleio/UUID.c | 2 +- shared-bindings/_bleio/UUID.c | 2 +- shared-bindings/_bleio/UUID.h | 2 +- shared-module/_bleio/Characteristic.h | 13 + 12 files changed, 368 insertions(+), 229 deletions(-) (limited to 'ports') diff --git a/devices/ble_hci/common-hal/_bleio/Attribute.c b/devices/ble_hci/common-hal/_bleio/Attribute.c index d32ed1167..26fabed09 100644 --- a/devices/ble_hci/common-hal/_bleio/Attribute.c +++ b/devices/ble_hci/common-hal/_bleio/Attribute.c @@ -24,55 +24,26 @@ * 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" -// Return the type of the attribute. -ble_attribute_type_uuid bleio_attribute_type_uuid(mp_obj_t *attribute) { + +bleio_uuid_obj_t *bleio_attribute_get_uuid(mp_obj_t *attribute) { if (MP_OBJ_IS_TYPE(attribute, &bleio_characteristic_type)) { - return BLE_TYPE_CHARACTERISTIC; + bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(attribute); + return characteristic->uuid; } if (MP_OBJ_IS_TYPE(attribute, &bleio_descriptor_type)) { - return BLE_TYPE_DESCRIPTOR; + 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->is_secondary ? BLE_TYPE_SECONDARY_SERVICE : BLE_TYPE_PRIMARY_SERVICE; + return service->uuid; } - return BLE_TYPE_UNKNOWN; + mp_raise_RuntimeError(translate("Invalid BLE attribute")); } - -// Convert a _bleio security mode to a ble_gap_conn_sec_mode_t setting. -// void bleio_attribute_gatts_set_security_mode(ble_gap_conn_sec_mode_t *perm, bleio_attribute_security_mode_t security_mode) { -// switch (security_mode) { -// case SECURITY_MODE_NO_ACCESS: -// BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(perm); -// break; - -// case SECURITY_MODE_OPEN: -// BLE_GAP_CONN_SEC_MODE_SET_OPEN(perm); -// break; - -// case SECURITY_MODE_ENC_NO_MITM: -// BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(perm); -// break; - -// case SECURITY_MODE_ENC_WITH_MITM: -// BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(perm); -// break; - -// case SECURITY_MODE_LESC_ENC_WITH_MITM: -// BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM(perm); -// break; - -// case SECURITY_MODE_SIGNED_NO_MITM: -// BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(perm); -// break; - -// case SECURITY_MODE_SIGNED_WITH_MITM: -// BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(perm); -// break; -// } -// } diff --git a/devices/ble_hci/common-hal/_bleio/Attribute.h b/devices/ble_hci/common-hal/_bleio/Attribute.h index 47327437b..f4b0b7dbb 100644 --- a/devices/ble_hci/common-hal/_bleio/Attribute.h +++ b/devices/ble_hci/common-hal/_bleio/Attribute.h @@ -28,23 +28,23 @@ #define MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_ATTRIBUTE_H #include "shared-module/_bleio/Attribute.h" +#include "shared-bindings/_bleio/UUID.h" // Types returned by attribute table lookups. These are UUIDs. typedef enum { - BLE_TYPE_UNKNOWN = 0x0000, - BLE_TYPE_PRIMARY_SERVICE = 0x2800, - BLE_TYPE_SECONDARY_SERVICE = 0x2801, - BLE_TYPE_CHARACTERISTIC = 0x2803, - BLE_TYPE_DESCRIPTOR = 0x2900 + BLE_TYPE_UNKNOWN = 0x0000, + BLE_TYPE_SERVICE_PRIMARY = 0x2800, + BLE_TYPE_SERVICE_SECONDARY = 0x2801, + BLE_TYPE_SERVICE_INCLUDE = 0x2802, // not yet implemented by us + BLE_TYPE_CHARACTERISTIC = 0x2803, + BLE_TYPE_CHAR_EXTENDED_PROPS = 0x2900, // not yet implemented by us + BLE_TYPE_CHAR_USER_DESC = 0x2901, // not yet implemented by us + BLE_TYPE_CCCD = 0x2902, + BLE_TYPE_SCCD = 0x2903, // not yet implemented by us + BLE_TYPE_CHAR_PRESENTATION_FMT = 0x2904, // not yet implemented by us + BLE_TYPE_CHAR_AGGREGATE_FMT = 0x2905, // not yet implemented by us } ble_attribute_type_uuid; -// typedef struct -// { -// uint8_t sm : 4; /**< Security Mode (1 or 2), 0 for no permissions at all. */ -// uint8_t lv : 4; /**< Level (1, 2, 3 or 4), 0 for no permissions at all. */ - -// } ble_gap_conn_sec_mode_t; - -ble_attribute_type_uuid bleio_attribute_type_uuid(mp_obj_t *attribute); +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 index 2f4a81f9a..b62957ea6 100644 --- a/devices/ble_hci/common-hal/_bleio/Characteristic.c +++ b/devices/ble_hci/common-hal/_bleio/Characteristic.c @@ -149,7 +149,7 @@ void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t * } descriptor->handle = bleio_adapter_add_attribute(&common_hal_bleio_adapter_obj, MP_OBJ_TO_PTR(descriptor)); - // Include this desriptor in the service handles range. + // Include this descriptor in the service handle's range. self->service->end_handle = descriptor->handle; // Link together all the descriptors for this characteristic. diff --git a/devices/ble_hci/common-hal/_bleio/Service.c b/devices/ble_hci/common-hal/_bleio/Service.c index abccfd5c4..b6963b7a4 100644 --- a/devices/ble_hci/common-hal/_bleio/Service.c +++ b/devices/ble_hci/common-hal/_bleio/Service.c @@ -99,20 +99,30 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, self->end_handle = characteristic->handle; if (characteristic->props & (CHAR_PROP_NOTIFY | CHAR_PROP_INDICATE)) { - // We need a CCCD. + // 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; - cccd->read_perm = SECURITY_MODE_OPEN; - // Make CCCD write permission match characteristic read permission. - cccd->write_perm = characteristic->read_perm; - - const uint16_t cccd_handle = bleio_adapter_add_attribute( - &common_hal_bleio_adapter_obj, MP_OBJ_TO_PTR(cccd)); - cccd->handle = cccd_handle; - characteristic->cccd_handle = cccd_handle; - common_hal_bleio_characteristic_add_descriptor(characteristic, cccd); - self->end_handle = cccd_handle; + uint16_t zero = 0; + mp_buffer_info_t zero_cccd = { + .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 // 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_handle = cccd->handle; } // #if CIRCUITPY_VERBOSE_BLE diff --git a/devices/ble_hci/common-hal/_bleio/UUID.c b/devices/ble_hci/common-hal/_bleio/UUID.c index d86878e47..fd8d8bfe9 100644 --- a/devices/ble_hci/common-hal/_bleio/UUID.c +++ b/devices/ble_hci/common-hal/_bleio/UUID.c @@ -36,7 +36,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[16]) { +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) { diff --git a/devices/ble_hci/common-hal/_bleio/__init__.c b/devices/ble_hci/common-hal/_bleio/__init__.c index ee953cfeb..16b4a26e2 100644 --- a/devices/ble_hci/common-hal/_bleio/__init__.c +++ b/devices/ble_hci/common-hal/_bleio/__init__.c @@ -38,6 +38,9 @@ #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_hci_error(hci_result_t result) { @@ -112,6 +115,10 @@ void check_hci_error(hci_result_t result) { // 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_TYPE_CCCD, NULL); + bleio_hci_reset(); if (!common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) { @@ -123,6 +130,7 @@ void bleio_reset() { return; } common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, false); + //FIX bonding_reset(); supervisor_start_bluetooth(); } diff --git a/devices/ble_hci/common-hal/_bleio/__init__.h b/devices/ble_hci/common-hal/_bleio/__init__.h index 5873675af..e84320e30 100644 --- a/devices/ble_hci/common-hal/_bleio/__init__.h +++ b/devices/ble_hci/common-hal/_bleio/__init__.h @@ -29,6 +29,8 @@ #include +#include "shared-bindings/_bleio/UUID.h" + #include "hci.h" void bleio_background(void); @@ -59,4 +61,7 @@ void check_sec_status(uint8_t sec_status); // 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 index ba6c7c3d0..8daddd3a9 100644 --- a/devices/ble_hci/common-hal/_bleio/att.c +++ b/devices/ble_hci/common-hal/_bleio/att.c @@ -33,6 +33,8 @@ #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" @@ -54,8 +56,63 @@ STATIC struct { 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; + //FIX BLEDeviceEventHandler event_handlers[2]; +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; +} + +// 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; +// } STATIC void send_error(uint16_t conn_handle, uint8_t opcode, uint16_t handle, uint8_t code) { struct __packed { @@ -187,13 +244,13 @@ bool att_disconnect_from_address(bt_addr_le_t *addr) { // BLEUuid serviceUuid(serviceUuidFilter); // while (reqEnd_handle == 0xffff) { -// int respLength = readByGroupReq(conn_handle, reqStart_handle, reqEnd_handle, BLE_TYPE_PRIMARY_SERVICE, response_buffer); +// int respLength = readByGroupReq(conn_handle, reqStart_handle, reqEnd_handle, BLE_TYPE_SERVICE_PRIMARY, response_buffer); // if (respLength == 0) { // return false; // } -// if (response_buffer[0] == BT_ATT_OP_READ_BY_GROUP_RSP) { +// if (response_buffer[0] == BT_ATT_OP_READ_GROUP_RSP) { // uint16_t lengthPerService = response_buffer[1]; // uint8_t uuidLen = lengthPerService - 4; @@ -254,7 +311,7 @@ bool att_disconnect_from_address(bt_addr_le_t *addr) { // return false; // } -// if (response_buffer[0] == BT_ATT_OP_READ_BY_TYPE_RSP) { +// if (response_buffer[0] == BT_ATT_OP_READ_TYPE_RSP) { // uint16_t lengthPerCharacteristic = response_buffer[1]; // uint8_t uuidLen = lengthPerCharacteristic - 5; @@ -759,56 +816,88 @@ STATIC void process_find_info_req(uint16_t conn_handle, uint16_t mtu, uint8_t dl return; } - //FIX - // uint8_t response[mtu]; - // uint16_t response_length; + typedef struct __packed { + struct bt_att_hdr h; + struct bt_att_find_info_rsp r; + } rsp_t; - // response[0] = BT_ATT_OP_FIND_INFO_RSP; - // response[1] = 0x00; - // response_length = 2; + uint8_t rsp_bytes[mtu]; + rsp_t *rsp = (rsp_t *) rsp_bytes; + rsp->h.code = BT_ATT_OP_FIND_INFO_RSP; - // for (uint16_t i = (req->start_handle - 1); i < GATT.attributeCount() && i <= (req->end_handle - 1); i++) { - // BLELocalAttribute* attribute = GATT.attribute(i); - // uint16_t handle = (i + 1); - // bool is_value_handle = (attribute->type() == BLE_TYPE_CHARACTERISTIC) && (((BLELocalCharacteristic*)attribute)->valueHandle() == handle); - // int uuid_len = is_value_handle ? 2 : attribute->uuid_length(); - // size_t info_type = (uuidLen == 2) ? 0x01 : 0x02; + // Keeps track of total length of the response. + size_t rsp_length = sizeof(rsp_t); - // if (response[1] == 0) { - // response[1] = info_type; - // } + bool no_data = true; - // if (response[1] != info_type) { - // // different type - // break; - // } + // 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; - // // add the handle - // memcpy(&response[response_length], &handle, sizeof(handle)); - // response_length += sizeof(handle); + 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 (is_value_handle || attribute->type() == BLE_TYPE_DESCRIPTOR) { - // // add the UUID - // memcpy(&response[response_length], attribute->uuid_data(), uuid_len); - // response_length += uuidLen; - // } else { - // // add the type - // uint16_t type = attribute->type(); + mp_obj_t *attribute_obj = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, handle); - // memcpy(&response[response_length], &type, sizeof(type)); - // response_length += sizeof(type); - // } + // Fetch the uuid for the given attribute, which might be a characteristic or a descriptor. + bleio_uuid_obj_t *uuid; - // if ((response_length + (2 + uuidLen)) > mtu) { - // break; - // } - // } + 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; - // if (response_length == 2) { - // send_error(conn_handle, BT_ATT_OP_FIND_INFO_REQ, findInfoReq->start_handle, BT_ATT_ERR_ATTR_NOT_FOUND); - // } else { - // hci_send_acl_pkt(conn_handle, BT_L2CAP_CID_ATT, response_length, response); - // } + } 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[]) { @@ -834,7 +923,7 @@ STATIC void process_find_info_rsp(uint16_t conn_handle, uint8_t dlen, uint8_t da check_and_save_expected_rsp(conn_handle, BT_ATT_OP_FIND_INFO_RSP, dlen, data); } -STATIC void process_find_by_type_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen, uint8_t 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)) { @@ -849,11 +938,11 @@ STATIC void process_find_by_type_req(uint16_t conn_handle, uint16_t mtu, uint8_t response_length = 1; //FIX - // if (find_by_type_req->type == BLE_TYPE_PRIMARY_SERVICE) { - // for (uint16_t i = (find_by_type_req->start_handle - 1); i < GATT.attributeCount() && i <= (find_by_type_req->end_handle - 1); i++) { + // if (find_type_req->type == BLE_TYPE_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_by_type_req->type) && (attribute->uuidLength() == value_length) && memcmp(attribute->uuidData(), value, value_length) == 0) { + // 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 @@ -880,15 +969,15 @@ STATIC void process_find_by_type_req(uint16_t conn_handle, uint16_t mtu, uint8_t } } -void process_read_by_group_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen, uint8_t data[]) { +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_TYPE_PRIMARY_SERVICE && - type_uuid != BLE_TYPE_SECONDARY_SERVICE)) { + (type_uuid != BLE_TYPE_SERVICE_PRIMARY && + type_uuid != BLE_TYPE_SERVICE_SECONDARY)) { send_error(conn_handle, BT_ATT_OP_READ_GROUP_REQ, req->start_handle, BT_ATT_ERR_UNSUPPORTED_GROUP_TYPE); return; } @@ -927,37 +1016,34 @@ void process_read_by_group_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen, } mp_obj_t *attribute_obj = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, handle); - if (type_uuid != bleio_attribute_type_uuid(attribute_obj)) { - // Not a primary or secondary service. - continue; - } - // Now we know it's a service. - 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; - } - + 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 ones in this transmission. - rsp->r.len = data_length; + // 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]; + 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); + 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; + rsp_length += data_length; + no_data = false; + } } if (no_data) { @@ -967,7 +1053,7 @@ void process_read_by_group_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen, } } -int att_read_by_group_req(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, uint16_t uuid, uint8_t response_buffer[]) { +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; @@ -985,7 +1071,7 @@ int att_read_by_group_req(uint16_t conn_handle, uint16_t start_handle, uint16_t return send_req_wait_for_rsp(conn_handle, sizeof(req), (uint8_t *) &req, response_buffer); } -STATIC void process_read_by_group_rsp(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) { +STATIC void process_read_group_rsp(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) { if (dlen < 2) { return; // invalid, drop } @@ -1040,7 +1126,7 @@ STATIC void process_read_or_read_blob_req(uint16_t conn_handle, uint16_t mtu, ui //FIX BLELocalAttribute* attribute = GATT.attribute(handle - 1); // enum BLEAttributeType attributeType = attribute->type(); - // if (attributeType == BLE_TYPE_PRIMARY_SERVICE) { + // if (attributeType == BLE_TYPE_SERVICE_PRIMARY) { // if (offset) { // send_error(conn_handle, BT_ATT_ERR_ATTR_NOT_LONG, handle, BT_ATT_ERR_INVALID_PDU); // return; @@ -1118,110 +1204,156 @@ 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_by_type_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen, uint8_t 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)) { + 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; } - // uint8_t response[mtu]; - // uint16_t response_length; + typedef struct __packed { + struct bt_att_hdr h; + struct bt_att_read_type_rsp r; + } rsp_t; - // response[0] = BT_ATT_OP_READ_TYPE_RSP; - // response[1] = 0x00; - // response_length = 2; + 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; - // for (uint16_t i = (req->start_handle - 1); i < GATT.attributeCount() && i <= (req->end_handle - 1); i++) { - // BLELocalAttribute* attribute = GATT.attribute(i); - // uint16_t handle = (i + 1); + // Keeps track of total length of the response. + size_t rsp_length = sizeof(rsp_t); - // if (attribute->type() == readByTypeReq->uuid) { - // if (attribute->type() == BLE_TYPE_CHARACTERISTIC) { - // BLELocalCharacteristic* characteristic = (BLELocalCharacteristic*)attribute; + bool no_data = true; - // if (characteristic->value_handle() == handle) { - // // value handle, skip - // continue; - // } + // 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; - // int uuidLen = attribute->uuidLength(); - // int typeSize = (uuidLen == 2) ? 7 : 21; + // 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); - // if (response[1] == 0) { - // response[1] = typeSize; - // } + 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 (response[1] != typeSize) { - // // all done, wrong size - // break; - // } + if (rsp_length + data_length > mtu) { + // The next possible bt_att_data chunk won't fit. The response is full. + break; + } - // // add the handle - // memcpy(&response[response_length], &handle, sizeof(handle)); - // response_length += sizeof(handle); + mp_obj_t *attribute_obj = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, handle); - // // add the properties - // response[response_length++] = characteristic->properties(); + if (type_uuid == BLE_TYPE_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; + } - // // add the value handle - // uint16_t value_handle = (handle + 1); - // memcpy(&response[response_length], &value_handle, sizeof(value_handle)); - // response_length += sizeof(value_handle); + // 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; + } - // // add the UUID - // memcpy(&response[response_length], characteristic->uuidData(), uuidLen); - // response_length += uuidLen; + // Pass the length of ONE bt_att_data chunk. + // There may be multiple chunks in this transmission. + rsp->r.len = data_length; - // // skip the next handle, it's a value handle - // i++; + struct bt_att_data *att_data = (struct bt_att_data *) &rsp_bytes[rsp_length]; - // if ((response_length + typeSize) > mtu) { - // break; - // } - // } else if (attribute->type() == 0x2902) { - // BLELocalDescriptor* descriptor = (BLELocalDescriptor*)attribute; + att_data->handle = characteristic->decl_handle; - // // add the handle - // memcpy(&response[response_length], &handle, sizeof(handle)); - // response_length += sizeof(handle); + characteristic_declaration_t *char_decl = (characteristic_declaration_t *) att_data->value; - // // add the value - // int valueSize = min((uint16_t)(mtu - response_length), (uint16_t)descriptor->valueSize()); - // memcpy(&response[response_length], descriptor->value(), valueSize); - // response_length += valueSize; + // 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); - // response[1] = 2 + valueSize; + // We know the next handle will be the characteristic value handle, so skip it. + handle++; - // break; // all done - // } - // } else if (attribute->type() == BLE_TYPE_CHARACTERISTIC && attribute->uuidLength() == 2 && memcmp(&readByTypeReq->uuid, attribute->uuidData(), 2) == 0) { - // BLELocalCharacteristic* characteristic = (BLELocalCharacteristic*)attribute; + rsp_length += data_length; + no_data = false; - // // add the handle - // memcpy(&response[response_length], &handle, sizeof(handle)); - // response_length += sizeof(handle); + } 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 (common_hal_bleio_uuid_get_size(descriptor->uuid) == 16 && + common_hal_bleio_uuid_get_uuid16(descriptor->uuid) == type_uuid) { - // // add the value - // int value_length = min((uint16_t)(mtu - response_length), (uint16_t)characteristic->value_length()); - // memcpy(&response[response_length], characteristic->value(), value_length); - // response_length += value_length; + struct bt_att_data *att_data = (struct bt_att_data *) &rsp_bytes[rsp_length]; - // response[1] = 2 + value_length; + att_data->handle = handle; - // break; // all done - // } - // } + 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; - // if (response_length == 2) { - // send_error(conn_handle, BT_ATT_OP_READ_BY_TYPE_REQ, readByTypeReq->start_handle, BT_ATT_ERR_ATTR_NOT_FOUND); - // } else { - // hci_send_acl_pkt(conn_handle, BT_L2CAP_CID_ATT, response_length, response); - // } + // 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 (common_hal_bleio_uuid_get_size(characteristic->uuid) == 16 && + common_hal_bleio_uuid_get_uuid16(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_by_type_req(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, uint16_t type, uint8_t response_buffer[]) { +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; @@ -1238,7 +1370,7 @@ int att_read_by_type_req(uint16_t conn_handle, uint16_t start_handle, uint16_t e return send_req_wait_for_rsp(conn_handle, sizeof(req), (uint8_t *) &req, response_buffer); } -STATIC void process_read_by_type_rsp(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) { +STATIC void process_read_type_rsp(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) { if (dlen < 1) { return; // invalid, drop } @@ -1597,23 +1729,23 @@ void att_process_data(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) { break; case BT_ATT_OP_FIND_TYPE_REQ: - process_find_by_type_req(conn_handle, mtu, dlen, data); + process_find_type_req(conn_handle, mtu, dlen, data); break; case BT_ATT_OP_READ_TYPE_REQ: - process_read_by_type_req(conn_handle, mtu, dlen, data); + process_read_type_req(conn_handle, mtu, dlen, data); break; case BT_ATT_OP_READ_TYPE_RSP: - process_read_by_type_rsp(conn_handle, dlen, data); + process_read_type_rsp(conn_handle, dlen, data); break; case BT_ATT_OP_READ_GROUP_REQ: - process_read_by_group_req(conn_handle, mtu, dlen, data); + process_read_group_req(conn_handle, mtu, dlen, data); break; case BT_ATT_OP_READ_GROUP_RSP: - process_read_by_group_rsp(conn_handle, dlen, data); + process_read_group_rsp(conn_handle, dlen, data); break; case BT_ATT_OP_READ_REQ: diff --git a/ports/nrf/common-hal/_bleio/UUID.c b/ports/nrf/common-hal/_bleio/UUID.c index f80352ccb..0c79e980e 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[16]) { +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/shared-bindings/_bleio/UUID.c b/shared-bindings/_bleio/UUID.c index 6d92cf793..93f89403b 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 178b0ca96..b10cce67f 100644 --- a/shared-bindings/_bleio/UUID.h +++ b/shared-bindings/_bleio/UUID.h @@ -36,7 +36,7 @@ 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[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-module/_bleio/Characteristic.h b/shared-module/_bleio/Characteristic.h index 409a57c76..7776b1fa5 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 -- cgit v1.2.3 From 06f3b4048a4ec18d9e46444972d12dc677745793 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Tue, 11 Aug 2020 16:21:16 -0400 Subject: fix #3228 for nrf; still needs to be fixed for HCI; tested --- devices/ble_hci/common-hal/_bleio/Characteristic.c | 28 ++++++++++++--- devices/ble_hci/common-hal/_bleio/Characteristic.h | 4 ++- devices/ble_hci/common-hal/_bleio/Connection.c | 22 ++++++------ devices/ble_hci/common-hal/_bleio/Connection.h | 2 +- ports/nrf/common-hal/_bleio/Adapter.c | 3 ++ ports/nrf/common-hal/_bleio/Characteristic.c | 10 +++--- ports/nrf/common-hal/_bleio/Characteristic.h | 2 +- ports/nrf/common-hal/_bleio/Connection.c | 42 +++++++++++----------- ports/nrf/common-hal/_bleio/Connection.h | 5 +-- ports/nrf/common-hal/_bleio/Descriptor.h | 1 - ports/nrf/common-hal/_bleio/Service.c | 4 +-- ports/nrf/common-hal/_bleio/Service.h | 1 - shared-bindings/_bleio/Characteristic.c | 18 ++-------- shared-bindings/_bleio/Characteristic.h | 10 +++--- shared-bindings/_bleio/Service.c | 24 ++----------- shared-bindings/_bleio/Service.h | 4 +-- shared-bindings/_bleio/__init__.h | 1 - 17 files changed, 85 insertions(+), 96 deletions(-) (limited to 'ports') diff --git a/devices/ble_hci/common-hal/_bleio/Characteristic.c b/devices/ble_hci/common-hal/_bleio/Characteristic.c index b62957ea6..4e69c3522 100644 --- a/devices/ble_hci/common-hal/_bleio/Characteristic.c +++ b/devices/ble_hci/common-hal/_bleio/Characteristic.c @@ -47,7 +47,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->descriptor_linked_list = mp_obj_new_list(0, NULL); + self->watchers_list = mp_obj_new_list(0, NULL); const mp_int_t max_length_max = 512; if (max_length < 0 || max_length > max_length_max) { @@ -67,8 +68,8 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, } } -bleio_descriptor_obj_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self) { - return self->descriptor_list; +bleio_descriptor_obj_t *common_hal_bleio_characteristic_get_descriptor_linked_list(bleio_characteristic_obj_t *self) { + return self->descriptor_linked_list; } bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_characteristic_obj_t *self) { @@ -153,8 +154,8 @@ void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t * self->service->end_handle = descriptor->handle; // Link together all the descriptors for this characteristic. - descriptor->next = self->descriptor_list; - self->descriptor_list = descriptor; + descriptor->next = self->descriptor_linked_list; + self->descriptor_linked_list = descriptor; } void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate) { @@ -201,3 +202,20 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, // } } + +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) { + bool + } + + mp_buffer_info_t char_bufinfo; + if (!mp_get_buffer(characteristic->value, &bufinfo, MP_BUFFER_WRITE)) { + return false; + } + memcpy(&char_bufinfo->buf, bufinfo->buf, bufinfo->len); + + for (size_t i; i < characteristic->set_callbacks. +} diff --git a/devices/ble_hci/common-hal/_bleio/Characteristic.h b/devices/ble_hci/common-hal/_bleio/Characteristic.h index ce8302fcf..cc5ba4108 100644 --- a/devices/ble_hci/common-hal/_bleio/Characteristic.h +++ b/devices/ble_hci/common-hal/_bleio/Characteristic.h @@ -40,6 +40,8 @@ typedef struct _bleio_characteristic_obj { bleio_service_obj_t *service; bleio_uuid_obj_t *uuid; mp_obj_t value; + mp_obj_list_t watcher_list; + mp_obj_list_t descriptor_linked_list; uint16_t max_length; bool fixed_length; uint16_t decl_handle; @@ -47,7 +49,7 @@ typedef struct _bleio_characteristic_obj { 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; + bleio_descriptor_obj_t *descriptor_linked_list; uint16_t user_desc_handle; uint16_t cccd_handle; uint16_t sccd_handle; diff --git a/devices/ble_hci/common-hal/_bleio/Connection.c b/devices/ble_hci/common-hal/_bleio/Connection.c index 6b528552a..98fa4d1f7 100644 --- a/devices/ble_hci/common-hal/_bleio/Connection.c +++ b/devices/ble_hci/common-hal/_bleio/Connection.c @@ -319,7 +319,7 @@ static volatile bool m_discovery_successful; // } void bleio_connection_clear(bleio_connection_internal_t *self) { - self->remote_service_list = NULL; + self->remote_service_linked_list = NULL; //FIX self->conn_handle = BLE_CONN_HANDLE_INVALID; self->pair_status = PAIR_NOT_PAIRED; @@ -449,7 +449,7 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern // } // 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; +// bleio_service_obj_t* tail = connection->remote_service_linked_list; // for (size_t i = 0; i < response->count; ++i) { // ble_gattc_service_t *gattc_service = &response->services[i]; @@ -482,7 +482,7 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern // tail = service; // } -// connection->remote_service_list = tail; +// connection->remote_service_linked_list = tail; // if (response->count > 0) { // m_discovery_successful = true; @@ -581,7 +581,7 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern // 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(m_desc_discovery_characteristic->descriptor_linked_list, MP_OBJ_FROM_PTR(descriptor)); // } // if (response->count > 0) { @@ -622,7 +622,7 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern // ble_drv_add_event_handler(discovery_on_ble_evt, self); // // Start over with an empty list. -// self->remote_service_list = NULL; +// self->remote_service_linked_list = NULL; // if (service_uuids_whitelist == mp_const_none) { // // List of service UUID's not given, so discover all available services. @@ -634,7 +634,7 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern // // 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; +// const bleio_service_obj_t *service = self->remote_service_linked_list; // next_service_start_handle = service->end_handle + 1; // } // } else { @@ -658,7 +658,7 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern // } -// bleio_service_obj_t *service = self->remote_service_list; +// bleio_service_obj_t *service = self->remote_service_linked_list; // while (service != NULL) { // // Skip the service if it had an unknown (unregistered) UUID. // if (service->uuid == NULL) { @@ -707,14 +707,14 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern // // 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_list. +// // 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. -// const bleio_descriptor_obj_t *descriptor = characteristic->descriptor_list; +// const bleio_descriptor_obj_t *descriptor = characteristic->descriptor_linked_list; // next_desc_start_handle = descriptor->handle + 1; // } // } @@ -730,8 +730,8 @@ mp_obj_tuple_t *common_hal_bleio_connection_discover_remote_services(bleio_conne //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 = service_linked_list_to_tuple(self->connection->remote_service_list); - self->connection->remote_service_list = NULL; + mp_obj_tuple_t *services_tuple = service_linked_list_to_tuple(self->connection->remote_service_linked_list); + self->connection->remote_service_linked_list = NULL; return services_tuple; } diff --git a/devices/ble_hci/common-hal/_bleio/Connection.h b/devices/ble_hci/common-hal/_bleio/Connection.h index 8b9790d9e..efd496ecc 100644 --- a/devices/ble_hci/common-hal/_bleio/Connection.h +++ b/devices/ble_hci/common-hal/_bleio/Connection.h @@ -50,7 +50,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; + bleio_service_obj_t *remote_service_linked_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). diff --git a/ports/nrf/common-hal/_bleio/Adapter.c b/ports/nrf/common-hal/_bleio/Adapter.c index 0b23bb7bf..dffaaf8b8 100644 --- a/ports/nrf/common-hal/_bleio/Adapter.c +++ b/ports/nrf/common-hal/_bleio/Adapter.c @@ -352,6 +352,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); @@ -576,6 +578,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 d507cecca..cacd53417 100644 --- a/ports/nrf/common-hal/_bleio/Characteristic.c +++ b/ports/nrf/common-hal/_bleio/Characteristic.c @@ -90,7 +90,7 @@ 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->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) { @@ -111,8 +111,8 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, } } -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) { @@ -218,8 +218,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 bb8f28495..19970ef82 100644 --- a/ports/nrf/common-hal/_bleio/Characteristic.h +++ b/ports/nrf/common-hal/_bleio/Characteristic.h @@ -46,7 +46,7 @@ typedef struct _bleio_characteristic_obj { 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 00c1acd4d..fccb5a22a 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; } @@ -528,7 +525,8 @@ STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio GATT_MAX_DATA_LENGTH, false, // max_length, fixed_length: values may not matter for gattc NULL); - 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 b051e5c51..180b2727c 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.h b/ports/nrf/common-hal/_bleio/Descriptor.h index c70547c08..f76510d12 100644 --- a/ports/nrf/common-hal/_bleio/Descriptor.h +++ b/ports/nrf/common-hal/_bleio/Descriptor.h @@ -47,7 +47,6 @@ typedef struct _bleio_descriptor_obj { 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 19288f747..8c57442f2 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) { diff --git a/ports/nrf/common-hal/_bleio/Service.h b/ports/nrf/common-hal/_bleio/Service.h index 6ee9fe63d..00f611dd9 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/shared-bindings/_bleio/Characteristic.c b/shared-bindings/_bleio/Characteristic.c index 557a356b6..24b127e4a 100644 --- a/shared-bindings/_bleio/Characteristic.c +++ b/shared-bindings/_bleio/Characteristic.c @@ -212,26 +212,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 c4356fd4b..e28d61e1f 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/Service.c b/shared-bindings/_bleio/Service.c index f410b1798..2ddf1a712 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 273c6bd98..8b8a6ce77 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/__init__.h b/shared-bindings/_bleio/__init__.h index 5256bdaa0..969d2efb1 100644 --- a/shared-bindings/_bleio/__init__.h +++ b/shared-bindings/_bleio/__init__.h @@ -63,7 +63,6 @@ NORETURN void mp_raise_bleio_SecurityError(const compressed_string_t* msg, ...); void common_hal_bleio_check_connected(uint16_t conn_handle); uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device); -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); -- cgit v1.2.3 From 44c9c43cd15ea7be3192313b1a1bb204743492a1 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Thu, 13 Aug 2020 00:03:39 -0400 Subject: ble_uart_echo_test works --- devices/ble_hci/common-hal/_bleio/Adapter.c | 43 ++-- devices/ble_hci/common-hal/_bleio/Adapter.h | 7 + devices/ble_hci/common-hal/_bleio/Characteristic.c | 125 +++++------ devices/ble_hci/common-hal/_bleio/Characteristic.h | 15 +- .../common-hal/_bleio/CharacteristicBuffer.c | 65 +----- .../common-hal/_bleio/CharacteristicBuffer.h | 2 + devices/ble_hci/common-hal/_bleio/Connection.c | 73 ++++--- devices/ble_hci/common-hal/_bleio/Connection.h | 3 +- devices/ble_hci/common-hal/_bleio/Descriptor.c | 33 ++- devices/ble_hci/common-hal/_bleio/PacketBuffer.c | 238 +++++---------------- devices/ble_hci/common-hal/_bleio/PacketBuffer.h | 2 + devices/ble_hci/common-hal/_bleio/Service.c | 19 +- devices/ble_hci/common-hal/_bleio/__init__.c | 143 ------------- devices/ble_hci/common-hal/_bleio/__init__.h | 3 +- devices/ble_hci/common-hal/_bleio/att.c | 113 +++++++--- devices/ble_hci/common-hal/_bleio/att.h | 2 +- devices/ble_hci/common-hal/_bleio/hci.c | 27 +-- devices/ble_hci/common-hal/_bleio/hci.h | 2 +- ports/nrf/common-hal/_bleio/Characteristic.c | 8 +- ports/nrf/common-hal/_bleio/Characteristic.h | 2 +- ports/nrf/common-hal/_bleio/Connection.c | 2 +- ports/nrf/common-hal/_bleio/Descriptor.c | 5 +- ports/nrf/common-hal/_bleio/Descriptor.h | 2 +- ports/nrf/common-hal/_bleio/Service.c | 7 +- 24 files changed, 352 insertions(+), 589 deletions(-) (limited to 'ports') diff --git a/devices/ble_hci/common-hal/_bleio/Adapter.c b/devices/ble_hci/common-hal/_bleio/Adapter.c index c8147fbc1..4ed85f754 100644 --- a/devices/ble_hci/common-hal/_bleio/Adapter.c +++ b/devices/ble_hci/common-hal/_bleio/Adapter.c @@ -60,6 +60,8 @@ #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) @@ -179,13 +181,31 @@ STATIC void bleio_adapter_reset_name(bleio_adapter_obj_t *self) { } // Get various values and limits set by the adapter. -STATIC void bleio_adapter_get_info(bleio_adapter_obj_t *self) { +// Set event mask. +STATIC void bleio_adapter_setup(bleio_adapter_obj_t *self) { + // 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; @@ -213,7 +233,7 @@ STATIC void bleio_adapter_get_info(bleio_adapter_obj_t *self) { } self->max_adv_data_len = max_adv_data_len; } else { - self->max_adv_data_len = 31; + self->max_adv_data_len = MAX_ADVERTISEMENT_SIZE; } } @@ -226,7 +246,7 @@ void common_hal_bleio_adapter_hci_uart_init(bleio_adapter_obj_t *self, busio_uar self->enabled = false; common_hal_bleio_adapter_set_enabled(self, true); - bleio_adapter_get_info(self); + bleio_adapter_setup(self); bleio_adapter_reset_name(self); } @@ -477,14 +497,10 @@ mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_addre return mp_const_none; } -// The nRF SD 6.1.0 can only do one concurrent advertisement so share the advertising handle. -//FIX uint8_t adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; - STATIC void check_data_fit(size_t data_len, bool connectable) { - //FIX if (data_len > BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_MAX_SUPPORTED || - // (connectable && data_len > BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_CONNECTABLE_MAX_SUPPORTED)) { - // mp_raise_ValueError(translate("Data too large for advertisement packet")); - // } + 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) { @@ -604,8 +620,9 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, 0x00 // filter policy: no filter )); - // The HCI commands expect 31 octets, even though the actual data length may be shorter. - uint8_t full_data[31] = { 0 }; + // 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)); check_hci_error(hci_le_set_advertising_data(advertising_data_len, full_data)); memset(full_data, 0, sizeof(full_data)); @@ -636,7 +653,7 @@ void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool check_data_fit(advertising_data_bufinfo->len, connectable); check_data_fit(scan_response_data_bufinfo->len, connectable); - if (advertising_data_bufinfo->len > 31 && scan_response_data_bufinfo->len > 0) { + 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.")); } diff --git a/devices/ble_hci/common-hal/_bleio/Adapter.h b/devices/ble_hci/common-hal/_bleio/Adapter.h index 1fae5f682..a6a78f67e 100644 --- a/devices/ble_hci/common-hal/_bleio/Adapter.h +++ b/devices/ble_hci/common-hal/_bleio/Adapter.h @@ -56,6 +56,13 @@ typedef struct _bleio_adapter_obj_t { 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. diff --git a/devices/ble_hci/common-hal/_bleio/Characteristic.c b/devices/ble_hci/common-hal/_bleio/Characteristic.c index 4e69c3522..5f9b96b35 100644 --- a/devices/ble_hci/common-hal/_bleio/Characteristic.c +++ b/devices/ble_hci/common-hal/_bleio/Characteristic.c @@ -29,7 +29,9 @@ #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" @@ -47,8 +49,12 @@ 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_linked_list = mp_obj_new_list(0, NULL); - self->watchers_list = mp_obj_new_list(0, NULL); + 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) { @@ -62,14 +68,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_linked_list(bleio_characteristic_obj_t *self) { - return self->descriptor_linked_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) { @@ -79,13 +81,19 @@ bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_character 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) { - uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); + //FIX 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); + //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 { - // conn_handle is ignored for non-system attributes. - return common_hal_bleio_gatts_read(self->handle, conn_handle, buf, len); + mp_buffer_info_t bufinfo; + if (!mp_get_buffer(self->value, &bufinfo, MP_BUFFER_READ)) { + return 0; + } + memcpy(buf, bufinfo.buf, MIN(len, bufinfo.len)); } } @@ -102,32 +110,40 @@ void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, // 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)) { - uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); - // Last argument is true if write-no-reponse desired. - common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo, - (self->props & CHAR_PROP_WRITE_NO_RESPONSE)); + //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. - // conn_handle is ignored for non-system attributes, so we use BLE_CONN_HANDLE_INVALID. - common_hal_bleio_gatts_write(self->handle, BLE_CONN_HANDLE_INVALID, bufinfo); + bleio_characteristic_set_local_value(self, bufinfo); // Notify or indicate all active connections. - uint16_t cccd = 0; + + 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_handle != BLE_GATT_HANDLE_INVALID) { - common_hal_bleio_gatts_read(self->cccd_handle, BLE_CONN_HANDLE_INVALID, - (uint8_t *) &cccd, sizeof(cccd)); + 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 & CCCD_NOTIFY)) { + if (notify && (cccd_value & CCCD_NOTIFY)) { att_notify(self->handle, bufinfo->buf, MIN(bufinfo->len, self->max_length)); } - if (indicate && (cccd & CCCD_INDICATE)) { + if (indicate && (cccd_value & CCCD_INDICATE)) { att_indicate(self->handle, bufinfo->buf, MIN(bufinfo->len, self->max_length)); } @@ -153,13 +169,12 @@ void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t * // Include this descriptor in the service handle's range. self->service->end_handle = descriptor->handle; - // Link together all the descriptors for this characteristic. - descriptor->next = self->descriptor_linked_list; - self->descriptor_linked_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) { - if (self->cccd_handle == BLE_GATT_HANDLE_INVALID) { + if (self->cccd == NULL) { mp_raise_bleio_BluetoothError(translate("No CCCD for this Characteristic")); } @@ -174,33 +189,12 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, (notify ? CCCD_NOTIFY : 0) | (indicate ? CCCD_INDICATE : 0); + //FIX do remote (void) cccd_value; - //FIX call att_something to set remote CCCD - // ble_gattc_write_params_t write_params = { - // .write_op = BLE_GATT_OP_WRITE_REQ, - // .handle = self->cccd_handle, - // .p_value = (uint8_t *) &cccd_value, - // .len = 2, - // }; - - // while (1) { - // uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params); - // if (err_code == NRF_SUCCESS) { - // break; - // } - - // // Write with response will return NRF_ERROR_BUSY if the response has not been received. - // // Write without reponse will return NRF_ERROR_RESOURCES if too many writes are pending. - // if (err_code == NRF_ERROR_BUSY || err_code == NRF_ERROR_RESOURCES) { - // // We could wait for an event indicating the write is complete, but just retrying is easier. - // RUN_BACKGROUND_TASKS; - // continue; - // } - - // // Some real error occurred. - // check_nrf_error(err_code); + // 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) { @@ -208,14 +202,25 @@ bool bleio_characteristic_set_local_value(bleio_characteristic_obj_t *self, mp_b return false; } if (bufinfo->len > self->max_length) { - bool + return false; } - mp_buffer_info_t char_bufinfo; - if (!mp_get_buffer(characteristic->value, &bufinfo, MP_BUFFER_WRITE)) { + 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; } - memcpy(&char_bufinfo->buf, bufinfo->buf, bufinfo->len); + return true; +} + +void bleio_characteristic_set_observer(bleio_characteristic_obj_t *self, mp_obj_t observer) { + self->observer = observer; +} - for (size_t i; i < characteristic->set_callbacks. +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 index cc5ba4108..6d5a12509 100644 --- a/devices/ble_hci/common-hal/_bleio/Characteristic.h +++ b/devices/ble_hci/common-hal/_bleio/Characteristic.h @@ -40,8 +40,8 @@ typedef struct _bleio_characteristic_obj { bleio_service_obj_t *service; bleio_uuid_obj_t *uuid; mp_obj_t value; - mp_obj_list_t watcher_list; - mp_obj_list_t descriptor_linked_list; + mp_obj_t observer; + mp_obj_list_t *descriptor_list; uint16_t max_length; bool fixed_length; uint16_t decl_handle; @@ -50,9 +50,14 @@ typedef struct _bleio_characteristic_obj { bleio_attribute_security_mode_t read_perm; bleio_attribute_security_mode_t write_perm; bleio_descriptor_obj_t *descriptor_linked_list; - uint16_t user_desc_handle; - uint16_t cccd_handle; - uint16_t sccd_handle; + 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 index c4eb6a19f..e8cd51880 100644 --- a/devices/ble_hci/common-hal/_bleio/CharacteristicBuffer.c +++ b/devices/ble_hci/common-hal/_bleio/CharacteristicBuffer.c @@ -37,44 +37,13 @@ #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) { -// uint8_t is_nested_critical_region; -// sd_nvic_critical_region_enter(&is_nested_critical_region); -// ringbuf_put_n(&self->ringbuf, data, len); -// sd_nvic_critical_region_exit(is_nested_critical_region); -// } - -// STATIC bool characteristic_buffer_on_ble_evt(ble_evt_t *ble_evt, void *param) { -// bleio_characteristic_buffer_obj_t *self = (bleio_characteristic_buffer_obj_t *) param; -// switch (ble_evt->header.evt_id) { -// case BLE_GATTS_EVT_WRITE: { -// // A client wrote to this server 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 == self->characteristic->handle) { -// write_to_ringbuf(self, evt_write->data, evt_write->len); -// } -// break; -// } - -// case BLE_GATTC_EVT_HVX: { -// // A remote service wrote to this characteristic. - -// ble_gattc_evt_hvx_t* evt_hvx = &ble_evt->evt.gattc_evt.params.hvx; -// // Must be a notification, and event handle must match the handle for my characteristic. -// if (evt_hvx->type == BLE_GATT_HVX_NOTIFICATION && -// evt_hvx->handle == self->characteristic->handle) { -// write_to_ringbuf(self, evt_hvx->data, evt_hvx->len); -// } -// break; -// } -// default: -// return false; -// break; -// } -// return true; -// } +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, @@ -88,8 +57,7 @@ void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffe // true means long-lived, so it won't be moved. ringbuf_alloc(&self->ringbuf, buffer_size, true); - // FIX ble_drv_add_event_handler(characteristic_buffer_on_ble_evt, self); - + 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) { @@ -104,32 +72,17 @@ uint32_t common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer } } - // Copy received data. Lock out write interrupt handler while copying. - // FIX uint8_t is_nested_critical_region; - // FIX sd_nvic_critical_region_enter(&is_nested_critical_region); - uint32_t num_bytes_read = ringbuf_get_n(&self->ringbuf, data, len); - - // Writes now OK. - // FIX sd_nvic_critical_region_exit(is_nested_critical_region); - return num_bytes_read; } uint32_t common_hal_bleio_characteristic_buffer_rx_characters_available(bleio_characteristic_buffer_obj_t *self) { - //FIX uint8_t is_nested_critical_region; - //FIX sd_nvic_critical_region_enter(&is_nested_critical_region); uint16_t count = ringbuf_num_filled(&self->ringbuf); - //FIX sd_nvic_critical_region_exit(is_nested_critical_region); return count; } void common_hal_bleio_characteristic_buffer_clear_rx_buffer(bleio_characteristic_buffer_obj_t *self) { - // prevent conflict with uart irq - //FIX uint8_t is_nested_critical_region; - //FIX sd_nvic_critical_region_enter(&is_nested_critical_region); ringbuf_clear(&self->ringbuf); - //FIX sd_nvic_critical_region_exit(is_nested_critical_region); } bool common_hal_bleio_characteristic_buffer_deinited(bleio_characteristic_buffer_obj_t *self) { @@ -138,7 +91,7 @@ bool common_hal_bleio_characteristic_buffer_deinited(bleio_characteristic_buffer void common_hal_bleio_characteristic_buffer_deinit(bleio_characteristic_buffer_obj_t *self) { if (!common_hal_bleio_characteristic_buffer_deinited(self)) { - //FIX ble_drv_remove_event_handler(characteristic_buffer_on_ble_evt, self); + bleio_characteristic_clear_observer(self->characteristic); } } diff --git a/devices/ble_hci/common-hal/_bleio/CharacteristicBuffer.h b/devices/ble_hci/common-hal/_bleio/CharacteristicBuffer.h index 8738d2c59..107e5801f 100644 --- a/devices/ble_hci/common-hal/_bleio/CharacteristicBuffer.h +++ b/devices/ble_hci/common-hal/_bleio/CharacteristicBuffer.h @@ -38,4 +38,6 @@ typedef struct { 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 index 98fa4d1f7..ba4eb477d 100644 --- a/devices/ble_hci/common-hal/_bleio/Connection.c +++ b/devices/ble_hci/common-hal/_bleio/Connection.c @@ -27,6 +27,8 @@ #include "shared-bindings/_bleio/Connection.h" +#include "att.h" + #include #include @@ -319,10 +321,11 @@ static volatile bool m_discovery_successful; // } void bleio_connection_clear(bleio_connection_internal_t *self) { - self->remote_service_linked_list = NULL; + mp_obj_list_clear(MP_OBJ_FROM_PTR(self->remote_service_list)); - //FIX self->conn_handle = BLE_CONN_HANDLE_INVALID; + self->conn_handle = BLE_CONN_HANDLE_INVALID; self->pair_status = PAIR_NOT_PAIRED; + self->is_central = false; //FIX bonding_clear_keys(&self->bonding_keys); } @@ -337,12 +340,11 @@ bool common_hal_bleio_connection_get_connected(bleio_connection_obj_t *self) { if (self->connection == NULL) { return false; } - return false; - //FIX return self->connection->conn_handle != BLE_CONN_HANDLE_INVALID; + return self->connection->conn_handle != BLE_CONN_HANDLE_INVALID; } void common_hal_bleio_connection_disconnect(bleio_connection_internal_t *self) { - //FIX sd_ble_gap_disconnect(self->conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + hci_disconnect(self->conn_handle); } void common_hal_bleio_connection_pair(bleio_connection_internal_t *self, bool bond) { @@ -369,8 +371,7 @@ mp_float_t common_hal_bleio_connection_get_connection_interval(bleio_connection_ // Return the current negotiated MTU length, minus overhead. mp_int_t common_hal_bleio_connection_get_max_packet_length(bleio_connection_internal_t *self) { - /// FIX return (self->mtu == 0 ? BLE_GATT_ATT_MTU_DEFAULT : self->mtu) - 3; - return 0; + 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) { @@ -449,8 +450,6 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern // } // 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_linked_list; - // for (size_t i = 0; i < response->count; ++i) { // ble_gattc_service_t *gattc_service = &response->services[i]; @@ -477,13 +476,11 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern // // For now, just set the UUID to NULL. // 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_linked_list = tail; - +// // if (response->count > 0) { // m_discovery_successful = true; // } @@ -525,7 +522,8 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern // GATT_MAX_DATA_LENGTH, false, // max_length, fixed_length: values may not matter for gattc // NULL); -// 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) { @@ -581,7 +579,8 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern // GATT_MAX_DATA_LENGTH, false, mp_const_empty_bytes); // descriptor->handle = gattc_desc->handle; -// mp_obj_list_append(m_desc_discovery_characteristic->descriptor_linked_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) { @@ -622,7 +621,8 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern // ble_drv_add_event_handler(discovery_on_ble_evt, self); // // Start over with an empty list. -// self->remote_service_linked_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. @@ -634,7 +634,9 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern // // 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_linked_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 { @@ -658,11 +660,10 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern // } -// bleio_service_obj_t *service = self->remote_service_linked_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; // } @@ -714,11 +715,12 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern // 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_linked_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. @@ -730,10 +732,11 @@ mp_obj_tuple_t *common_hal_bleio_connection_discover_remote_services(bleio_conne //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 = service_linked_list_to_tuple(self->connection->remote_service_linked_list); - self->connection->remote_service_linked_list = NULL; - - return services_tuple; + 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) { @@ -757,13 +760,13 @@ mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t* interna // 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) { - //FIX 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; - // } - // } + 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 index efd496ecc..0b1f26a21 100644 --- a/devices/ble_hci/common-hal/_bleio/Connection.h +++ b/devices/ble_hci/common-hal/_bleio/Connection.h @@ -50,7 +50,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_linked_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). @@ -60,7 +60,6 @@ typedef struct { volatile pair_status_t pair_status; uint8_t sec_status; // Internal security status. mp_obj_t connection_obj; - //REMOVE ble_drv_evt_handler_entry_t handler_entry; //REMOVE ble_gap_conn_params_t conn_params; volatile bool conn_params_updating; uint16_t mtu; diff --git a/devices/ble_hci/common-hal/_bleio/Descriptor.c b/devices/ble_hci/common-hal/_bleio/Descriptor.c index faf50c658..cc45a8985 100644 --- a/devices/ble_hci/common-hal/_bleio/Descriptor.c +++ b/devices/ble_hci/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->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) { @@ -62,11 +63,20 @@ bleio_characteristic_obj_t *common_hal_bleio_descriptor_get_characteristic(bleio 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) { - uint16_t conn_handle = bleio_connection_get_conn_handle(self->characteristic->service->connection); if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) { - return common_hal_bleio_gattc_read(self->handle, conn_handle, buf, len); + //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 { - return common_hal_bleio_gatts_read(self->handle, conn_handle, buf, len); + mp_buffer_info_t bufinfo; + if (!mp_get_buffer(self->value, &bufinfo, MP_BUFFER_READ)) { + return 0; + } + size_t actual_length = MIN(len, bufinfo.len); + memcpy(buf, bufinfo.buf, actual_length); + return actual_length; } } @@ -85,13 +95,20 @@ void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buff // 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); if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) { - // false means WRITE_REQ, not write-no-response - common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo, false); + //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 { - common_hal_bleio_gatts_write(self->handle, conn_handle, bufinfo); + // 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/PacketBuffer.c b/devices/ble_hci/common-hal/_bleio/PacketBuffer.c index 65d413960..98912ba90 100644 --- a/devices/ble_hci/common-hal/_bleio/PacketBuffer.c +++ b/devices/ble_hci/common-hal/_bleio/PacketBuffer.c @@ -36,152 +36,48 @@ #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. -// //FIX uint8_t is_nested_critical_region; -// //FIX sd_nvic_critical_region_enter(&is_nested_critical_region); -// // 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); -// //FIX sd_nvic_critical_region_exit(is_nested_critical_region); -// } - -//FIX -// 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) { -// uint16_t conn_handle = self->conn_handle; -// uint32_t err_code; -// if (self->client) { -// ble_gattc_write_params_t write_params = { -// .write_op = self->write_type, -// .handle = self->characteristic->handle, -// .p_value = self->outgoing[self->pending_index], -// .len = self->pending_size, -// }; - -// err_code = sd_ble_gattc_write(conn_handle, &write_params); -// } else { -// uint16_t hvx_len = self->pending_size; - -// ble_gatts_hvx_params_t hvx_params = { -// .handle = self->characteristic->handle, -// .type = self->write_type, -// .offset = 0, -// .p_len = &hvx_len, -// .p_data = self->outgoing[self->pending_index], -// }; -// err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params); -// } -// if (err_code != NRF_SUCCESS) { -// // On error, simply skip updating the pending buffers so that the next HVC or WRITE -// // complete event triggers another attempt. -// return err_code; -// } -// self->pending_size = 0; -// self->pending_index = (self->pending_index + 1) % 2; -// self->packet_queued = true; -// } -// return NRF_SUCCESS; -// } - -// STATIC bool packet_buffer_on_ble_client_evt(ble_evt_t *ble_evt, void *param) { -// const uint16_t evt_id = ble_evt->header.evt_id; -// // Check if this is a GATTC event so we can make sure the conn_handle is valid. -// if (evt_id < BLE_GATTC_EVT_BASE || evt_id > BLE_GATTC_EVT_LAST) { -// return false; -// } - -// uint16_t conn_handle = ble_evt->evt.gattc_evt.conn_handle; -// bleio_packet_buffer_obj_t *self = (bleio_packet_buffer_obj_t *) param; -// if (conn_handle != self->conn_handle) { -// return false; -// } -// switch (evt_id) { -// case BLE_GATTC_EVT_HVX: { -// // A remote service wrote to this characteristic. -// ble_gattc_evt_hvx_t* evt_hvx = &ble_evt->evt.gattc_evt.params.hvx; -// // Must be a notification, and event handle must match the handle for my characteristic. -// if (evt_hvx->handle == self->characteristic->handle) { -// write_to_ringbuf(self, evt_hvx->data, evt_hvx->len); -// if (evt_hvx->type == BLE_GATT_HVX_INDICATION) { -// sd_ble_gattc_hv_confirm(conn_handle, evt_hvx->handle); -// } -// } -// break; -// } -// case BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE: { -// queue_next_write(self); -// break; -// } -// case BLE_GATTC_EVT_WRITE_RSP: { -// queue_next_write(self); -// break; -// } -// default: -// return false; -// break; -// } -// return true; -// } - -// STATIC bool packet_buffer_on_ble_server_evt(ble_evt_t *ble_evt, void *param) { -// bleio_packet_buffer_obj_t *self = (bleio_packet_buffer_obj_t *) param; -// switch (ble_evt->header.evt_id) { -// case BLE_GATTS_EVT_WRITE: { -// uint16_t conn_handle = ble_evt->evt.gatts_evt.conn_handle; -// // A client wrote to this server 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 == self->characteristic->handle) { -// if (self->conn_handle == BLE_CONN_HANDLE_INVALID) { -// self->conn_handle = conn_handle; -// } else if (self->conn_handle != conn_handle) { -// return false; -// } -// write_to_ringbuf(self, evt_write->data, evt_write->len); -// } else if (evt_write->handle == self->characteristic->cccd_handle) { -// uint16_t cccd = *((uint16_t*) evt_write->data); -// if (cccd & BLE_GATT_HVX_NOTIFICATION) { -// self->conn_handle = conn_handle; -// } else { -// self->conn_handle = BLE_CONN_HANDLE_INVALID; -// } -// } -// break; -// } -// case BLE_GAP_EVT_DISCONNECTED: { -// if (self->conn_handle == ble_evt->evt.gap_evt.conn_handle) { -// self->conn_handle = BLE_CONN_HANDLE_INVALID; -// } -// } -// case BLE_GATTS_EVT_HVN_TX_COMPLETE: { -// queue_next_write(self); -// } -// default: -// return false; -// break; -// } -// return true; -// } +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, @@ -189,8 +85,10 @@ void common_hal_bleio_packet_buffer_construct( 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); + 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. @@ -219,32 +117,7 @@ void common_hal_bleio_packet_buffer_construct( self->outgoing[1] = NULL; } - //FIX if (self->client) { - // ble_drv_add_event_handler(packet_buffer_on_ble_client_evt, self); - // if (incoming) { - // // Prefer notify if both are available. - // if (incoming & CHAR_PROP_NOTIFY) { - // self->write_type = BLE_GATT_HVX_NOTIFICATION; - // common_hal_bleio_characteristic_set_cccd(self->characteristic, true, false); - // } else { - // common_hal_bleio_characteristic_set_cccd(self->characteristic, false, true); - // } - // } - // if (outgoing) { - // self->write_type = BLE_GATT_OP_WRITE_REQ; - // if (outgoing & CHAR_PROP_WRITE_NO_RESPONSE) { - // self->write_type = BLE_GATT_OP_WRITE_CMD; - // } - // } - // } else { - // ble_drv_add_event_handler(packet_buffer_on_ble_server_evt, self); - // if (outgoing) { - // self->write_type = BLE_GATT_HVX_INDICATION; - // if (outgoing & CHAR_PROP_NOTIFY) { - // self->write_type = BLE_GATT_HVX_NOTIFICATION; - // } - // } - // } + 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) { @@ -252,10 +125,7 @@ mp_int_t common_hal_bleio_packet_buffer_readinto(bleio_packet_buffer_obj_t *self return 0; } - // Copy received data. Lock out write interrupt handler while copying. - //FIX uint8_t is_nested_critical_region; - //FIX sd_nvic_critical_region_enter(&is_nested_critical_region); - + // 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)); @@ -274,9 +144,6 @@ mp_int_t common_hal_bleio_packet_buffer_readinto(bleio_packet_buffer_obj_t *self ret = packet_length; } - // Writes now OK. - //FIX sd_nvic_critical_region_exit(is_nested_critical_region); - return ret; } @@ -307,9 +174,6 @@ mp_int_t common_hal_bleio_packet_buffer_write(bleio_packet_buffer_obj_t *self, u size_t num_bytes_written = 0; - //FIX uint8_t is_nested_critical_region; - //FIX sd_nvic_critical_region_enter(&is_nested_critical_region); - uint8_t* pending = self->outgoing[self->pending_index]; if (self->pending_size == 0) { @@ -321,11 +185,9 @@ mp_int_t common_hal_bleio_packet_buffer_write(bleio_packet_buffer_obj_t *self, u self->pending_size += len; num_bytes_written += len; - //FIX sd_nvic_critical_region_exit(is_nested_critical_region); - // If no writes are queued then sneak in this data. if (!self->packet_queued) { - //FIX queue_next_write(self); + queue_next_write(self); } return num_bytes_written; } @@ -398,6 +260,6 @@ bool common_hal_bleio_packet_buffer_deinited(bleio_packet_buffer_obj_t *self) { void common_hal_bleio_packet_buffer_deinit(bleio_packet_buffer_obj_t *self) { if (!common_hal_bleio_packet_buffer_deinited(self)) { - //FIX ble_drv_remove_event_handler(packet_buffer_on_ble_client_evt, 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 index e1577a995..074c03dc6 100644 --- a/devices/ble_hci/common-hal/_bleio/PacketBuffer.h +++ b/devices/ble_hci/common-hal/_bleio/PacketBuffer.h @@ -48,4 +48,6 @@ typedef struct { 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 index 0b6c83002..5803f5309 100644 --- a/devices/ble_hci/common-hal/_bleio/Service.c +++ b/devices/ble_hci/common-hal/_bleio/Service.c @@ -70,8 +70,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) { @@ -122,21 +122,8 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, // 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_handle = cccd->handle; + characteristic->cccd = cccd; } - // #if CIRCUITPY_VERBOSE_BLE - // // Turn on read authorization so that we receive an event to print on every read. - // char_attr_md.rd_auth = true; - // #endif - - // These are not supplied or available. - characteristic->user_desc_handle = BLE_GATT_HANDLE_INVALID; - characteristic->sccd_handle = BLE_GATT_HANDLE_INVALID; - - // #if CIRCUITPY_VERBOSE_BLE - // mp_printf(&mp_plat_print, "Char handle %x user %x cccd %x sccd %x\n", characteristic->handle, characteristic->user_desc_handle, characteristic->cccd_handle, characteristic->sccd_handle); - // #endif - mp_obj_list_append(self->characteristic_list, MP_OBJ_FROM_PTR(characteristic)); } diff --git a/devices/ble_hci/common-hal/_bleio/__init__.c b/devices/ble_hci/common-hal/_bleio/__init__.c index e2b463af8..3c23c160e 100644 --- a/devices/ble_hci/common-hal/_bleio/__init__.c +++ b/devices/ble_hci/common-hal/_bleio/__init__.c @@ -83,21 +83,6 @@ void check_hci_error(hci_result_t result) { } } -// void check_gatt_status(uint16_t gatt_status) { -// if (gatt_status == BLE_GATT_STATUS_SUCCESS) { -// return; -// } -// switch (gatt_status) { -// case BLE_GATT_STATUS_ATTERR_INSUF_AUTHENTICATION: -// mp_raise_bleio_SecurityError(translate("Insufficient authentication")); -// return; -// case BLE_GATT_STATUS_ATTERR_INSUF_ENCRYPTION: -// mp_raise_bleio_SecurityError(translate("Insufficient encryption")); -// return; -// default: -// mp_raise_bleio_BluetoothError(translate("Unknown gatt error: 0x%04x"), gatt_status); -// } -// } // void check_sec_status(uint8_t sec_status) { // if (sec_status == BLE_GAP_SEC_STATUS_SUCCESS) { @@ -148,134 +133,6 @@ void common_hal_bleio_check_connected(uint16_t conn_handle) { } } -// GATTS read of a Characteristic or Descriptor. -size_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle, uint8_t* buf, size_t len) { - // conn_handle is ignored unless this is a system attribute. - // If we're not connected, that's OK, because we can still read and write the local value. - - //FIX ble_gatts_value_t gatts_value = { - // .p_value = buf, - // .len = len, - // }; - - // check_nrf_error(sd_ble_gatts_value_get(conn_handle, handle, &gatts_value)); - - // return gatts_value.len; - return 0; -} - -void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo) { - // conn_handle is ignored unless this is a system attribute. - // If we're not connected, that's OK, because we can still read and write the local value. - - //FIX ble_gatts_value_t gatts_value = { - // .p_value = bufinfo->buf, - // .len = bufinfo->len, - // }; - - // check_nrf_error(sd_ble_gatts_value_set(conn_handle, handle, &gatts_value)); -} - -//FIX -// typedef struct { -// uint8_t* buf; -// size_t len; -// size_t final_len; -// uint16_t conn_handle; -// volatile uint16_t status; -// volatile bool done; -// } read_info_t; - -// STATIC bool _on_gattc_read_rsp_evt(ble_evt_t *ble_evt, void *param) { -// read_info_t* read = param; -// switch (ble_evt->header.evt_id) { - -// // More events may be handled later, so keep this as a switch. - -// case BLE_GATTC_EVT_READ_RSP: { -// ble_gattc_evt_t* evt = &ble_evt->evt.gattc_evt; -// ble_gattc_evt_read_rsp_t *response = &evt->params.read_rsp; -// if (read && evt->conn_handle == read->conn_handle) { -// read->status = evt->gatt_status; -// size_t len = MIN(read->len, response->len); -// memcpy(read->buf, response->data, len); -// read->final_len = len; -// // Indicate to busy-wait loop that we've read the attribute value. -// read->done = true; -// } -// break; -// } - -// default: -// // For debugging. -// // mp_printf(&mp_plat_print, "Unhandled characteristic event: 0x%04x\n", ble_evt->header.evt_id); -// return false; -// break; -// } -// return true; -// } - -size_t common_hal_bleio_gattc_read(uint16_t handle, uint16_t conn_handle, uint8_t* buf, size_t len) { - common_hal_bleio_check_connected(conn_handle); - - //FIX read_info_t read_info; - // read_info.buf = buf; - // read_info.len = len; - // read_info.final_len = 0; - // read_info.conn_handle = conn_handle; - // // Set to true by the event handler. - // read_info.done = false; - // ble_drv_add_event_handler(_on_gattc_read_rsp_evt, &read_info); - - // uint32_t nrf_error = NRF_ERROR_BUSY; - // while (nrf_error == NRF_ERROR_BUSY) { - // nrf_error = sd_ble_gattc_read(conn_handle, handle, 0); - // } - // if (nrf_error != NRF_SUCCESS) { - // ble_drv_remove_event_handler(_on_gattc_read_rsp_evt, &read_info); - // check_nrf_error(nrf_error); - // } - - // while (!read_info.done) { - // RUN_BACKGROUND_TASKS; - // } - - // ble_drv_remove_event_handler(_on_gattc_read_rsp_evt, &read_info); - // check_gatt_status(read_info.status); - // return read_info.final_len; - return 0; -} - -void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response) { - common_hal_bleio_check_connected(conn_handle); - - //FIX - // ble_gattc_write_params_t write_params = { - // .write_op = write_no_response ? BLE_GATT_OP_WRITE_CMD: BLE_GATT_OP_WRITE_REQ, - // .handle = handle, - // .p_value = bufinfo->buf, - // .len = bufinfo->len, - // }; - - // while (1) { - // uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params); - // if (err_code == NRF_SUCCESS) { - // break; - // } - - // // Write with response will return NRF_ERROR_BUSY if the response has not been received. - // // Write without reponse will return NRF_ERROR_RESOURCES if too many writes are pending. - // if (err_code == NRF_ERROR_BUSY || err_code == NRF_ERROR_RESOURCES) { - // // We could wait for an event indicating the write is complete, but just retrying is easier. - // MICROPY_VM_HOOK_LOOP; - // continue; - // } - - // // Some real error occurred. - // check_nrf_error(err_code); - // } -} - void common_hal_bleio_gc_collect(void) { bleio_adapter_gc_collect(&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 index e84320e30..086d56a4b 100644 --- a/devices/ble_hci/common-hal/_bleio/__init__.h +++ b/devices/ble_hci/common-hal/_bleio/__init__.h @@ -31,6 +31,7 @@ #include "shared-bindings/_bleio/UUID.h" +#include "att.h" #include "hci.h" void bleio_background(void); @@ -44,7 +45,7 @@ typedef struct { // We assume variable length data. // 20 bytes max (23 - 3). -#define GATT_MAX_DATA_LENGTH (BLE_GATT_ATT_MTU_DEFAULT - 3) +#define GATT_MAX_DATA_LENGTH (BT_ATT_DEFAULT_LE_MTU - 3) //FIX #define BLE_GATT_HANDLE_INVALID 0x0000 diff --git a/devices/ble_hci/common-hal/_bleio/att.c b/devices/ble_hci/common-hal/_bleio/att.c index 603f1dde3..aa436faa5 100644 --- a/devices/ble_hci/common-hal/_bleio/att.c +++ b/devices/ble_hci/common-hal/_bleio/att.c @@ -64,8 +64,6 @@ typedef struct __packed { uint8_t uuid[0]; // 2 or 16 bytes } characteristic_declaration_t; -//FIX BLEDeviceEventHandler event_handlers[2]; - 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) { @@ -220,21 +218,16 @@ bool att_connect_to_address(bt_addr_le_t *addr) { return is_connected; } -bool att_disconnect_from_address(bt_addr_le_t *addr) { - uint16_t conn_handle = att_conn_handle(addr); - if (conn_handle == 0xffff) { +bool att_disconnect(uint16_t conn_handle) { + if (conn_handle == BLE_CONN_HANDLE_INVALID) { return false; } hci_disconnect(conn_handle); - hci_poll_for_incoming_pkt_timeout(timeout); - if (!att_handle_is_connected(conn_handle)) { - return true; - } - - return false; + // Confirm we're now disconnected. + return !att_handle_is_connected(conn_handle); } //FIX @@ -512,10 +505,6 @@ void att_add_connection(uint16_t handle, uint8_t role, bt_addr_le_t *peer_addr, 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)); - - //FIX if (event_handlers[BLEConnected]) { - // event_handlers[BLEConnected](BLEDevice(peer_bdaddr_type, peer_bdaddr)); - // } } @@ -564,11 +553,6 @@ void att_remove_connection(uint16_t handle, uint8_t reason) { long_write_value_length = 0; } - //FIX - // if (event_handlers[BLEDisconnected]) { - // event_handlers[BLEDisconnected](bleDevice); - // } - 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)); @@ -630,7 +614,7 @@ bool att_disconnect_all(void) { continue; } - if (hci_disconnect(bleio_connections[i].conn_handle) != 0) { + if (att_disconnect(bleio_connections[i].conn_handle) != 0) { continue; } @@ -1391,7 +1375,8 @@ STATIC void process_write_req_or_cmd(uint16_t conn_handle, uint16_t mtu, uint8_t return; } - common_hal_bleio_characteristic_set_value(characteristic, &bufinfo); + // 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); @@ -1403,7 +1388,6 @@ STATIC void process_write_req_or_cmd(uint16_t conn_handle, uint16_t mtu, uint8_t return; } - //FIX need to set up event handlers, etc.? common_hal_bleio_descriptor_set_value(descriptor, &bufinfo); } @@ -1593,14 +1577,6 @@ bool att_exchange_mtu(uint16_t conn_handle) { return send_req_wait_for_rsp(conn_handle, sizeof(req), (uint8_t *) &req, response_buffer); } - - -//FIX void att_set_event_handler(BLEDeviceEvent event, BLEDeviceEventHandler event_handler) { -// if (event < (sizeof(event_handlers) / (sizeof(event_handlers[0])))) { -// event_handlers[event] = event_handler; -// } -// } - int att_read_req(uint16_t conn_handle, uint16_t handle, uint8_t response_buffer[]) { struct __packed { struct bt_att_hdr h; @@ -1642,7 +1618,7 @@ void att_write_cmd(uint16_t conn_handle, uint16_t handle, const uint8_t* data, u cmd->r.handle = handle; memcpy(cmd->r.value, data, data_len); - return send_req(conn_handle, sizeof(cmd_bytes), cmd_bytes); + send_req(conn_handle, sizeof(cmd_bytes), cmd_bytes); } void att_process_data(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) { @@ -1738,3 +1714,76 @@ void att_process_data(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) { 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 index 820e86bfb..2b1723440 100644 --- a/devices/ble_hci/common-hal/_bleio/att.h +++ b/devices/ble_hci/common-hal/_bleio/att.h @@ -35,8 +35,8 @@ 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_disconnect_from_address(bt_addr_le_t *addr); 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); diff --git a/devices/ble_hci/common-hal/_bleio/hci.c b/devices/ble_hci/common-hal/_bleio/hci.c index 52452a26d..f29121aaa 100644 --- a/devices/ble_hci/common-hal/_bleio/hci.c +++ b/devices/ble_hci/common-hal/_bleio/hci.c @@ -172,15 +172,14 @@ STATIC void process_evt_pkt(size_t pkt_len, uint8_t pkt_data[]) struct bt_hci_evt_disconn_complete *disconn_complete = (struct bt_hci_evt_disconn_complete*) pkt->params; (void) disconn_complete; - //FIX - // ATT.removeConnection(disconn_complete->handle, disconn_complete->reason); - // L2CAPSignaling.removeConnection(disconn_complete->handle, disconn_complete->reason); + + att_remove_connection(disconn_complete->handle, disconn_complete->reason); + //FIX L2CAPSignaling.removeConnection(disconn_complete->handle, disconn_complete->reason); hci_le_set_advertising_enable(0x01); 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; @@ -238,19 +237,21 @@ STATIC void process_evt_pkt(size_t pkt_len, uint8_t pkt_data[]) (struct bt_hci_evt_le_conn_complete *) le_evt; if (le_conn_complete->status == BT_HCI_ERR_SUCCESS) { - // ATT.addConnection(le_conn_complete->handle, - // le_conn_complete->role, - // le_conn_complete->peer_addr //FIX struct - // le_conn_complete->interval, - // le_conn_complete->latency, - // le_conn_complete->supv_timeout - // le_conn_complete->clock_accuracy); + 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 handle kind of advertising + if (le_advertising_info->evt_type == BT_HCI_ADV_DIRECT_IND) { + //FIX // last byte is RSSI // GAP.handleLeAdvertisingReport(leAdvertisingReport->type, // leAdvertisingReport->peerBdaddrType, @@ -538,7 +539,7 @@ hci_result_t hci_read_rssi(uint16_t handle, int *rssi) { return result; } -hci_result_t hci_set_evt_mask(uint64_t event_mask) { +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); } diff --git a/devices/ble_hci/common-hal/_bleio/hci.h b/devices/ble_hci/common-hal/_bleio/hci.h index d907a84b7..5dc831eb4 100644 --- a/devices/ble_hci/common-hal/_bleio/hci.h +++ b/devices/ble_hci/common-hal/_bleio/hci.h @@ -75,6 +75,6 @@ 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, uint8_t data_len, uint8_t *data); -hci_result_t hci_set_evt_mask(uint64_t event_mask); +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/ports/nrf/common-hal/_bleio/Characteristic.c b/ports/nrf/common-hal/_bleio/Characteristic.c index cacd53417..57c481448 100644 --- a/ports/nrf/common-hal/_bleio/Characteristic.c +++ b/ports/nrf/common-hal/_bleio/Characteristic.c @@ -90,6 +90,7 @@ 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->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; @@ -105,10 +106,6 @@ 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); - } } mp_obj_tuple_t *common_hal_bleio_characteristic_get_descriptors(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, diff --git a/ports/nrf/common-hal/_bleio/Characteristic.h b/ports/nrf/common-hal/_bleio/Characteristic.h index 19970ef82..382fd4a81 100644 --- a/ports/nrf/common-hal/_bleio/Characteristic.h +++ b/ports/nrf/common-hal/_bleio/Characteristic.h @@ -39,7 +39,7 @@ 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; diff --git a/ports/nrf/common-hal/_bleio/Connection.c b/ports/nrf/common-hal/_bleio/Connection.c index fccb5a22a..4f747bf97 100644 --- a/ports/nrf/common-hal/_bleio/Connection.c +++ b/ports/nrf/common-hal/_bleio/Connection.c @@ -523,7 +523,7 @@ 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(MP_OBJ_FROM_PTR(m_char_discovery_service->characteristic_list), MP_OBJ_FROM_PTR(characteristic)); diff --git a/ports/nrf/common-hal/_bleio/Descriptor.c b/ports/nrf/common-hal/_bleio/Descriptor.c index faf50c658..9e9110723 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 f76510d12..4d6ac2543 100644 --- a/ports/nrf/common-hal/_bleio/Descriptor.h +++ b/ports/nrf/common-hal/_bleio/Descriptor.h @@ -41,7 +41,7 @@ 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; diff --git a/ports/nrf/common-hal/_bleio/Service.c b/ports/nrf/common-hal/_bleio/Service.c index 8c57442f2..3159d3392 100644 --- a/ports/nrf/common-hal/_bleio/Service.c +++ b/ports/nrf/common-hal/_bleio/Service.c @@ -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, }; -- cgit v1.2.3 From 58573a70e19d69efd78f75a4780b55dced0e3cda Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Fri, 21 Aug 2020 11:02:24 -0400 Subject: bring submodules up to date --- frozen/circuitpython-stage | 2 +- lib/mp3 | 2 +- lib/protomatter | 2 +- lib/tinyusb | 2 +- ports/atmel-samd/asf4 | 2 +- ports/atmel-samd/peripherals | 2 +- ports/cxd56/spresense-exported-sdk | 2 +- ports/esp32s2/esp-idf | 2 +- ports/stm/st_driver | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) (limited to 'ports') diff --git a/frozen/circuitpython-stage b/frozen/circuitpython-stage index 0d2c083a2..9596a5904 160000 --- a/frozen/circuitpython-stage +++ b/frozen/circuitpython-stage @@ -1 +1 @@ -Subproject commit 0d2c083a2fb57a1562d4806775f45273abbfbfae +Subproject commit 9596a5904ed757e6fbffcf03e7aa77ae9ecf5223 diff --git a/lib/mp3 b/lib/mp3 index c3c664bf4..bc58a6549 160000 --- a/lib/mp3 +++ b/lib/mp3 @@ -1 +1 @@ -Subproject commit c3c664bf4db6a36d11808dfcbb5dbf7cff1715b8 +Subproject commit bc58a654964c799e972719a63ff12694998f3549 diff --git a/lib/protomatter b/lib/protomatter index 9f71088d2..761d6437e 160000 --- a/lib/protomatter +++ b/lib/protomatter @@ -1 +1 @@ -Subproject commit 9f71088d2c32206c6f0495704ae0c040426d5764 +Subproject commit 761d6437e8cd6a131d51de96974337121a9c7164 diff --git a/lib/tinyusb b/lib/tinyusb index dc5445e2f..22100b252 160000 --- a/lib/tinyusb +++ b/lib/tinyusb @@ -1 +1 @@ -Subproject commit dc5445e2f45cb348a44fe24fc1be4bc8b5ba5bab +Subproject commit 22100b252fc2eb8f51ed407949645653c4880fd9 diff --git a/ports/atmel-samd/asf4 b/ports/atmel-samd/asf4 index c0eef7b75..35a152579 160000 --- a/ports/atmel-samd/asf4 +++ b/ports/atmel-samd/asf4 @@ -1 +1 @@ -Subproject commit c0eef7b75124fc946af5f75e12d82d6d01315ab1 +Subproject commit 35a1525796c7ef8a3893d90befdad2f267fca20e diff --git a/ports/atmel-samd/peripherals b/ports/atmel-samd/peripherals index e4161d7d6..0f5f1522d 160000 --- a/ports/atmel-samd/peripherals +++ b/ports/atmel-samd/peripherals @@ -1 +1 @@ -Subproject commit e4161d7d6d98d78eddcccb82128856af4baf7e50 +Subproject commit 0f5f1522d09c8fa7d858edec484a994c21c59668 diff --git a/ports/cxd56/spresense-exported-sdk b/ports/cxd56/spresense-exported-sdk index 7f6568c7f..c991d439f 160000 --- a/ports/cxd56/spresense-exported-sdk +++ b/ports/cxd56/spresense-exported-sdk @@ -1 +1 @@ -Subproject commit 7f6568c7f4898cdb24a2f06040784a836050686e +Subproject commit c991d439fac9c23cfcac0da16fe8055f818d40a4 diff --git a/ports/esp32s2/esp-idf b/ports/esp32s2/esp-idf index 7aae7f034..160ba4924 160000 --- a/ports/esp32s2/esp-idf +++ b/ports/esp32s2/esp-idf @@ -1 +1 @@ -Subproject commit 7aae7f034bab68d2dd6aaa763924c91eb697d87e +Subproject commit 160ba4924d8b588e718f76e3a0d0e92c11052fa3 diff --git a/ports/stm/st_driver b/ports/stm/st_driver index 3fc2e0f3d..190083475 160000 --- a/ports/stm/st_driver +++ b/ports/stm/st_driver @@ -1 +1 @@ -Subproject commit 3fc2e0f3db155b33177bb0705e0dd65cadb58412 +Subproject commit 1900834751fd6754457874b8c971690bab33e0a7 -- cgit v1.2.3 From c137a1612133e06d2b7bec06b325695c9a60c4b9 Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Mon, 24 Aug 2020 14:49:06 -0400 Subject: Remove Meowbit LSE flag, harsher failure for LSE issues --- ports/stm/boards/meowbit_v121/mpconfigboard.h | 3 +-- ports/stm/peripherals/stm32f4/clocks.c | 17 +++-------------- ports/stm/peripherals/stm32f7/clocks.c | 17 +++-------------- ports/stm/peripherals/stm32h7/clocks.c | 17 +++-------------- 4 files changed, 10 insertions(+), 44 deletions(-) (limited to 'ports') diff --git a/ports/stm/boards/meowbit_v121/mpconfigboard.h b/ports/stm/boards/meowbit_v121/mpconfigboard.h index 106f25b15..be9f2a75f 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/peripherals/stm32f4/clocks.c b/ports/stm/peripherals/stm32f4/clocks.c index 7a16812b3..c2d0a452a 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 93016f682..f13088782 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 0e4e79f9f..a088f78bf 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? - } } -- cgit v1.2.3 From de9fd4a0fb26c1a62b97d6175c75568b68e50abd Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Mon, 24 Aug 2020 17:59:13 -0400 Subject: Fix null dereference, invert auto_brightness to reenable screen --- ports/stm/boards/meowbit_v121/board.c | 2 +- ports/stm/boards/meowbit_v121/mpconfigboard.mk | 4 +++- ports/stm/common-hal/pulseio/PWMOut.c | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'ports') diff --git a/ports/stm/boards/meowbit_v121/board.c b/ports/stm/boards/meowbit_v121/board.c index 812a8c208..b74f13516 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.mk b/ports/stm/boards/meowbit_v121/mpconfigboard.mk index 852836ef8..9eaa1bd8f 100644 --- a/ports/stm/boards/meowbit_v121/mpconfigboard.mk +++ b/ports/stm/boards/meowbit_v121/mpconfigboard.mk @@ -18,4 +18,6 @@ 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/pulseio/PWMOut.c b/ports/stm/common-hal/pulseio/PWMOut.c index ddbadaf4c..4bcb07212 100644 --- a/ports/stm/common-hal/pulseio/PWMOut.c +++ b/ports/stm/common-hal/pulseio/PWMOut.c @@ -239,13 +239,14 @@ void common_hal_pulseio_pwmout_deinit(pulseio_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_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty) { -- cgit v1.2.3 From 563e038c0d210dd0d17f6dc65f2c9eb5bbff1892 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 27 Aug 2020 15:11:17 -0500 Subject: stm: Specify max endpoints for stm32f405xx .. which is why we can't have HID or MIDI on the stm32f405 feather --- ports/stm/mpconfigport.mk | 1 + 1 file changed, 1 insertion(+) (limited to 'ports') diff --git a/ports/stm/mpconfigport.mk b/ports/stm/mpconfigport.mk index 19f9ffa44..b827aa48b 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) -- cgit v1.2.3 From a09243472cf4e57d9c157ecd4c55416a42fb7081 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Fri, 28 Aug 2020 16:08:24 -0700 Subject: Add Kaluga board definition --- .github/workflows/build.yml | 1 + ports/esp32s2/boards/espressif_kaluga_1/board.c | 47 +++++++++++++++ .../boards/espressif_kaluga_1/mpconfigboard.h | 34 +++++++++++ .../boards/espressif_kaluga_1/mpconfigboard.mk | 17 ++++++ ports/esp32s2/boards/espressif_kaluga_1/pins.c | 66 ++++++++++++++++++++++ ports/esp32s2/boards/espressif_kaluga_1/sdkconfig | 33 +++++++++++ 6 files changed, 198 insertions(+) create mode 100644 ports/esp32s2/boards/espressif_kaluga_1/board.c create mode 100644 ports/esp32s2/boards/espressif_kaluga_1/mpconfigboard.h create mode 100644 ports/esp32s2/boards/espressif_kaluga_1/mpconfigboard.mk create mode 100644 ports/esp32s2/boards/espressif_kaluga_1/pins.c create mode 100644 ports/esp32s2/boards/espressif_kaluga_1/sdkconfig (limited to 'ports') diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a8528168a..e780f652a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -409,6 +409,7 @@ jobs: matrix: board: - "electroniccats_bastwifi" + - "espressif_kaluga_1" - "espressif_saola_1_wroom" - "espressif_saola_1_wrover" - "microdev_micro_s2" 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 000000000..9f708874b --- /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 000000000..84d15ffc2 --- /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 000000000..43b1a9a68 --- /dev/null +++ b/ports/esp32s2/boards/espressif_kaluga_1/mpconfigboard.mk @@ -0,0 +1,17 @@ +USB_VID = 0x239A +USB_PID = 0x80A6 +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 000000000..b0e9957a1 --- /dev/null +++ b/ports/esp32s2/boards/espressif_kaluga_1/pins.c @@ -0,0 +1,66 @@ +#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_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_NEOPIXEL), MP_ROM_PTR(&pin_GPIO45) }, +}; +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 000000000..9d8bbde96 --- /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 -- cgit v1.2.3 From 81870413af5efc35beb31449a099fb69ba05e15c Mon Sep 17 00:00:00 2001 From: lady ada Date: Fri, 28 Aug 2020 19:08:36 -0400 Subject: add default I2C --- ports/atmel-samd/boards/blm_badge/pins.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'ports') diff --git a/ports/atmel-samd/boards/blm_badge/pins.c b/ports/atmel-samd/boards/blm_badge/pins.c index af1b69358..6e7d8da75 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); -- cgit v1.2.3 From 0bb5c6c07fdb0ce4100cd4b8a9465ad9f4d090ff Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Fri, 28 Aug 2020 16:37:25 -0700 Subject: Add unique USB PID --- ports/esp32s2/boards/espressif_kaluga_1/mpconfigboard.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ports') diff --git a/ports/esp32s2/boards/espressif_kaluga_1/mpconfigboard.mk b/ports/esp32s2/boards/espressif_kaluga_1/mpconfigboard.mk index 43b1a9a68..ba85e46ef 100644 --- a/ports/esp32s2/boards/espressif_kaluga_1/mpconfigboard.mk +++ b/ports/esp32s2/boards/espressif_kaluga_1/mpconfigboard.mk @@ -1,5 +1,5 @@ USB_VID = 0x239A -USB_PID = 0x80A6 +USB_PID = 0x80C8 USB_PRODUCT = "Kaluga 1" USB_MANUFACTURER = "Espressif" -- cgit v1.2.3 From 7b59ede25e4bba09e2b104c2404399bbf0af7fb6 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Fri, 28 Aug 2020 18:22:22 -0700 Subject: Add remaining pins --- ports/esp32s2/boards/espressif_kaluga_1/pins.c | 61 +++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) (limited to 'ports') diff --git a/ports/esp32s2/boards/espressif_kaluga_1/pins.c b/ports/esp32s2/boards/espressif_kaluga_1/pins.c index b0e9957a1..c1657d6c0 100644 --- a/ports/esp32s2/boards/espressif_kaluga_1/pins.c +++ b/ports/esp32s2/boards/espressif_kaluga_1/pins.c @@ -44,6 +44,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { 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) }, @@ -61,6 +63,63 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { 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_NEOPIXEL), MP_ROM_PTR(&pin_GPIO45) }, + + { 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); -- cgit v1.2.3 From 4ac7650f22c049d9059e6173e55cf44c43b1b5ac Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 31 Aug 2020 23:56:38 -0400 Subject: matrix portal board --- .github/workflows/build.yml | 1 + ports/atmel-samd/boards/matrixportal_m4/board.c | 39 ++++++++++++++ .../boards/matrixportal_m4/mpconfigboard.h | 30 +++++++++++ .../boards/matrixportal_m4/mpconfigboard.mk | 12 +++++ ports/atmel-samd/boards/matrixportal_m4/pins.c | 61 ++++++++++++++++++++++ 5 files changed, 143 insertions(+) create mode 100644 ports/atmel-samd/boards/matrixportal_m4/board.c create mode 100644 ports/atmel-samd/boards/matrixportal_m4/mpconfigboard.h create mode 100644 ports/atmel-samd/boards/matrixportal_m4/mpconfigboard.mk create mode 100644 ports/atmel-samd/boards/matrixportal_m4/pins.c (limited to 'ports') diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e780f652a..ec57f889f 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" 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 000000000..2d4f30239 --- /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 000000000..0368d577b --- /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 000000000..44b28acbc --- /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 000000000..34865597b --- /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); -- cgit v1.2.3 From ad4bf75367b1b1992d653428593c0f66f5b5e7ff Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 1 Sep 2020 10:05:13 -0500 Subject: samd: only set NDEBUG for non-debug builds --- ports/atmel-samd/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'ports') diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index 30487ae3e..25dc0cf15 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -107,7 +107,7 @@ 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 @@ -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. -- cgit v1.2.3 From 952d9bbb4a99cc598b56e170cdc05d94087d0d6d Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 28 Aug 2020 11:24:36 -0500 Subject: samd: Ignore a maybe-uninitialized diagnostic in asf4 I encountered this when changing optimization flags for debugging purposes. The diagnostic appears spurious and unrelated to what I'm debugging. --- ports/atmel-samd/Makefile | 2 ++ 1 file changed, 2 insertions(+) (limited to 'ports') diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index 25dc0cf15..3b7ab75bb 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -258,6 +258,8 @@ 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 = \ -- cgit v1.2.3