From 439eca03d4351e24a5f94f48e765ed95ead8db68 Mon Sep 17 00:00:00 2001 From: Carlo Parata Date: Mon, 8 Feb 2021 16:11:26 +0100 Subject: [PATCH 1/5] Add static random address support for all ST BLE chips --- src/utility/HCISharedMemTransport.cpp | 200 +++++++- src/utility/HCISharedMemTransport.h | 5 + src/utility/HCISpiTransport.cpp | 639 +++++++++++++++++++++++++- src/utility/HCISpiTransport.h | 7 + 4 files changed, 829 insertions(+), 22 deletions(-) diff --git a/src/utility/HCISharedMemTransport.cpp b/src/utility/HCISharedMemTransport.cpp index 8ccd6b25..17526274 100644 --- a/src/utility/HCISharedMemTransport.cpp +++ b/src/utility/HCISharedMemTransport.cpp @@ -48,11 +48,17 @@ volatile uint16_t _write_index; /* fifo position when receiving */ /* var of different device steps during init and receiving */ volatile bool phase_bd_addr; volatile bool phase_tx_power; +volatile bool phase_gatt_init; +volatile bool phase_gap_init; +volatile bool phase_random_addr; +volatile bool phase_get_random_addr; volatile bool phase_reset; volatile bool phase_running; +volatile bool is_random_addr_msg; /** Bluetooth Device Address */ static uint8_t bd_addr_udn[CONFIG_DATA_PUBADDR_LEN]; +static uint8_t helper_random_addr[6]; /* Private functions ---------------------------------------------------------*/ /** @@ -175,12 +181,21 @@ void evt_received(TL_EvtPacket_t *hcievt) * the Reset packet is handled at HCI layer : the running_phase begins */ if (phase_running == false) { - /* check the Rx event of complete the previous bd_addr opcode 0xFC0C */ + /* check the Rx event of complete the previous bd_addr or random address opcode 0xFC0C */ if ((hcievt->evtserial.evt.evtcode == TL_BLEEVT_CC_OPCODE) && (hcievt->evtserial.evt.payload[0] == 0x01) && (hcievt->evtserial.evt.payload[1] == 0x0C) && (hcievt->evtserial.evt.payload[2] == 0xFC)) { - phase_bd_addr = true; + /* First setting must be global address and is_random_addr_msg should be false + * Second setting must be static random address and is_random_addr_msg should be true + */ + if(!is_random_addr_msg) { + phase_bd_addr = true; + is_random_addr_msg = true; + } else { + phase_random_addr = true; + is_random_addr_msg = false; + } if (hcievt->evtserial.evt.payload[3] != 0) { #if defined(PRINT_IPCC_INFO) printf("Error: wrong BD Addr\r\n"); @@ -203,6 +218,50 @@ void evt_received(TL_EvtPacket_t *hcievt) /* rx data is no more useful : not stored in the _rxbuff */ break; } + /* check the Rx event of complete the previous gatt init 0xFD01 */ + if ((hcievt->evtserial.evt.evtcode == TL_BLEEVT_CC_OPCODE) && + (hcievt->evtserial.evt.payload[0] == 0x01) && + (hcievt->evtserial.evt.payload[1] == 0x01) && + (hcievt->evtserial.evt.payload[2] == 0xFD)) { + phase_gatt_init = true; + if (hcievt->evtserial.evt.payload[3] != 0) { +#if defined(PRINT_IPCC_INFO) + printf("Error: wrong Random Addr\r\n"); +#endif /*(PRINT_IPCC_INFO)*/ + } + /* rx data is no more useful : not stored in the _rxbuff */ + break; + } + /* check the Rx event of complete the previous gap init 0xFC8A */ + if ((hcievt->evtserial.evt.evtcode == TL_BLEEVT_CC_OPCODE) && + (hcievt->evtserial.evt.payload[0] == 0x01) && + (hcievt->evtserial.evt.payload[1] == 0x8A) && + (hcievt->evtserial.evt.payload[2] == 0xFC)) { + phase_gap_init = true; + if (hcievt->evtserial.evt.payload[3] != 0) { +#if defined(PRINT_IPCC_INFO) + printf("Error: wrong Random Addr\r\n"); +#endif /*(PRINT_IPCC_INFO)*/ + } + /* rx data is no more useful : not stored in the _rxbuff */ + break; + } + /* check the Rx event of complete the previous get random addr opcode 0xFC0D */ + if ((hcievt->evtserial.evt.evtcode == TL_BLEEVT_CC_OPCODE) && + (hcievt->evtserial.evt.payload[0] == 0x01) && + (hcievt->evtserial.evt.payload[1] == 0x0D) && + (hcievt->evtserial.evt.payload[2] == 0xFC)) { + if (hcievt->evtserial.evt.payload[3] != 0) { +#if defined(PRINT_IPCC_INFO) + printf("Error: wrong Random Addr\r\n"); +#endif /*(PRINT_IPCC_INFO)*/ + } + + memcpy(helper_random_addr, &hcievt->evtserial.evt.payload[5], 6); + phase_get_random_addr = true; + /* rx data is no more useful : not stored in the _rxbuff */ + break; + } /* check if the reset phase is in progress (opcode is 0x0C03) */ if ((hcievt->evtserial.evt.evtcode == TL_BLEEVT_CC_OPCODE) && (hcievt->evtserial.evt.payload[0] == 0x01) && @@ -389,8 +448,13 @@ HCISharedMemTransportClass::HCISharedMemTransportClass() phase_bd_addr = false; phase_tx_power = false; + phase_gatt_init = false; + phase_gap_init = false; + phase_random_addr = false; + phase_get_random_addr = false; phase_reset = false; phase_running = false; + is_random_addr_msg = false; } HCISharedMemTransportClass::~HCISharedMemTransportClass() @@ -453,8 +517,13 @@ void HCISharedMemTransportClass::end() /* the HCI RESET command ready to be processed again */ phase_bd_addr = false; phase_tx_power = false; + phase_gatt_init = false; + phase_gap_init = false; + phase_random_addr = false; + phase_get_random_addr = false; phase_reset = false; phase_running = false; + is_random_addr_msg = false; } void HCISharedMemTransportClass::wait(unsigned long timeout) @@ -543,11 +612,34 @@ size_t HCISharedMemTransportClass::write(const uint8_t *data, size_t length) while (!phase_bd_addr); /* this sequence is now complete */ + /* set the random address */ + bt_ipm_set_random_addr(); + /* wait for the Rx complete */ + while (!phase_random_addr); + /* set the Tx power */ bt_ipm_set_power(); /* wait for the Rx complete */ while (!phase_tx_power); + /* gatt init */ + bt_ipm_gatt_init(); + /* wait for the Rx complete */ + while (!phase_gatt_init); + + /* gap init */ + bt_ipm_gap_init(); + /* wait for the Rx complete */ + while (!phase_gap_init); + + /* get the random address */ + bt_ipm_get_random_addr(); + /* wait for the Rx complete */ + while (!phase_get_random_addr); + + /* Now we can copy the random address and save it in the transport class */ + memcpy(_random_addr, helper_random_addr, 6); + /* this sequence is now complete */ phase_running = true; @@ -725,6 +817,41 @@ int HCISharedMemTransportClass::bt_ipm_set_addr(void) return 0; /* Error */ } +int HCISharedMemTransportClass::bt_ipm_set_random_addr(void) +{ + /* the specific table for set addr is 8 bytes: + * one byte for config_offset + * one byte for length + * 6 bytes for payload */ + uint8_t data[4 + 8]; + + /* + * Static random Address + * The two upper bits shall be set to 1 + * The lowest 32bits is read from the UDN to differentiate between devices + * The RNG may be used to provide a random number on each power on + */ + uint32_t srd_bd_addr[2]; + + phase_random_addr = false; + + srd_bd_addr[1] = 0x0000ED6E; + srd_bd_addr[0] = LL_FLASH_GetUDN( ); + + data[0] = BT_BUF_CMD; + data[1] = uint8_t(ACI_WRITE_CONFIG_DATA_OPCODE & 0x000000FF); /* OCF */ + data[2] = uint8_t((ACI_WRITE_CONFIG_DATA_OPCODE & 0x0000FF00) >> 8); /* OGF */ + data[3] = 8; /* length of parameters */ + /* fill the ACI_HAL_WRITE_CONFIG_DATA with the addr*/ + data[4] = 0x2E; /* the offset */ + data[5] = 6; /* is the length of the random address */ + memcpy(data + 6, srd_bd_addr, 6); + /* send the ACI_HAL_WRITE_CONFIG_DATA */ + mbox_write(data[0], 11, &data[1]); + /* now wait for the corresponding Rx event */ + return 1; /* success */ +} + int HCISharedMemTransportClass::bt_ipm_set_power(void) { /* the specific table for power is 2 bytes: @@ -737,14 +864,79 @@ int HCISharedMemTransportClass::bt_ipm_set_power(void) data[1] = (uint8_t)(ACI_HAL_SET_TX_POWER_LEVEL & 0x000000FF); /* the OPCODE */ data[2] = (uint8_t)((ACI_HAL_SET_TX_POWER_LEVEL & 0x0000FF00) >> 8); data[3] = 2; /* the length */ - /* fill the ACI_HAL_WRITE_CONFIG_DATA */ + /* fill the SET_POWER */ data[4] = 0x01; /* En_High_Power */ data[5] = CFG_TX_POWER; /* PA_level */ - /* send the ACI_HAL_WRITE_CONFIG_DATA */ + /* send the SET_POWER */ mbox_write(data[0], 5, &data[1]); /* now wait for the corresponding Rx event */ return 1; /* success */ } +int HCISharedMemTransportClass::bt_ipm_gatt_init(void) +{ + /* the specific table for gatt init */ + uint8_t data[4]; + + phase_gatt_init = false; + + data[0] = BT_BUF_CMD; /* the type */ + data[1] = 0x01; /* the OPCODE */ + data[2] = 0xFD; + data[3] = 0; /* the length */ + + /* send the GATT_INIT */ + mbox_write(data[0], 3, &data[1]); + /* now wait for the corresponding Rx event */ + return 1; /* success */ +} + +int HCISharedMemTransportClass::bt_ipm_gap_init(void) +{ + /* the specific table for gap init is 3 bytes: + * Role byte, enable_privacy byte, device_name_char_len byte */ + uint8_t data[4 + 3]; + + phase_tx_power = false; + + data[0] = BT_BUF_CMD; /* the type */ + data[1] = 0x8A; /* the OPCODE */ + data[2] = 0xFC; + data[3] = 3; /* the length */ + /* fill the GAP_INIT */ + data[4] = 0x0F; /* role */ + data[5] = 0x00; /* enable_privacy */ + data[6] = 0x00; /* device_name_char_len */ + + /* send the GAP_INIT */ + mbox_write(data[0], 6, &data[1]); + /* now wait for the corresponding Rx event */ + return 1; /* success */ +} + +int HCISharedMemTransportClass::bt_ipm_get_random_addr(void) +{ + /* the specific table for set addr is 8 bytes: + * one byte for config_offset + * one byte for length + * 6 bytes for payload */ + uint8_t data[4 + 1]; + + phase_get_random_addr = false; + + /* create ACI_READ_CONFIG_DATA_OPCODE */ + data[0] = BT_BUF_CMD; + data[1] = uint8_t(ACI_READ_CONFIG_DATA_OPCODE & 0x000000FF); /* OCF */ + data[2] = uint8_t((ACI_READ_CONFIG_DATA_OPCODE & 0x0000FF00) >> 8); /* OGF */ + data[3] = 1; /* length of parameters */ + /* fill the ACI_READ_CONFIG_DATA_OPCODE with the offset*/ + data[4] = 0x2E; /* the offset */ + + /* send the ACI_READ_CONFIG_DATA_OPCODE */ + mbox_write(data[0], 4, &data[1]); + /* now wait for the corresponding Rx event */ + return 1; /* success */ +} + #endif /* STM32WBxx */ diff --git a/src/utility/HCISharedMemTransport.h b/src/utility/HCISharedMemTransport.h index 9b9751f2..e4bd6ed6 100644 --- a/src/utility/HCISharedMemTransport.h +++ b/src/utility/HCISharedMemTransport.h @@ -87,8 +87,13 @@ class HCISharedMemTransportClass : public HCITransportInterface { int stm32wb_start_ble(void); int bt_ipm_ble_init(void); int bt_ipm_set_addr(void); + int bt_ipm_set_random_addr(void); int bt_ipm_set_power(void); + int bt_ipm_gatt_init(void); + int bt_ipm_gap_init(void); + int bt_ipm_get_random_addr(void); + uint8_t _random_addr[6]; }; #endif /* _HCI_SHARED_MEM_TRANSPORT_H_ */ diff --git a/src/utility/HCISpiTransport.cpp b/src/utility/HCISpiTransport.cpp index 512e6e9a..cb2430c2 100644 --- a/src/utility/HCISpiTransport.cpp +++ b/src/utility/HCISpiTransport.cpp @@ -237,6 +237,15 @@ int HCISpiTransportClass::available() delay(300); } + /* Call ACI Gatt Init and ACI Gap Init to activate the random BLE address */ + aci_gatt_init(); + wait_for_aci_gatt_init(); + aci_gap_init(); + wait_for_aci_gap_init(); + /* Call ACI Read Config Parameter to retrieve the random BLE address */ + aci_read_config_parameter(); + wait_for_aci_read_config_parameter(); + /* Now we can update the write index and close the initial phase */ _write_index = _write_index_initial; _initial_phase = 0; @@ -397,6 +406,10 @@ void HCISpiTransportClass::wait_for_blue_initialize() while (digitalRead(_spi_irq) == 1) { uint8_t header_master[5] = {0x0b, 0x00, 0x00, 0x00, 0x00}; + if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) { + detachInterrupt(_spi_irq); + } + _spi->beginTransaction(_spiSettings); digitalWrite(_cs_pin, LOW); @@ -404,9 +417,35 @@ void HCISpiTransportClass::wait_for_blue_initialize() /* Write the header */ _spi->transfer(header_master, 5); - /* device is ready */ - if (header_master[0] == 0x02) { + if (_ble_chip == SPBTLE_RF || _ble_chip == BLUENRG_M0) { /* device is ready */ + if (header_master[0] == 0x02) { + /* device is ready */ + uint16_t byte_count = (header_master[4] << 8) | header_master[3]; + + if (byte_count > 0) { + /* Read the response */ + if (byte_count == 6) { + for (int j = 0; j < byte_count; j++) { + event[j] = _spi->transfer(0xFF); + } + + if (event[0] == 0x04 && + event[1] == 0xFF && + event[2] == 0x03 && + event[3] == 0x01 && + event[4] == 0x00 && + event[5] == 0x01) { + event_blue_initialize = 1; + } + } else { + for (int j = 0; j < byte_count; j++) { + _spi->transfer(0xFF); + } + } + } + } + } else if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) { uint16_t byte_count = (header_master[4] << 8) | header_master[3]; if (byte_count > 0) { @@ -435,6 +474,10 @@ void HCISpiTransportClass::wait_for_blue_initialize() digitalWrite(_cs_pin, HIGH); _spi->endTransaction(); + + if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) { + attachInterrupt(_spi_irq, SPI_Irq_Callback, RISING); + } } } while (!event_blue_initialize); } @@ -455,6 +498,10 @@ void HCISpiTransportClass::wait_for_enable_ll_only() while (digitalRead(_spi_irq) == 1) { uint8_t header_master[5] = {0x0b, 0x00, 0x00, 0x00, 0x00}; + if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) { + detachInterrupt(_spi_irq); + } + _spi->beginTransaction(_spiSettings); digitalWrite(_cs_pin, LOW); @@ -462,9 +509,32 @@ void HCISpiTransportClass::wait_for_enable_ll_only() /* Write the header */ _spi->transfer(header_master, 5); - /* device is ready */ - if (header_master[0] == 0x02) { + if (_ble_chip == SPBTLE_RF || _ble_chip == BLUENRG_M0) { /* device is ready */ + if (header_master[0] == 0x02) { + /* device is ready */ + uint16_t byte_count = (header_master[4] << 8) | header_master[3]; + + if (byte_count > 0) { + /* Read the response */ + for (int j = 0; j < byte_count; j++) { + data[j] = _spi->transfer(0xFF); + } + + if (byte_count >= 7) { + if (data[0] == 0x04 && + data[1] == 0x0E && + data[2] == 0x04 && + data[3] == 0x01 && + data[4] == 0x0C && + data[5] == 0xFC && + data[6] == 0x00) { + status = 1; + } + } + } + } + } else if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) { uint16_t byte_count = (header_master[4] << 8) | header_master[3]; if (byte_count > 0) { @@ -473,7 +543,7 @@ void HCISpiTransportClass::wait_for_enable_ll_only() data[j] = _spi->transfer(0xFF); } - if (byte_count == 7) { + if (byte_count >= 7) { if (data[0] == 0x04 && data[1] == 0x0E && data[2] == 0x04 && @@ -490,6 +560,10 @@ void HCISpiTransportClass::wait_for_enable_ll_only() digitalWrite(_cs_pin, HIGH); _spi->endTransaction(); + + if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) { + attachInterrupt(_spi_irq, SPI_Irq_Callback, RISING); + } } } while (!status); } @@ -501,30 +575,559 @@ void HCISpiTransportClass::enable_ll_only() int result = 0; do { - result = 0; + if (_ble_chip == SPBTLE_RF || _ble_chip == BLUENRG_M0) { + result = 0; + + _spi->beginTransaction(_spiSettings); + + digitalWrite(_cs_pin, LOW); + + /* Write the header */ + _spi->transfer(header_master, 5); + + /* device is ready */ + if (header_master[0] == 0x02) { + /* Write the data */ + if (header_master[1] >= 7) { + /* Write the data */ + _spi->transfer((void *)cmd, 7); + } else { + result = -2; + } + } else { + result = -1; + } + + digitalWrite(_cs_pin, HIGH); + + _spi->endTransaction(); + } else if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) { + uint32_t tickstart_data_available = millis(); + result = 0; + + detachInterrupt(_spi_irq); + + _spi->beginTransaction(_spiSettings); + + digitalWrite(_cs_pin, LOW); - _spi->beginTransaction(_spiSettings); + while (!(digitalRead(_spi_irq) == 1)) { + if ((millis() - tickstart_data_available) > 1000) { + result = -3; + break; + } + } - digitalWrite(_cs_pin, LOW); + if (result == -3) { + digitalWrite(_cs_pin, HIGH); + _spi->endTransaction(); + attachInterrupt(_spi_irq, SPI_Irq_Callback, RISING); + break; + } - /* Write the header */ - _spi->transfer(header_master, 5); + /* Write the header */ + _spi->transfer(header_master, 5); - /* device is ready */ - if (header_master[0] == 0x02) { - /* Write the data */ - if (header_master[1] >= 7) { + if ((int)((((uint16_t)header_master[2]) << 8) | ((uint16_t)header_master[1])) >= 7) { /* Write the data */ _spi->transfer((void *)cmd, 7); } else { result = -2; } - } else { - result = -1; + + digitalWrite(_cs_pin, HIGH); + + _spi->endTransaction(); + + attachInterrupt(_spi_irq, SPI_Irq_Callback, RISING); + } + } while (result < 0); +} + +void HCISpiTransportClass::wait_for_aci_gatt_init() +{ + uint8_t data[8]; + int status = 0; + + do { + while (!data_avail); + + if (digitalRead(_spi_irq) == 0) { + continue; + } + + data_avail = 0; + while (digitalRead(_spi_irq) == 1) { + uint8_t header_master[5] = {0x0b, 0x00, 0x00, 0x00, 0x00}; + + if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) { + detachInterrupt(_spi_irq); + } + + _spi->beginTransaction(_spiSettings); + + digitalWrite(_cs_pin, LOW); + + /* Write the header */ + _spi->transfer(header_master, 5); + + if (_ble_chip == SPBTLE_RF || _ble_chip == BLUENRG_M0) { + /* device is ready */ + if (header_master[0] == 0x02) { + /* device is ready */ + uint16_t byte_count = (header_master[4] << 8) | header_master[3]; + + if (byte_count > 0) { + /* Read the response */ + for (int j = 0; j < byte_count; j++) { + data[j] = _spi->transfer(0xFF); + } + + if (byte_count >= 7) { + if (data[0] == 0x04 && + data[1] == 0x0E && + data[2] == 0x04 && + data[3] == 0x01 && + data[4] == 0x01 && + data[5] == 0xFD && + data[6] == 0x00) { + status = 1; + } + } + } + } + } else if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) { + uint16_t byte_count = (header_master[4] << 8) | header_master[3]; + + if (byte_count > 0) { + /* Read the response */ + for (int j = 0; j < byte_count; j++) { + data[j] = _spi->transfer(0xFF); + } + + if (byte_count >= 7) { + if (data[0] == 0x04 && + data[1] == 0x0E && + data[2] == 0x04 && + data[3] == 0x01 && + data[4] == 0x01 && + data[5] == 0xFD && + data[6] == 0x00) { + status = 1; + } + } + } + } + + digitalWrite(_cs_pin, HIGH); + + _spi->endTransaction(); + + if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) { + attachInterrupt(_spi_irq, SPI_Irq_Callback, RISING); + } + } + } while (!status); +} + +void HCISpiTransportClass::aci_gatt_init() +{ + uint8_t header_master[5] = {0x0a, 0x00, 0x00, 0x00, 0x00}; + uint8_t cmd[4] = {0x01, 0x01, 0xFD, 0x00}; // ACI_GATT_INIT + int result = 0; + + do { + if (_ble_chip == SPBTLE_RF || _ble_chip == BLUENRG_M0) { + result = 0; + + _spi->beginTransaction(_spiSettings); + + digitalWrite(_cs_pin, LOW); + + /* Write the header */ + _spi->transfer(header_master, 5); + + /* device is ready */ + if (header_master[0] == 0x02) { + /* Write the data */ + if (header_master[1] >= 4) { + /* Write the data */ + _spi->transfer((void *)cmd, 4); + } else { + result = -2; + } + } else { + result = -1; + } + + digitalWrite(_cs_pin, HIGH); + + _spi->endTransaction(); + } else if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) { + uint32_t tickstart_data_available = millis(); + result = 0; + + detachInterrupt(_spi_irq); + + _spi->beginTransaction(_spiSettings); + + digitalWrite(_cs_pin, LOW); + + while (!(digitalRead(_spi_irq) == 1)) { + if ((millis() - tickstart_data_available) > 1000) { + result = -3; + break; + } + } + + if (result == -3) { + digitalWrite(_cs_pin, HIGH); + _spi->endTransaction(); + attachInterrupt(_spi_irq, SPI_Irq_Callback, RISING); + break; + } + + /* Write the header */ + _spi->transfer(header_master, 5); + + if ((int)((((uint16_t)header_master[2]) << 8) | ((uint16_t)header_master[1])) >= 4) { + /* Write the data */ + _spi->transfer((void *)cmd, 4); + } else { + result = -2; + } + + digitalWrite(_cs_pin, HIGH); + + _spi->endTransaction(); + + attachInterrupt(_spi_irq, SPI_Irq_Callback, RISING); } + } while (result < 0); +} + +void HCISpiTransportClass::wait_for_aci_gap_init() +{ + uint8_t data[14]; + int status = 0; - digitalWrite(_cs_pin, HIGH); + do { + while (!data_avail); - _spi->endTransaction(); + if (digitalRead(_spi_irq) == 0) { + continue; + } + + data_avail = 0; + while (digitalRead(_spi_irq) == 1) { + uint8_t header_master[5] = {0x0b, 0x00, 0x00, 0x00, 0x00}; + + if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) { + detachInterrupt(_spi_irq); + } + + _spi->beginTransaction(_spiSettings); + + digitalWrite(_cs_pin, LOW); + + /* Write the header */ + _spi->transfer(header_master, 5); + + if (_ble_chip == SPBTLE_RF || _ble_chip == BLUENRG_M0) { + /* device is ready */ + if (header_master[0] == 0x02) { + /* device is ready */ + uint16_t byte_count = (header_master[4] << 8) | header_master[3]; + + if (byte_count > 0) { + /* Read the response */ + for (int j = 0; j < byte_count; j++) { + data[j] = _spi->transfer(0xFF); + } + + if (byte_count >= 13) { + if (data[0] == 0x04 && + data[1] == 0x0E && + data[2] == 0x0A && + data[3] == 0x01 && + data[4] == 0x8A && + data[5] == 0xFC && + data[6] == 0x00) { + status = 1; + } + } + } + } + } else if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) { + uint16_t byte_count = (header_master[4] << 8) | header_master[3]; + + if (byte_count > 0) { + /* Read the response */ + for (int j = 0; j < byte_count; j++) { + data[j] = _spi->transfer(0xFF); + } + + if (byte_count >= 13) { + if (data[0] == 0x04 && + data[1] == 0x0E && + data[2] == 0x0A && + data[3] == 0x01 && + data[4] == 0x8A && + data[5] == 0xFC && + data[6] == 0x00) { + status = 1; + } + } + } + } + + digitalWrite(_cs_pin, HIGH); + + _spi->endTransaction(); + + if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) { + attachInterrupt(_spi_irq, SPI_Irq_Callback, RISING); + } + } + } while (!status); +} + +void HCISpiTransportClass::aci_gap_init() +{ + uint8_t header_master[5] = {0x0a, 0x00, 0x00, 0x00, 0x00}; + uint8_t cmd[7] = {0x01, 0x8A, 0xFC, 0x03, 0x0F, 0x00, 0x00}; // ACI_GAP_INIT + int result = 0; + + do { + if (_ble_chip == SPBTLE_RF || _ble_chip == BLUENRG_M0) { + result = 0; + + _spi->beginTransaction(_spiSettings); + + digitalWrite(_cs_pin, LOW); + + /* Write the header */ + _spi->transfer(header_master, 5); + + /* device is ready */ + if (header_master[0] == 0x02) { + /* Write the data */ + if (header_master[1] >= 7) { + /* Write the data */ + _spi->transfer((void *)cmd, 7); + } else { + result = -2; + } + } else { + result = -1; + } + + digitalWrite(_cs_pin, HIGH); + + _spi->endTransaction(); + } else if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) { + uint32_t tickstart_data_available = millis(); + result = 0; + + detachInterrupt(_spi_irq); + + _spi->beginTransaction(_spiSettings); + + digitalWrite(_cs_pin, LOW); + + while (!(digitalRead(_spi_irq) == 1)) { + if ((millis() - tickstart_data_available) > 1000) { + result = -3; + break; + } + } + + if (result == -3) { + digitalWrite(_cs_pin, HIGH); + _spi->endTransaction(); + attachInterrupt(_spi_irq, SPI_Irq_Callback, RISING); + break; + } + + /* Write the header */ + _spi->transfer(header_master, 5); + + if ((int)((((uint16_t)header_master[2]) << 8) | ((uint16_t)header_master[1])) >= 7) { + /* Write the data */ + _spi->transfer((void *)cmd, 7); + } else { + result = -2; + } + + digitalWrite(_cs_pin, HIGH); + + _spi->endTransaction(); + + attachInterrupt(_spi_irq, SPI_Irq_Callback, RISING); + } + } while (result < 0); +} + +void HCISpiTransportClass::wait_for_aci_read_config_parameter() +{ + uint8_t data[15]; + int status = 0; + + do { + while (!data_avail); + + if (digitalRead(_spi_irq) == 0) { + continue; + } + + data_avail = 0; + while (digitalRead(_spi_irq) == 1) { + uint8_t header_master[5] = {0x0b, 0x00, 0x00, 0x00, 0x00}; + + if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) { + detachInterrupt(_spi_irq); + } + + _spi->beginTransaction(_spiSettings); + + digitalWrite(_cs_pin, LOW); + + /* Write the header */ + _spi->transfer(header_master, 5); + + if (_ble_chip == SPBTLE_RF || _ble_chip == BLUENRG_M0) { + /* device is ready */ + if (header_master[0] == 0x02) { + /* device is ready */ + uint16_t byte_count = (header_master[4] << 8) | header_master[3]; + + if (byte_count > 0) { + /* Read the response */ + for (int j = 0; j < byte_count; j++) { + data[j] = _spi->transfer(0xFF); + } + + if (byte_count >= 13) { + if (data[0] == 0x04 && + data[1] == 0x0E && + data[2] == 0x0A && + data[3] == 0x01 && + data[4] == 0x0D && + data[5] == 0xFC && + data[6] == 0x00) { + memcpy(_random_addr, &data[7], 6); + status = 1; + } + } + } + } + } else if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) { + uint16_t byte_count = (header_master[4] << 8) | header_master[3]; + + if (byte_count > 0) { + /* Read the response */ + for (int j = 0; j < byte_count; j++) { + data[j] = _spi->transfer(0xFF); + } + + if (byte_count >= 14) { + if (data[0] == 0x04 && + data[1] == 0x0E && + data[2] == 0x0B && + data[3] == 0x01 && + data[4] == 0x0D && + data[5] == 0xFC && + data[6] == 0x00) { + memcpy(_random_addr, &data[8], 6); + status = 1; + } + } + } + } + + digitalWrite(_cs_pin, HIGH); + + _spi->endTransaction(); + + if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) { + attachInterrupt(_spi_irq, SPI_Irq_Callback, RISING); + } + } + } while (!status); +} + +void HCISpiTransportClass::aci_read_config_parameter() +{ + uint8_t header_master[5] = {0x0a, 0x00, 0x00, 0x00, 0x00}; + uint8_t cmd[5] = {0x01, 0x0D, 0xFC, 0x01, 0x80}; // ACI_READ_CONFIG_PARAMETER + int result = 0; + + do { + if (_ble_chip == SPBTLE_RF || _ble_chip == BLUENRG_M0) { + result = 0; + + _spi->beginTransaction(_spiSettings); + + digitalWrite(_cs_pin, LOW); + + /* Write the header */ + _spi->transfer(header_master, 5); + + /* device is ready */ + if (header_master[0] == 0x02) { + /* Write the data */ + if (header_master[1] >= 5) { + /* Write the data */ + _spi->transfer((void *)cmd, 5); + } else { + result = -2; + } + } else { + result = -1; + } + + digitalWrite(_cs_pin, HIGH); + + _spi->endTransaction(); + } else if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) { + uint32_t tickstart_data_available = millis(); + result = 0; + + detachInterrupt(_spi_irq); + + _spi->beginTransaction(_spiSettings); + + digitalWrite(_cs_pin, LOW); + + while (!(digitalRead(_spi_irq) == 1)) { + if ((millis() - tickstart_data_available) > 1000) { + result = -3; + break; + } + } + + if (result == -3) { + digitalWrite(_cs_pin, HIGH); + _spi->endTransaction(); + attachInterrupt(_spi_irq, SPI_Irq_Callback, RISING); + break; + } + + /* Write the header */ + _spi->transfer(header_master, 5); + + if ((int)((((uint16_t)header_master[2]) << 8) | ((uint16_t)header_master[1])) >= 5) { + /* Write the data */ + _spi->transfer((void *)cmd, 5); + } else { + result = -2; + } + + digitalWrite(_cs_pin, HIGH); + + _spi->endTransaction(); + + attachInterrupt(_spi_irq, SPI_Irq_Callback, RISING); + } } while (result < 0); } diff --git a/src/utility/HCISpiTransport.h b/src/utility/HCISpiTransport.h index 4da3befb..9c3afc34 100644 --- a/src/utility/HCISpiTransport.h +++ b/src/utility/HCISpiTransport.h @@ -55,6 +55,12 @@ class HCISpiTransportClass : public HCITransportInterface { void wait_for_blue_initialize(); void wait_for_enable_ll_only(); void enable_ll_only(); + void wait_for_aci_gatt_init(); + void aci_gatt_init(); + void wait_for_aci_gap_init(); + void aci_gap_init(); + void wait_for_aci_read_config_parameter(); + void aci_read_config_parameter(); SPIClass *_spi; SPISettings _spiSettings; BLEChip_t _ble_chip; @@ -66,6 +72,7 @@ class HCISpiTransportClass : public HCITransportInterface { uint16_t _write_index; uint16_t _write_index_initial; uint8_t _initial_phase; + uint8_t _random_addr[6]; }; #endif /* _HCI_SPI_TRANSPORT_H_ */ From 9ec4d798943885f5bbd8e068456c67f03a2ad673 Mon Sep 17 00:00:00 2001 From: Carlo Parata Date: Mon, 8 Feb 2021 16:25:43 +0100 Subject: [PATCH 2/5] Fix code spelling issues --- src/utility/HCISpiTransport.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utility/HCISpiTransport.cpp b/src/utility/HCISpiTransport.cpp index cb2430c2..a503b427 100644 --- a/src/utility/HCISpiTransport.cpp +++ b/src/utility/HCISpiTransport.cpp @@ -237,12 +237,12 @@ int HCISpiTransportClass::available() delay(300); } - /* Call ACI Gatt Init and ACI Gap Init to activate the random BLE address */ + /* Call Gatt Init and Gap Init to activate the random BLE address */ aci_gatt_init(); wait_for_aci_gatt_init(); aci_gap_init(); wait_for_aci_gap_init(); - /* Call ACI Read Config Parameter to retrieve the random BLE address */ + /* Call Read Config Parameter to retrieve the random BLE address */ aci_read_config_parameter(); wait_for_aci_read_config_parameter(); From d1535a02b79afc3d1b9443e2f91a5b7dda1dc738 Mon Sep 17 00:00:00 2001 From: Carlo Parata Date: Mon, 8 Feb 2021 16:42:53 +0100 Subject: [PATCH 3/5] Fix typo --- src/utility/HCISharedMemTransport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utility/HCISharedMemTransport.cpp b/src/utility/HCISharedMemTransport.cpp index 17526274..50d7e83c 100644 --- a/src/utility/HCISharedMemTransport.cpp +++ b/src/utility/HCISharedMemTransport.cpp @@ -898,7 +898,7 @@ int HCISharedMemTransportClass::bt_ipm_gap_init(void) * Role byte, enable_privacy byte, device_name_char_len byte */ uint8_t data[4 + 3]; - phase_tx_power = false; + phase_gap_init = false; data[0] = BT_BUF_CMD; /* the type */ data[1] = 0x8A; /* the OPCODE */ From c1c7d1acbbc3a98cf668f3775f0ddfb1c9f06056 Mon Sep 17 00:00:00 2001 From: Carlo Parata Date: Tue, 9 Feb 2021 15:35:13 +0100 Subject: [PATCH 4/5] Add the possibility to choose the ownAddressType in the Arduino stack --- src/local/BLELocalDevice.cpp | 8 ++++++-- src/local/BLELocalDevice.h | 8 +++++++- src/utility/ATT.cpp | 7 ++++++- src/utility/ATT.h | 4 ++++ src/utility/GAP.cpp | 11 ++++++++--- src/utility/GAP.h | 3 +++ 6 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/local/BLELocalDevice.cpp b/src/local/BLELocalDevice.cpp index 78918760..21de8efc 100644 --- a/src/local/BLELocalDevice.cpp +++ b/src/local/BLELocalDevice.cpp @@ -23,8 +23,8 @@ #include "utility/L2CAPSignaling.h" #include "BLELocalDevice.h" -BLELocalDevice::BLELocalDevice(HCITransportInterface *HCITransport) : - _HCITransport(HCITransport) +BLELocalDevice::BLELocalDevice(HCITransportInterface *HCITransport, uint8_t ownBdaddrType) : + _HCITransport(HCITransport), _ownBdaddrType(ownBdaddrType) { _advertisingData.setFlags(BLEFlagsGeneralDiscoverable | BLEFlagsBREDRNotSupported); } @@ -76,6 +76,10 @@ int BLELocalDevice::begin() GATT.begin(); + GAP.setOwnBdaddrType(_ownBdaddrType); + + ATT.setOwnBdaddrType(_ownBdaddrType); + return 1; } diff --git a/src/local/BLELocalDevice.h b/src/local/BLELocalDevice.h index bcf3c416..beddb0ee 100644 --- a/src/local/BLELocalDevice.h +++ b/src/local/BLELocalDevice.h @@ -25,9 +25,14 @@ #include "BLEService.h" #include "BLEAdvertisingData.h" +#define PUBLIC_ADDR (0) +#define STATIC_RANDOM_ADDR (1) +#define RESOLVABLE_PRIVATE_ADDR (2) +#define NON_RESOLVABLE_PRIVATE_ADDR (3) + class BLELocalDevice { public: - BLELocalDevice(HCITransportInterface *HCITransport); + BLELocalDevice(HCITransportInterface *HCITransport, uint8_t ownBdaddrType = STATIC_RANDOM_ADDR); virtual ~BLELocalDevice(); virtual int begin(); @@ -90,6 +95,7 @@ class BLELocalDevice { HCITransportInterface *_HCITransport; BLEAdvertisingData _advertisingData; BLEAdvertisingData _scanResponseData; + uint8_t _ownBdaddrType; }; extern BLELocalDevice& BLE; diff --git a/src/utility/ATT.cpp b/src/utility/ATT.cpp index 6ec2f27e..6c502068 100644 --- a/src/utility/ATT.cpp +++ b/src/utility/ATT.cpp @@ -109,7 +109,7 @@ ATTClass::~ATTClass() bool ATTClass::connect(uint8_t peerBdaddrType, uint8_t peerBdaddr[6]) { - if (HCI.leCreateConn(0x0060, 0x0030, 0x00, peerBdaddrType, peerBdaddr, 0x00, + if (HCI.leCreateConn(0x0060, 0x0030, 0x00, peerBdaddrType, peerBdaddr, _ownBdaddrType, 0x0006, 0x000c, 0x0000, 0x00c8, 0x0004, 0x0006) != 0) { return false; } @@ -1688,6 +1688,11 @@ void ATTClass::writeCmd(uint16_t connectionHandle, uint16_t handle, const uint8_ sendReq(connectionHandle, &writeReq, 3 + dataLen, NULL); } +void ATTClass::setOwnBdaddrType(uint8_t ownBdaddrType) +{ + _ownBdaddrType = ownBdaddrType; +} + #if !defined(FAKE_ATT) ATTClass ATTObj; ATTClass& ATT = ATTObj; diff --git a/src/utility/ATT.h b/src/utility/ATT.h index d7f54d9d..eba4a76b 100644 --- a/src/utility/ATT.h +++ b/src/utility/ATT.h @@ -77,6 +77,8 @@ class ATTClass { virtual int writeReq(uint16_t connectionHandle, uint16_t handle, const uint8_t* data, uint8_t dataLen, uint8_t responseBuffer[]); virtual void writeCmd(uint16_t connectionHandle, uint16_t handle, const uint8_t* data, uint8_t dataLen); + void setOwnBdaddrType(uint8_t ownBdaddrType); + private: virtual void error(uint16_t connectionHandle, uint8_t dlen, uint8_t data[]); virtual void mtuReq(uint16_t connectionHandle, uint8_t dlen, uint8_t data[]); @@ -135,6 +137,8 @@ class ATTClass { } _pendingResp; BLEDeviceEventHandler _eventHandlers[2]; + + uint8_t _ownBdaddrType; }; extern ATTClass& ATT; diff --git a/src/utility/GAP.cpp b/src/utility/GAP.cpp index 1a3858b2..9bdb10b1 100644 --- a/src/utility/GAP.cpp +++ b/src/utility/GAP.cpp @@ -54,7 +54,7 @@ int GAPClass::advertise(uint8_t* advData, uint8_t advDataLen, uint8_t* scanData, stopAdvertise(); - if (HCI.leSetAdvertisingParameters(_advertisingInterval, _advertisingInterval, type, 0x00, 0x00, directBdaddr, 0x07, 0) != 0) { + if (HCI.leSetAdvertisingParameters(_advertisingInterval, _advertisingInterval, type, _ownBdaddrType, 0x00, directBdaddr, 0x07, 0) != 0) { return 0; } @@ -91,8 +91,8 @@ int GAPClass::scan(bool withDuplicates) } } - // active scan, 10 ms scan interval (N * 0.625), 10 ms scan window (N * 0.625), public own address type, no filter - if (HCI.leSetScanParameters(0x01, 0x0010, 0x0010, 0x00, 0x00) != 0) { + // active scan, 10 ms scan interval (N * 0.625), 10 ms scan window (N * 0.625), public or static random own address type, no filter + if (HCI.leSetScanParameters(0x01, 0x0010, 0x0010, _ownBdaddrType, 0x00) != 0) { return false; } @@ -270,6 +270,11 @@ bool GAPClass::matchesScanFilter(const BLEDevice& device) return true; } +void GAPClass::setOwnBdaddrType(uint8_t ownBdaddrType) +{ + _ownBdaddrType = ownBdaddrType; +} + #if !defined(FAKE_GAP) GAPClass GAPObj; GAPClass& GAP = GAPObj; diff --git a/src/utility/GAP.h b/src/utility/GAP.h index f1c34b4f..c79a2aa7 100644 --- a/src/utility/GAP.h +++ b/src/utility/GAP.h @@ -45,6 +45,8 @@ class GAPClass { virtual void setEventHandler(BLEDeviceEvent event, BLEDeviceEventHandler eventHandler); + void setOwnBdaddrType(uint8_t ownBdaddrType); + protected: friend class HCIClass; @@ -67,6 +69,7 @@ class GAPClass { String _scanNameFilter; String _scanUuidFilter; String _scanAddressFilter; + uint8_t _ownBdaddrType; }; extern GAPClass& GAP; From ec6547b50aab2c353c1992e6acaa70bfa9763f27 Mon Sep 17 00:00:00 2001 From: Carlo Parata Date: Tue, 9 Feb 2021 16:34:29 +0100 Subject: [PATCH 5/5] Fix button issue on WB55 --- examples/Central/LedControl/LedControl.ino | 2 +- examples/Peripheral/ButtonLED/ButtonLED.ino | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/Central/LedControl/LedControl.ino b/examples/Central/LedControl/LedControl.ino index 225ba38b..c3ca2082 100644 --- a/examples/Central/LedControl/LedControl.ino +++ b/examples/Central/LedControl/LedControl.ino @@ -102,7 +102,7 @@ void setup() { while (!Serial); // configure the button pin as input - pinMode(buttonPin, INPUT); + pinMode(buttonPin, INPUT_PULLUP); // initialize the BLE hardware BLE.begin(); diff --git a/examples/Peripheral/ButtonLED/ButtonLED.ino b/examples/Peripheral/ButtonLED/ButtonLED.ino index 27f74649..4567aaa8 100644 --- a/examples/Peripheral/ButtonLED/ButtonLED.ino +++ b/examples/Peripheral/ButtonLED/ButtonLED.ino @@ -108,7 +108,7 @@ void setup() { while (!Serial); pinMode(ledPin, OUTPUT); // use the LED as an output - pinMode(buttonPin, INPUT); // use button pin as an input + pinMode(buttonPin, INPUT_PULLUP); // use button pin as an input // begin initialization if (!BLE.begin()) {