diff --git a/libraries/CurieBLE/src/BLEDevice.cpp b/libraries/CurieBLE/src/BLEDevice.cpp index f4713cf8..8d0a610a 100644 --- a/libraries/CurieBLE/src/BLEDevice.cpp +++ b/libraries/CurieBLE/src/BLEDevice.cpp @@ -33,38 +33,25 @@ BLEDevice::BLEDevice() _conn_param.interval_max = BT_GAP_INIT_CONN_INT_MAX; _conn_param.interval_min = BT_GAP_INIT_CONN_INT_MIN; _conn_param.latency = 0; - _conn_param.timeout = 400; + _conn_param.timeout = 500; } -/* -BLEDevice::BLEDevice(String bleaddress) -{ - BLEUtils::macAddressString2BT(bleaddress.c_str(), _bt_addr); -} - -BLEDevice::BLEDevice(const char* bleaddress) -{ - BLEUtils::macAddressString2BT(bleaddress, _bt_addr); -} - -*/ - BLEDevice::BLEDevice(const bt_addr_le_t* bleaddress): BLEDevice() { - memcpy(&_bt_addr, bleaddress, sizeof(_bt_addr)); + bt_addr_le_copy(&_bt_addr, bleaddress); BLEDeviceManager::instance()->getConnectionInterval(this, &_conn_param); } BLEDevice::BLEDevice(const BLEDevice* bledevice) { - memcpy(&_bt_addr, bledevice->bt_le_address(), sizeof(_bt_addr)); + bt_addr_le_copy(&_bt_addr, bledevice->bt_le_address()); memcpy(&_conn_param, &bledevice->_conn_param, sizeof (_conn_param)); } BLEDevice::BLEDevice(const BLEDevice& bledevice) { - memcpy(&_bt_addr, bledevice.bt_le_address(), sizeof(_bt_addr)); + bt_addr_le_copy(&_bt_addr, bledevice.bt_le_address()); memcpy(&_conn_param, &bledevice._conn_param, sizeof (_conn_param)); } @@ -117,7 +104,7 @@ String BLEDevice::address() const void BLEDevice::setAddress(const bt_addr_le_t& addr) { - memcpy(&_bt_addr, &addr, sizeof(_bt_addr)); + bt_addr_le_copy(&_bt_addr, &addr); } void BLEDevice::setAdvertisedServiceUuid(const char* advertisedServiceUuid) @@ -229,7 +216,11 @@ void BLEDevice::setDeviceName(const char* deviceName) void BLEDevice::setAppearance(unsigned short appearance) { - BLEDeviceManager::instance()->setAppearance(appearance); + if (BLEUtils::isLocalBLE(*this)) + { + // Only local device can set the appearance + BLEDeviceManager::instance()->setAppearance(appearance); + } } int BLEDevice::addService(BLEService& attribute) @@ -280,12 +271,14 @@ BLEDevice& BLEDevice::operator=(const BLEDevice& device) bool BLEDevice::operator==(const BLEDevice& device) const { - return (memcmp(this->_bt_addr.val, device._bt_addr.val, 6) == 0); + return (bt_addr_le_cmp(&this->_bt_addr, &device._bt_addr) == 0); + //return (memcmp(this->_bt_addr.a.val, device._bt_addr.a.val, 6) == 0); } bool BLEDevice::operator!=(const BLEDevice& device) const { - return (memcmp(this->_bt_addr.val, device._bt_addr.val, 6) != 0); + return (bt_addr_le_cmp(&this->_bt_addr, &device._bt_addr) != 0); + //return (memcmp(this->_bt_addr.a.val, device._bt_addr.a.val, 6) != 0); } @@ -383,9 +376,10 @@ bool BLEDevice::connect() return BLEDeviceManager::instance()->connect(*this); } -bool BLEDevice::discoverAttributes() +bool BLEDevice::discoverAttributes(bool discoverGapGatt) { - return BLEProfileManager::instance()->discoverAttributes(this); + return BLEProfileManager::instance()->discoverAllAttributes(this, + discoverGapGatt); } bool BLEDevice::discoverAttributesByService(const char* svc_uuid) diff --git a/libraries/CurieBLE/src/BLEDevice.h b/libraries/CurieBLE/src/BLEDevice.h index 23279446..9c804d2f 100644 --- a/libraries/CurieBLE/src/BLEDevice.h +++ b/libraries/CurieBLE/src/BLEDevice.h @@ -481,7 +481,7 @@ class BLEDevice int rssi() const; // returns the RSSI of the peripheral at discovery bool connect(); // connect to the peripheral - bool discoverAttributes(); // discover the peripheral's attributes + bool discoverAttributes(bool discoverGapGatt = false); // discover the peripheral's attributes bool discoverAttributesByService(const char* svc_uuid); String deviceName(); // read the device name attribute of the peripheral, and return String value @@ -665,7 +665,7 @@ class BLEDevice const void *data, uint16_t length); friend uint8_t profile_descriptor_read_rsp_process(bt_conn_t *conn, - int err, + uint8_t err, bt_gatt_read_params_t *params, const void *data, uint16_t length); diff --git a/libraries/CurieBLE/src/BLEService.h b/libraries/CurieBLE/src/BLEService.h index 3d5785f3..cb76bafd 100644 --- a/libraries/CurieBLE/src/BLEService.h +++ b/libraries/CurieBLE/src/BLEService.h @@ -125,7 +125,7 @@ class BLEService friend class BLEServiceImp; friend class BLEProfileManager; friend uint8_t profile_service_read_rsp_process(bt_conn_t *conn, - int err, + uint8_t err, bt_gatt_read_params_t *params, const void *data, uint16_t length); diff --git a/libraries/CurieBLE/src/internal/BLECallbacks.cpp b/libraries/CurieBLE/src/internal/BLECallbacks.cpp index 328c196b..760bc828 100644 --- a/libraries/CurieBLE/src/internal/BLECallbacks.cpp +++ b/libraries/CurieBLE/src/internal/BLECallbacks.cpp @@ -27,6 +27,11 @@ #include "BLEDeviceManager.h" #include "BLEProfileManager.h" +#include "BLECallbacks.h" + +#include +#include "../src/services/ble/conn_internal.h" + // GATT Server Only ssize_t profile_read_process(bt_conn_t *conn, const bt_gatt_attr_t *attr, @@ -56,26 +61,27 @@ ssize_t profile_read_process(bt_conn_t *conn, ssize_t profile_write_process(bt_conn_t *conn, const bt_gatt_attr_t *attr, const void *buf, uint16_t len, - uint16_t offset) + uint16_t offset, uint8_t flags) { pr_info(LOG_MODULE_BLE, "%s1", __FUNCTION__); BLEAttribute *bleattr = (BLEAttribute *)attr->user_data; BLECharacteristicImp* blecharacteritic; BLEAttributeType type = bleattr->type(); - if ((BLETypeCharacteristic != type) || 0 != offset) + if (BLETypeCharacteristic != type) { return 0; } blecharacteritic = (BLECharacteristicImp*)bleattr; - blecharacteritic->setValue((const uint8_t *) buf, len); + blecharacteritic->setValue((const uint8_t *) buf, len, offset); return len; } +#ifdef TD_V3 ssize_t profile_longwrite_process(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, uint16_t len, - uint16_t offset) + uint16_t offset, uint8_t flags) { BLEAttribute *bleattr = (BLEAttribute *)attr->user_data; BLEAttributeType type = bleattr->type(); @@ -116,21 +122,18 @@ int profile_longflush_process(struct bt_conn *conn, return -EINVAL; } - +#endif // GATT client only uint8_t profile_notify_process (bt_conn_t *conn, bt_gatt_subscribe_params_t *params, const void *data, uint16_t length) { - //BLEPeripheralHelper* peripheral = BLECentralRole::instance()->peripheral(conn);// Find peripheral by bt_conn - //BLEAttribute* notifyatt = peripheral->attribute(params); // Find attribute by params BLECharacteristicImp* chrc = NULL; BLEDevice bleDevice(bt_conn_get_dst(conn)); chrc = BLEProfileManager::instance()->characteristic(bleDevice, params->value_handle); - //assert(notifyatt->type() == BLETypeCharacteristic); - pr_debug(LOG_MODULE_APP, "%s1", __FUNCTION__); + pr_debug(LOG_MODULE_APP, "%s-%d", __FUNCTION__, __LINE__); if (NULL != chrc) { chrc->setValue((const unsigned char *)data, length); @@ -146,24 +149,20 @@ uint8_t profile_discover_process(bt_conn_t *conn, uint8_t ret = BT_GATT_ITER_STOP; pr_debug(LOG_MODULE_BLE, "%s-%d", __FUNCTION__, __LINE__); ret = BLEProfileManager::instance()->discoverResponseProc(conn, attr, params); - pr_debug(LOG_MODULE_BLE, "%s-%d", __FUNCTION__, __LINE__); return ret; } // GATT Client only uint8_t profile_read_rsp_process(bt_conn_t *conn, - int err, + uint8_t err, bt_gatt_read_params_t *params, const void *data, uint16_t length) { - if (NULL == data && 0 != length) - { - return BT_GATT_ITER_STOP; - } BLECharacteristicImp *chrc = NULL; BLEDevice bleDevice(bt_conn_get_dst(conn)); + pr_debug(LOG_MODULE_BLE, "%s-%d", __FUNCTION__, __LINE__); // Get characteristic by handle params->single.handle chrc = BLEProfileManager::instance()->characteristic(bleDevice, params->single.handle); @@ -174,7 +173,7 @@ uint8_t profile_read_rsp_process(bt_conn_t *conn, } uint8_t profile_descriptor_read_rsp_process(bt_conn_t *conn, - int err, + uint8_t err, bt_gatt_read_params_t *params, const void *data, uint16_t length) @@ -186,20 +185,19 @@ uint8_t profile_descriptor_read_rsp_process(bt_conn_t *conn, BLEDescriptorImp *descriptor = NULL; BLEDevice bleDevice(bt_conn_get_dst(conn)); + pr_debug(LOG_MODULE_BLE, "%s-%d", __FUNCTION__, __LINE__); // Get characteristic by handle params->single.handle descriptor = BLEProfileManager::instance()->descriptor(bleDevice, params->single.handle); - //pr_debug(LOG_MODULE_BLE, "%s-%d", __FUNCTION__, __LINE__); if (descriptor) { descriptor->writeValue((const unsigned char *)data, length, params->single.offset); } - //pr_debug(LOG_MODULE_BLE, "%s-%d: desc len-%d", __FUNCTION__, __LINE__, descriptor->valueLength()); return BT_GATT_ITER_STOP; } uint8_t profile_service_read_rsp_process(bt_conn_t *conn, - int err, + uint8_t err, bt_gatt_read_params_t *params, const void *data, uint16_t length) @@ -210,7 +208,7 @@ uint8_t profile_service_read_rsp_process(bt_conn_t *conn, } uint8_t profile_characteristic_read_rsp_process(bt_conn_t *conn, - int err, + uint8_t err, bt_gatt_read_params_t *params, const void *data, uint16_t length) @@ -237,7 +235,6 @@ void bleConnectEventHandler(bt_conn_t *conn, p->handleConnectEvent(conn, err); } - void bleDisconnectEventHandler(bt_conn_t *conn, uint8_t reason, void *param) @@ -268,13 +265,14 @@ void ble_central_device_found(const bt_addr_le_t *addr, uint8_t len) { //char dev[BT_ADDR_LE_STR_LEN]; - //bt_addr_le_to_str(addr, dev, sizeof(dev)); //pr_debug(LOG_MODULE_BLE, "[DEVICE]: %s, AD evt type %u, AD data len %u, RSSI %i\n", // dev, type, len, rssi); + //pr_debug(LOG_MODULE_BLE, " AD evt type %u, AD data len %u, RSSI %i\n", + // type, len, rssi); BLEDeviceManager::instance()->handleDeviceFound(addr, rssi, type, - ad, len); + ad, len); } void ble_on_write_no_rsp_complete(struct bt_conn *conn, uint8_t err, @@ -283,3 +281,14 @@ void ble_on_write_no_rsp_complete(struct bt_conn *conn, uint8_t err, BLECharacteristicImp::writeResponseReceived(conn, err, data); } +void prfile_cccd_cfg_changed(void *user_data, uint16_t value) +{ + if (NULL == user_data) + return; + pr_debug(LOG_MODULE_BLE, "%s-%d: ccc userdata %p", __FUNCTION__, __LINE__, user_data); + + BLECharacteristicImp *blecharacteritic = (BLECharacteristicImp *)user_data; + blecharacteritic->cccdValueChanged(); +} + + diff --git a/libraries/CurieBLE/src/internal/BLECallbacks.h b/libraries/CurieBLE/src/internal/BLECallbacks.h index deffe92a..3925dbd3 100644 --- a/libraries/CurieBLE/src/internal/BLECallbacks.h +++ b/libraries/CurieBLE/src/internal/BLECallbacks.h @@ -24,13 +24,14 @@ uint8_t profile_notify_process (bt_conn_t *conn, bt_gatt_subscribe_params_t *params, const void *data, uint16_t length); -uint8_t profile_read_rsp_process(bt_conn_t *conn, int err, +uint8_t profile_read_rsp_process(bt_conn_t *conn, + uint8_t err, bt_gatt_read_params_t *params, const void *data, uint16_t length); uint8_t profile_descriptor_read_rsp_process(bt_conn_t *conn, - int err, + uint8_t err, bt_gatt_read_params_t *params, const void *data, uint16_t length); @@ -41,11 +42,13 @@ int profile_longflush_process(struct bt_conn *conn, ssize_t profile_longwrite_process(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, uint16_t len, - uint16_t offset); + uint16_t offset, + uint8_t flags); ssize_t profile_write_process(bt_conn_t *conn, const bt_gatt_attr_t *attr, const void *buf, uint16_t len, - uint16_t offset); + uint16_t offset, + uint8_t flags); ssize_t profile_read_process(bt_conn_t *conn, const bt_gatt_attr_t *attr, void *buf, uint16_t len, @@ -76,7 +79,7 @@ void ble_central_device_found(const bt_addr_le_t *addr, uint8_t len); uint8_t profile_service_read_rsp_process(bt_conn_t *conn, - int err, + uint8_t err, bt_gatt_read_params_t *params, const void *data, uint16_t length); @@ -84,10 +87,12 @@ uint8_t profile_service_read_rsp_process(bt_conn_t *conn, void ble_on_write_no_rsp_complete(struct bt_conn *conn, uint8_t err, const void *data); uint8_t profile_characteristic_read_rsp_process(bt_conn_t *conn, - int err, + uint8_t err, bt_gatt_read_params_t *params, const void *data, uint16_t length); +void prfile_cccd_cfg_changed(void *user_data, uint16_t value); + #endif diff --git a/libraries/CurieBLE/src/internal/BLECharacteristicImp.cpp b/libraries/CurieBLE/src/internal/BLECharacteristicImp.cpp index a7098e96..38730a0e 100644 --- a/libraries/CurieBLE/src/internal/BLECharacteristicImp.cpp +++ b/libraries/CurieBLE/src/internal/BLECharacteristicImp.cpp @@ -28,49 +28,22 @@ bt_uuid_16_t BLECharacteristicImp::_gatt_chrc_uuid = {BT_UUID_TYPE_16, BT_UUID_GATT_CHRC_VAL}; bt_uuid_16_t BLECharacteristicImp::_gatt_ccc_uuid = {BT_UUID_TYPE_16, BT_UUID_GATT_CCC_VAL}; volatile bool BLECharacteristicImp::_gattc_writing = false; +volatile bool BLECharacteristicImp::_gattc_write_result = false; -BLECharacteristicImp::BLECharacteristicImp(const bt_uuid_t* uuid, - unsigned char properties, - uint16_t handle, - const BLEDevice& bledevice): - BLEAttribute(uuid, BLETypeCharacteristic), - _value_length(0), - _value_buffer(NULL), - _value_updated(false), - _value_handle(handle), - _cccd_handle(0), - _attr_chrc_value(NULL), - _attr_cccd(NULL), - _subscribed(false), - _reading(false), - _ble_device() +void BLECharacteristicImp::initProfileParameter(unsigned char properties) { - _value_size = BLE_MAX_ATTR_DATA_LEN;// Set as MAX value. TODO: long read/write need to twist - _value = (unsigned char*)malloc(_value_size); - - // TODO: Enable when max value is not set. - // if (_value_size > BLE_MAX_ATTR_DATA_LEN) - // { - // _value_buffer = (unsigned char*)malloc(_value_size); - // } - - if (_value) - { - memset(_value, 0, _value_size); - } - else - { - errno = ENOMEM; - } - - memset(&_ccc_cfg, 0, sizeof(_ccc_cfg)); - memset(&_ccc_value, 0, sizeof(_ccc_value)); - memset(&_gatt_chrc, 0, sizeof(_gatt_chrc)); - memset(&_sub_params, 0, sizeof(_sub_params)); memset(&_discover_params, 0, sizeof(_discover_params)); + memset(&_ccc_cfg, 0, sizeof(_ccc_cfg)); + //memset(&_ccc_value, 0, sizeof(_ccc_value)); _ccc_value.cfg = &_ccc_cfg; _ccc_value.cfg_len = 1; + _ccc_value.user_data = (void *)this; + _ccc_value.cfg_changed = prfile_cccd_cfg_changed; + _ccc_value.value = 0; + + memset(&_gatt_chrc, 0, sizeof(_gatt_chrc)); + memset(&_sub_params, 0, sizeof(_sub_params)); if (BLERead & properties) { _gatt_chrc.properties |= BT_GATT_CHRC_READ; @@ -93,92 +66,113 @@ BLECharacteristicImp::BLECharacteristicImp(const bt_uuid_t* uuid, _gatt_chrc.properties |= BT_GATT_CHRC_INDICATE; _sub_params.value |= BT_GATT_CCC_INDICATE; } - _gatt_chrc.uuid = (bt_uuid_t*)this->bt_uuid();//&_characteristic_uuid;//this->uuid(); - memset(_event_handlers, 0, sizeof(_event_handlers)); - memset(_oldevent_handlers, 0, sizeof(_oldevent_handlers)); - + _gatt_chrc.uuid = (bt_uuid_t*)this->bt_uuid(); _sub_params.notify = profile_notify_process; - - // Update BLE device object - _ble_device.setAddress(*bledevice.bt_le_address()); - - memset(&_descriptors_header, 0, sizeof(_descriptors_header)); } -BLECharacteristicImp::BLECharacteristicImp(BLECharacteristic& characteristic, - const BLEDevice& bledevice): - BLEAttribute(characteristic.uuid(), BLETypeCharacteristic), - _value_length(0), - _value_buffer(NULL), - _value_updated(false), - _value_handle(0), - _cccd_handle(0), - _attr_chrc_value(NULL), - _attr_cccd(NULL), - _subscribed(false), - _reading(false), - _ble_device() +void BLECharacteristicImp::initVauleFromCharacteristic(const BLECharacteristic& characteristic) { - unsigned char properties = characteristic._properties; _value_size = characteristic._value_size; _value = (unsigned char*)malloc(_value_size); if (_value == NULL) { + _value_size = 0; errno = ENOMEM; } - if (_value_size > BLE_MAX_ATTR_DATA_LEN) + else { - _value_buffer = (unsigned char*)malloc(_value_size); + memset(_value, 0, _value_size); } - memset(&_ccc_cfg, 0, sizeof(_ccc_cfg)); - memset(&_ccc_value, 0, sizeof(_ccc_value)); - memset(&_gatt_chrc, 0, sizeof(_gatt_chrc)); - memset(&_sub_params, 0, sizeof(_sub_params)); - memset(&_discover_params, 0, sizeof(_discover_params)); - - _ccc_value.cfg = &_ccc_cfg; - _ccc_value.cfg_len = 1; - if (BLERead & properties) - { - _gatt_chrc.properties |= BT_GATT_CHRC_READ; - } - if (BLEWrite & properties) - { - _gatt_chrc.properties |= BT_GATT_CHRC_WRITE; - } - if (BLEWriteWithoutResponse & properties) - { - _gatt_chrc.properties |= BT_GATT_CHRC_WRITE_WITHOUT_RESP; - } - if (BLENotify & properties) - { - _gatt_chrc.properties |= BT_GATT_CHRC_NOTIFY; - _sub_params.value |= BT_GATT_CCC_NOTIFY; - } - if (BLEIndicate & properties) +#ifdef TD_V3 + // For long characteristic + if (_value_size > BLE_MAX_ATTR_DATA_LEN) { - _gatt_chrc.properties |= BT_GATT_CHRC_INDICATE; - _sub_params.value |= BT_GATT_CCC_INDICATE; + _value_buffer = (unsigned char*)malloc(_value_size); + if (_value_buffer == NULL) + { + pr_info(LOG_MODULE_BLE, "%s-%d", __FUNCTION__, __LINE__); + errno = ENOMEM; + } + else + { + memset(_value_buffer, 0, _value_size); + } + + pr_info(LOG_MODULE_BLE, "%s-%d: Length-%p, %d", + __FUNCTION__, __LINE__, _value_buffer, _value_size); } - _gatt_chrc.uuid = (bt_uuid_t*)this->bt_uuid();//&_characteristic_uuid;//this->uuid(); - +#endif + // GL. KW warning acknowldged memcpy(_event_handlers, characteristic._event_handlers, sizeof(_event_handlers)); memcpy(_oldevent_handlers, characteristic._oldevent_handlers, sizeof(_oldevent_handlers)); - _sub_params.notify = profile_notify_process; - - if (NULL != characteristic._value) + if (NULL != characteristic._value && NULL != _value) { - memcpy(_value, characteristic._value, _value_size); + memcpy(_value, characteristic._value, _value_size);// GL. KW warning acknowldged _value_length = _value_size; } - - // Update BLE device object - _ble_device.setAddress(*bledevice.bt_le_address()); +} + +void BLECharacteristicImp::resetEventHanler() +{ + memset(_event_handlers, 0, sizeof(_event_handlers)); + memset(_oldevent_handlers, 0, sizeof(_oldevent_handlers)); +} + +void BLECharacteristicImp::resetDescriptorList() +{ + memset(&_descriptors_header, 0, sizeof(_descriptors_header)); +} + + +BLECharacteristicImp::BLECharacteristicImp(const bt_uuid_t* uuid, + unsigned char properties, + uint16_t handle, + const BLEDevice& bledevice): + BLEAttribute(uuid, BLETypeCharacteristic), + _value_size(0), + _value_length(0), + _value(NULL), +#ifdef TD_V3 + _value_buffer(NULL), +#endif + _value_updated(false), + _value_handle(handle), + _cccd_handle(0), + _attr_chrc_value(NULL), + _attr_cccd(NULL), + _subscribed(false), + _reading(false), + _ble_device(bledevice) +{ + resetEventHanler(); + resetDescriptorList(); + initProfileParameter(properties); +} + +BLECharacteristicImp::BLECharacteristicImp(BLECharacteristic& characteristic, + const BLEDevice& bledevice): + BLEAttribute(characteristic.uuid(), BLETypeCharacteristic), + _value_length(0), +#ifdef TD_V3 + _value_buffer(NULL), +#endif + _value_updated(false), + _value_handle(0), + _cccd_handle(0), + _attr_chrc_value(NULL), + _attr_cccd(NULL), + _subscribed(false), + _reading(false), + _ble_device(bledevice) +{ + resetEventHanler(); + resetDescriptorList(); + initProfileParameter(characteristic._properties); + initVauleFromCharacteristic(characteristic); characteristic.setBLECharacteristicImp(this); - memset(&_descriptors_header, 0, sizeof(_descriptors_header)); } BLECharacteristicImp::~BLECharacteristicImp() @@ -190,11 +184,13 @@ BLECharacteristicImp::~BLECharacteristicImp() _value = (unsigned char *)NULL; } +#ifdef TD_V3 if (_value_buffer) { free(_value_buffer); _value_buffer = (unsigned char *)NULL; } +#endif } unsigned char @@ -205,34 +201,11 @@ BLECharacteristicImp::properties() const bool BLECharacteristicImp::writeValue(const byte value[], int length) { - int status; - bool retVal = false; - - _setValue(value, length, 0); - - // Address same is GATT server. Send notification if CCCD enabled - // Different is GATT client. Send write request - if (true == BLEUtils::isLocalBLE(_ble_device) && - NULL != _attr_chrc_value) - { - // Notify for peripheral. - status = bt_gatt_notify(NULL, _attr_chrc_value, value, length, NULL); - // Sid. KW found status is always 0 - // if (!status) - // { - retVal = true; - // } - } - - //Not schedule write request for central - // The write request may failed. - // If user want to get latest set value. Call read and get the real value - return retVal; + return writeValue(value, length, 0); } bool BLECharacteristicImp::writeValue(const byte value[], int length, int offset) { - int status; bool retVal = false; _setValue(value, length, offset); @@ -243,12 +216,8 @@ bool BLECharacteristicImp::writeValue(const byte value[], int length, int offset NULL != _attr_chrc_value) { // Notify for peripheral. - status = bt_gatt_notify(NULL, _attr_chrc_value, value, length, NULL); - // Sid. KW found status is always 0. - // if (!status) - // { - retVal = true; - // } + bt_gatt_notify(NULL, _attr_chrc_value, value, length, NULL); + retVal = true; } //Not schedule write request for central @@ -257,53 +226,88 @@ bool BLECharacteristicImp::writeValue(const byte value[], int length, int offset return retVal; } -bool -BLECharacteristicImp::setValue(const unsigned char value[], uint16_t length) +void BLECharacteristicImp::triggerValueUpdatedEvent() { - _setValue(value, length, 0); - _value_updated = true; if (BLEUtils::isLocalBLE(_ble_device) == true) { // GATT server // Write request for GATT server - if (_event_handlers[BLEWritten]) + if (_value_updated) { - BLECharacteristic chrcTmp(this, &_ble_device); - _event_handlers[BLEWritten](_ble_device, chrcTmp); + if (_event_handlers[BLEWritten]) + { + BLECharacteristic chrcTmp(this, &_ble_device); + _event_handlers[BLEWritten](_ble_device, chrcTmp); + } + + if (_oldevent_handlers[BLEWritten]) + { + BLECharacteristic chrcTmp(this, &_ble_device); + BLECentral central(_ble_device); + _oldevent_handlers[BLEWritten](central, chrcTmp); + } } - - if (_oldevent_handlers[BLEWritten]) + } + else + { + if (_value_updated) { - BLECharacteristic chrcTmp(this, &_ble_device); - BLECentral central(_ble_device); - _oldevent_handlers[BLEWritten](central, chrcTmp); + if (_event_handlers[BLEValueUpdated]) + { + BLECharacteristic chrcTmp(this, &_ble_device); + _event_handlers[BLEValueUpdated](_ble_device, chrcTmp); + } + + if (_oldevent_handlers[BLEValueUpdated]) + { + BLECharacteristic chrcTmp(this, &_ble_device); + BLECentral central(_ble_device); + _oldevent_handlers[BLEValueUpdated](central, chrcTmp); + } } } +} + +bool +BLECharacteristicImp::setValue (const unsigned char value[], + uint16_t length) +{ + return setValue(value, length, 0); +} + +bool +BLECharacteristicImp::setValue (const unsigned char value[], + uint16_t length, + uint16_t offset) +{ + bool read_process_result = true; + + pr_debug(LOG_MODULE_BLE, "%s-%d:Length-%p, %d", + __FUNCTION__, __LINE__, value, length); + + if (NULL != value && length != 0) + { + _setValue(value, length, offset); + _value_updated = true; + } else + { + read_process_result = false; + } + + if (BLEUtils::isLocalBLE(_ble_device) == false) { // GATT client // Discovered attribute - // Read response/Notification/Indication for GATT client if (_reading) { // Read response received. Not block the other reading. _reading = false; - } - - if (_event_handlers[BLEValueUpdated]) - { - BLECharacteristic chrcTmp(this, &_ble_device); - _event_handlers[BLEValueUpdated](_ble_device, chrcTmp); - } - - if (_oldevent_handlers[BLEValueUpdated]) - { - BLECharacteristic chrcTmp(this, &_ble_device); - BLECentral central(_ble_device); - _oldevent_handlers[BLEValueUpdated](central, chrcTmp); + _gattc_read_result = read_process_result; } } + triggerValueUpdatedEvent(); return true; } @@ -561,8 +565,25 @@ BLEDescriptorImp* BLECharacteristicImp::descriptor(uint16_t handle) void BLECharacteristicImp::_setValue(const uint8_t value[], uint16_t length, uint16_t offset) { + if (NULL == _value) + { + _value_size = length + offset; + // The discover didn't create the buffer + _value = (unsigned char*)malloc(_value_size); + if (_value) + { + memset(_value, 0, _value_size); + } + else + { + _value_size = 0; + errno = ENOMEM; + } + } + if (length + offset > _value_size) { + // Out of range. Cut the data if (_value_size > offset) { uint16_t temp_len = _value_size - offset; @@ -577,8 +598,8 @@ BLECharacteristicImp::_setValue(const uint8_t value[], uint16_t length, uint16_t } } - memcpy(_value + offset, value, length); - _value_length = length; + memcpy(_value + offset, value, length);// GL. KW warning acknowldged + _value_length = length + offset; } _bt_gatt_ccc_t* BLECharacteristicImp::getCccCfg(void) @@ -601,6 +622,11 @@ uint8_t BLECharacteristicImp::getPermission(void) if (_gatt_chrc.properties & (BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP)) { perm |= BT_GATT_PERM_WRITE; + // Long write support for GATT server + if (_value_size > BLE_MAX_ATTR_DATA_LEN) + { + perm |= BT_GATT_PERM_PREPARE_WRITE; + } } return perm; } @@ -650,12 +676,13 @@ bool BLECharacteristicImp::read(bool blocked) return false; } + _reading = true; // Send read request retval = bt_gatt_read(conn, &_read_params); if (0 == retval) { - _reading = true; ret_bool = true; + _gattc_read_result = false; // Block the call if (blocked == true) @@ -665,8 +692,17 @@ bool BLECharacteristicImp::read(bool blocked) delay(5); ret_bool = _ble_device.connected(); } + if (ret_bool) + { + ret_bool = _gattc_read_result; + } } } + else + { + // Read request failed + _reading = false; + } bt_conn_unref(conn); return ret_bool; } @@ -676,12 +712,14 @@ void BLECharacteristicImp::writeResponseReceived(struct bt_conn *conn, const void *data) { _gattc_writing = false; + _gattc_write_result = (err == 0); } bool BLECharacteristicImp::write(const unsigned char value[], uint16_t length) { int retval = 0; + bool write_process_result = true; bt_conn_t* conn = NULL; if (true == BLEUtils::isLocalBLE(_ble_device) || true == _gattc_writing) @@ -699,18 +737,30 @@ bool BLECharacteristicImp::write(const unsigned char value[], // Send write request if (_gatt_chrc.properties & BT_GATT_CHRC_WRITE) { + struct bt_gatt_write_params params; + params.data = value; + params.length = length; + params.func = ble_on_write_no_rsp_complete; + params.handle = _value_handle; + params.offset = 0; + _gattc_writing = true; - retval = bt_gatt_write(conn, - _value_handle, - 0, - value, - length, - ble_on_write_no_rsp_complete); - while (_gattc_writing) + _gattc_write_result = false; + + retval = bt_gatt_write(conn, ¶ms); + if (0 == retval) { - delay(2); + bool connected = true; + // Wait for write response + while (_gattc_writing && connected) + { + delay(2); + connected = _ble_device.connected(); + } + write_process_result = _gattc_write_result; } - } else if (_gatt_chrc.properties & BT_GATT_CHRC_WRITE_WITHOUT_RESP) + } + else if (_gatt_chrc.properties & BT_GATT_CHRC_WRITE_WITHOUT_RESP) { retval = bt_gatt_write_without_response(conn, _value_handle, @@ -719,9 +769,10 @@ bool BLECharacteristicImp::write(const unsigned char value[], false); } bt_conn_unref(conn); - return (0 == retval); + return (0 == retval) && write_process_result; } +#ifdef TD_V3 void BLECharacteristicImp::setBuffer(const uint8_t value[], uint16_t length, uint16_t offset) @@ -732,7 +783,7 @@ void BLECharacteristicImp::setBuffer(const uint8_t value[], return; } - memcpy(_value_buffer + offset, value, length); + memcpy(_value_buffer + offset, value, length); // GL. KW warning acknowldged } void BLECharacteristicImp::syncupBuffer2Value() @@ -743,8 +794,9 @@ void BLECharacteristicImp::syncupBuffer2Value() void BLECharacteristicImp::discardBuffer() { if(_value_buffer) - memcpy(_value_buffer, _value, _value_size); + memcpy(_value_buffer, _value, _value_size); // GL. KW warning acknowldged } +#endif bool BLECharacteristicImp::longCharacteristic() { @@ -784,9 +836,13 @@ int BLECharacteristicImp::updateProfile(bt_gatt_attr_t *attr_start, int& index) } else { +#ifdef TD_V3 // Long characteristic. MAX. 512 start->write = profile_longwrite_process; start->flush = profile_longflush_process; +#else + start->write = profile_write_process; +#endif } _attr_chrc_value = start; pr_debug(LOG_MODULE_BLE, "chrcdescripor-%p, chimp-%p type-%d", start, this, this->type()); @@ -800,7 +856,7 @@ int BLECharacteristicImp::updateProfile(bt_gatt_attr_t *attr_start, int& index) // Descriptor memset(start, 0, sizeof(bt_gatt_attr_t)); start->uuid = this->getClientCharacteristicConfigUuid(); - start->perm = BT_GATT_PERM_READ | BT_GATT_PERM_WRITE; + start->perm = BT_GATT_PERM_READ | BT_GATT_PERM_WRITE; // Fixed start->read = bt_gatt_attr_read_ccc; start->write = bt_gatt_attr_write_ccc; start->user_data = this->getCccCfg(); @@ -821,7 +877,7 @@ int BLECharacteristicImp::updateProfile(bt_gatt_attr_t *attr_start, int& index) counter += offset; node = node->next; } - pr_debug(LOG_MODULE_BLE, "%s:type-%d", __FUNCTION__, this->type()); + //pr_debug(LOG_MODULE_BLE, "%s:type-%d", __FUNCTION__, this->type()); return counter; } @@ -834,13 +890,13 @@ int BLECharacteristicImp::addDescriptor(BLEDescriptor& descriptor) } descriptorImp = new BLEDescriptorImp(_ble_device, descriptor); - pr_debug(LOG_MODULE_BLE, "%s-%d",__FUNCTION__, __LINE__); + //pr_debug(LOG_MODULE_BLE, "%s-%d- length %d",__FUNCTION__, __LINE__, descriptor.valueLength()); if (NULL == descriptorImp) { return BLE_STATUS_NO_MEMORY; } - pr_debug(LOG_MODULE_BLE, "%s-%d",__FUNCTION__, __LINE__); + //pr_debug(LOG_MODULE_BLE, "%s-%d",__FUNCTION__, __LINE__); BLEDescriptorNodePtr node = link_node_create(descriptorImp); if (NULL == node) { @@ -848,7 +904,7 @@ int BLECharacteristicImp::addDescriptor(BLEDescriptor& descriptor) return BLE_STATUS_NO_MEMORY; } link_node_insert_last(&_descriptors_header, node); - pr_debug(LOG_MODULE_BLE, "%s-%d",__FUNCTION__, __LINE__); + //pr_debug(LOG_MODULE_BLE, "%s-%d",__FUNCTION__, __LINE__); return BLE_STATUS_SUCCESS; } @@ -863,7 +919,7 @@ int BLECharacteristicImp::addDescriptor(const bt_uuid_t* uuid, } descriptorImp = new BLEDescriptorImp(uuid, property, handle, _ble_device); - pr_debug(LOG_MODULE_BLE, "%s-%d",__FUNCTION__, __LINE__); + //pr_debug(LOG_MODULE_BLE, "%s-%d",__FUNCTION__, __LINE__); if (NULL == descriptorImp) { return BLE_STATUS_NO_MEMORY; @@ -876,7 +932,6 @@ int BLECharacteristicImp::addDescriptor(const bt_uuid_t* uuid, return BLE_STATUS_NO_MEMORY; } link_node_insert_last(&_descriptors_header, node); - pr_debug(LOG_MODULE_BLE, "%s-%d",__FUNCTION__, __LINE__); return BLE_STATUS_SUCCESS; } @@ -959,23 +1014,10 @@ int BLECharacteristicImp::descriptorCount() const bool BLECharacteristicImp::discoverAttributes(BLEDevice* device) { - int err; bt_conn_t* conn; bt_gatt_discover_params_t* temp = NULL; - const bt_uuid_t* service_uuid = bt_uuid(); - if (service_uuid->type == BT_UUID_TYPE_16) - { - uint16_t uuid_tmp ;//= ((bt_uuid_16_t*)service_uuid)->val; - memcpy(&uuid_tmp, &((bt_uuid_16_t*)service_uuid)->val, sizeof(uuid_tmp)); - if (BT_UUID_GAP_VAL == uuid_tmp || - BT_UUID_GATT_VAL == uuid_tmp) - { - return false; - } - } - conn = bt_conn_lookup_addr_le(device->bt_le_address()); if (NULL == conn) { @@ -989,7 +1031,6 @@ bool BLECharacteristicImp::discoverAttributes(BLEDevice* device) temp->uuid = NULL; temp->type = BT_GATT_DISCOVER_DESCRIPTOR; temp->func = profile_discover_process; - pr_debug(LOG_MODULE_BLE, "%s-%d-charc",__FUNCTION__, __LINE__); err = bt_gatt_discover(conn, temp); bt_conn_unref(conn); if (err) @@ -1034,7 +1075,6 @@ uint8_t BLECharacteristicImp::discoverResponseProc(bt_conn_t *conn, retVal = BT_GATT_ITER_CONTINUE; const bt_uuid_t* desc_uuid = attr->uuid; uint16_t desc_handle = attr->handle; - pr_debug(LOG_MODULE_BLE, "%s-%d:handle-%d:%d", __FUNCTION__, __LINE__,attr->handle, desc_handle); if (isClientCharacteristicConfigurationDescriptor(desc_uuid)) { setCCCDHandle(desc_handle); @@ -1070,4 +1110,25 @@ uint8_t BLECharacteristicImp::discoverResponseProc(bt_conn_t *conn, return retVal; } +void BLECharacteristicImp::cccdValueChanged() +{ + enum BLECharacteristicEvent event = BLEUnsubscribed; + if (subscribed()) + { + event = BLESubscribed; + } + + if (_event_handlers[event]) + { + BLECharacteristic chrcTmp(this, &_ble_device); + _event_handlers[event](_ble_device, chrcTmp); + } + + if (_oldevent_handlers[event]) + { + BLECharacteristic chrcTmp(this, &_ble_device); + BLECentral central(_ble_device); + _oldevent_handlers[event](central, chrcTmp); + } +} diff --git a/libraries/CurieBLE/src/internal/BLECharacteristicImp.h b/libraries/CurieBLE/src/internal/BLECharacteristicImp.h index af5e9839..892c4aab 100644 --- a/libraries/CurieBLE/src/internal/BLECharacteristicImp.h +++ b/libraries/CurieBLE/src/internal/BLECharacteristicImp.h @@ -20,11 +20,6 @@ #ifndef _BLE_CHARACTERISTICIMP_H_INCLUDED #define _BLE_CHARACTERISTICIMP_H_INCLUDED -//#include "BLECommon.h" - -//#include "BLEDevice.h" -//#include "BLEDescriptor.h" - #include "CurieBLE.h" #include "BLEDescriptorImp.h" @@ -83,6 +78,9 @@ class BLECharacteristicImp: public BLEAttribute{ * @return bool true set value success, false on error */ bool setValue(const unsigned char value[], unsigned short length); + bool setValue (const unsigned char value[], + uint16_t length, + uint16_t offset); /** * Get the property mask of the Characteristic @@ -172,7 +170,7 @@ class BLECharacteristicImp: public BLEAttribute{ static void writeResponseReceived(struct bt_conn *conn, uint8_t err, const void *data); - + void cccdValueChanged(); int descriptorCount() const; uint8_t discoverResponseProc(bt_conn_t *conn, const bt_gatt_attr_t *attr, @@ -208,7 +206,8 @@ class BLECharacteristicImp: public BLEAttribute{ friend ssize_t profile_longwrite_process(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, uint16_t len, - uint16_t offset); + uint16_t offset, + uint8_t flags); int updateProfile(bt_gatt_attr_t *attr_start, int& index); @@ -216,11 +215,13 @@ class BLECharacteristicImp: public BLEAttribute{ bool longCharacteristic(); +#ifdef TD_V3 void setBuffer(const uint8_t value[], uint16_t length, uint16_t offset); void discardBuffer(); void syncupBuffer2Value(); +#endif /** * @brief Get the characteristic value handle @@ -299,11 +300,17 @@ class BLECharacteristicImp: public BLEAttribute{ private: + void resetEventHanler(); + void resetDescriptorList(); + void initProfileParameter(unsigned char properties); + void initVauleFromCharacteristic(const BLECharacteristic& characteristic); + void setCCCDHandle(uint16_t handle); void setHandle(uint16_t handle); void _setValue(const uint8_t value[], uint16_t length, uint16_t offset); bool isClientCharacteristicConfigurationDescriptor(const bt_uuid_t* uuid); - + void triggerValueUpdatedEvent(); + private: // Those 2 UUIDs are used for define the characteristic. static bt_uuid_16_t _gatt_chrc_uuid; // Characteristic UUID @@ -312,7 +319,9 @@ class BLECharacteristicImp: public BLEAttribute{ unsigned short _value_size; unsigned short _value_length; unsigned char* _value; +#ifdef TD_V3 unsigned char* _value_buffer; +#endif bool _value_updated; uint16_t _value_handle; // GATT client only @@ -331,7 +340,10 @@ class BLECharacteristicImp: public BLEAttribute{ bool _subscribed; volatile bool _reading; + volatile bool _gattc_read_result; + static volatile bool _gattc_writing; + static volatile bool _gattc_write_result; bt_gatt_read_params_t _read_params; // GATT read parameter typedef LinkNode BLEDescriptorLinkNodeHeader; diff --git a/libraries/CurieBLE/src/internal/BLEDeviceManager.cpp b/libraries/CurieBLE/src/internal/BLEDeviceManager.cpp index d5ddd181..1c495034 100644 --- a/libraries/CurieBLE/src/internal/BLEDeviceManager.cpp +++ b/libraries/CurieBLE/src/internal/BLEDeviceManager.cpp @@ -45,7 +45,6 @@ BLEDeviceManager::BLEDeviceManager(): _connecting(false), _has_service_uuid(false), _has_service_solicit_uuid(false), - _appearance(0), _manufacturer_data_length(0), _service_data_length(0), _adv_type(0), @@ -66,8 +65,7 @@ BLEDeviceManager::BLEDeviceManager(): ble_client_get_factory_config(&_local_bda, _device_name); - _adv_param.type = BT_LE_ADV_IND; - _adv_param.addr_type = _local_bda.type; + setConnectable(true); _adv_param.interval_min = 0xA0; _adv_param.interval_max = 0xF0; @@ -81,7 +79,7 @@ BLEDeviceManager::BLEDeviceManager(): memset(_peer_adv_data, 0, sizeof(_peer_adv_data)); memset(_peer_adv_data_len, 0, sizeof(_peer_adv_data_len)); memset(_peer_scan_rsp_data, 0, sizeof(_peer_scan_rsp_data)); - memset(_peer_scan_rsp_data_len, -1, sizeof(_peer_scan_rsp_data_len)); + memset(_peer_scan_rsp_data_len, 0, sizeof(_peer_scan_rsp_data_len)); memset(_peer_adv_rssi, 0, sizeof(_peer_adv_rssi)); memset(_peer_adv_connectable, 0, sizeof(_peer_adv_connectable)); @@ -132,6 +130,11 @@ bool BLEDeviceManager::begin(BLEDevice *device) { if (NULL == _local_ble) { + // TODO: Olny allow call one time + ble_client_init (bleConnectEventHandler, this, + bleDisconnectEventHandler, this, + bleParamUpdatedEventHandler, this); + _local_ble = device; bt_le_set_mac_address(_local_bda); @@ -139,10 +142,6 @@ bool BLEDeviceManager::begin(BLEDevice *device) setDeviceName(); _state = BLE_PERIPH_STATE_READY; delay(4); - // TODO: Olny allow call one time - ble_client_init (bleConnectEventHandler, this, - bleDisconnectEventHandler, this, - bleParamUpdatedEventHandler, this); return true; } else @@ -247,13 +246,14 @@ void BLEDeviceManager::setAdvertisedServiceData(const bt_uuid_t* serviceDataUuid const uint8_t* serviceData, uint8_t serviceDataLength) { + // GL. KW warning acknowldged memcpy(&_service_data_uuid, serviceDataUuid, sizeof(_service_data_uuid)); if (serviceDataLength > BLE_MAX_ADV_SIZE) { serviceDataLength = BLE_MAX_ADV_SIZE; } - memcpy(_service_data, serviceData, serviceDataLength); + memcpy(_service_data, serviceData, serviceDataLength);// GL. KW warning acknowldged _service_data_length = serviceDataLength; } @@ -271,7 +271,7 @@ void BLEDeviceManager::setManufacturerData(const unsigned char manufacturerData[ manufacturerDataLength = BLE_MAX_ADV_SIZE; } _manufacturer_data_length = manufacturerDataLength; - memcpy(_manufacturer_data, manufacturerData, manufacturerDataLength); + memcpy(_manufacturer_data, manufacturerData, manufacturerDataLength);// GL. KW warning acknowldged } void BLEDeviceManager::setLocalName(const char *localName) @@ -322,12 +322,14 @@ bool BLEDeviceManager::setTxPower(int txPower) void BLEDeviceManager::setConnectable(bool connectable) { - uint8_t type = BT_LE_ADV_IND; if (connectable == false) { - type = BT_LE_ADV_NONCONN_IND; + _adv_param.options = 0; + } + else + { + _adv_param.options = BT_LE_ADV_OPT_CONNECTABLE; } - _adv_param.type = type; } void BLEDeviceManager::setDeviceName(const char* deviceName) @@ -338,7 +340,7 @@ void BLEDeviceManager::setDeviceName(const char* deviceName) int len = strlen(deviceName); if (len > BLE_MAX_DEVICE_NAME) len = BLE_MAX_DEVICE_NAME; - memcpy(_device_name, deviceName, len); + memcpy(_device_name, deviceName, len);// GL. KW warning acknowldged if (NULL != _local_ble) { setDeviceName(); @@ -355,7 +357,7 @@ BLEDeviceManager::setDeviceName() void BLEDeviceManager::setAppearance(unsigned short appearance) { - _appearance = appearance; + BLEProfileManager::instance()->setAppearance(appearance); } BLE_STATUS_T @@ -407,19 +409,10 @@ BLEDeviceManager::setAdvertiseData(uint8_t type, const uint8_t* data, uint8_t le } BLE_STATUS_T -BLEDeviceManager::_advDataInit(void) +BLEDeviceManager::setAdvertiseSolicitService() { BLE_STATUS_T ret = BLE_STATUS_SUCCESS; - // Clear the indexs - _adv_data_idx = 0; - _scan_rsp_data_idx = 0; - - /* Add flags */ - _adv_type = (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR); - ret = setAdvertiseData (BT_DATA_FLAGS, &_adv_type, sizeof(_adv_type)); - - if (_has_service_solicit_uuid && - (BLE_STATUS_SUCCESS == ret)) + if (_has_service_solicit_uuid) { uint8_t type; uint8_t length; @@ -441,9 +434,14 @@ BLEDeviceManager::_advDataInit(void) ret = setAdvertiseData(type, data, length); } - - if (_has_service_uuid && - (BLE_STATUS_SUCCESS == ret)) + return ret; +} + +BLE_STATUS_T +BLEDeviceManager::setAdvertiseService() +{ + BLE_STATUS_T ret = BLE_STATUS_SUCCESS; + if (_has_service_uuid) { uint8_t type; uint8_t length; @@ -464,17 +462,28 @@ BLEDeviceManager::_advDataInit(void) } ret = setAdvertiseData(type, data, length); } - - if (_manufacturer_data_length > 0 && - (BLE_STATUS_SUCCESS == ret)) + return ret; +} + +BLE_STATUS_T +BLEDeviceManager::setAdvertiseManufacturerData() +{ + BLE_STATUS_T ret = BLE_STATUS_SUCCESS; + + if (_manufacturer_data_length > 0) { ret = setAdvertiseData (BT_DATA_MANUFACTURER_DATA, _manufacturer_data, _manufacturer_data_length); } + return ret; +} - if (_local_name.length() > 0 && - (BLE_STATUS_SUCCESS == ret)) +BLE_STATUS_T +BLEDeviceManager::setAdvertiseLocalName() +{ + BLE_STATUS_T ret = BLE_STATUS_SUCCESS; + if (_local_name.length() > 0) { uint8_t length = _local_name.length(); ret = setAdvertiseData (BT_DATA_NAME_COMPLETE, @@ -482,8 +491,14 @@ BLEDeviceManager::_advDataInit(void) length); } - if (_service_data_length > 0 && - (BLE_STATUS_SUCCESS == ret)) + return ret; +} + +BLE_STATUS_T +BLEDeviceManager::setAdvertiseServiceData() +{ + BLE_STATUS_T ret = BLE_STATUS_SUCCESS; + if (_service_data_length > 0) { /* Add Service Data (if it will fit) */ @@ -506,12 +521,73 @@ BLEDeviceManager::_advDataInit(void) block_len); uint8_t *adv_tmp = _service_data_buf; - + + // GL. KW warning acknowldged memcpy(adv_tmp, &((bt_uuid_16_t*)&_service_data_uuid)->val, sizeof(uint16_t)); adv_tmp += 2; memcpy(adv_tmp, _service_data, _service_data_length); } + return ret; +} + +BLE_STATUS_T +BLEDeviceManager::setAdvertiseFlagData() +{ + BLE_STATUS_T ret = BLE_STATUS_SUCCESS; + /* Add flags */ + _adv_type = (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR); + ret = setAdvertiseData (BT_DATA_FLAGS, &_adv_type, sizeof(_adv_type)); + return ret; +} + +void BLEDeviceManager::clearPeripheralAdvertiseData() +{ + // Clear the indexs + _adv_data_idx = 0; + _scan_rsp_data_idx = 0; +} + +BLE_STATUS_T +BLEDeviceManager::_advDataInit(void) +{ + BLE_STATUS_T ret = BLE_STATUS_SUCCESS; + + clearPeripheralAdvertiseData(); + + ret = setAdvertiseFlagData(); + if (BLE_STATUS_SUCCESS != ret) + { + return ret; + } + ret = setAdvertiseSolicitService(); + if (BLE_STATUS_SUCCESS != ret) + { + return ret; + } + + ret = setAdvertiseService(); + if (BLE_STATUS_SUCCESS != ret) + { + return ret; + } + + ret = setAdvertiseManufacturerData(); + if (BLE_STATUS_SUCCESS != ret) + { + return ret; + } + + ret = setAdvertiseLocalName(); + if (BLE_STATUS_SUCCESS != ret) + { + return ret; + } + + ret = setAdvertiseServiceData(); + + pr_debug(LOG_MODULE_BLE, "%s-ad_len:%d, scanrsp_len:%d", + __FUNCTION__, _adv_data_idx, _scan_rsp_data_idx); return ret; } @@ -519,19 +595,25 @@ BLE_STATUS_T BLEDeviceManager::startAdvertising() { int ret; BLE_STATUS_T status; + bt_data_t* scan_rsp_data = NULL; status = _advDataInit(); if (BLE_STATUS_SUCCESS != status) { return status; } - pr_info(LOG_MODULE_BLE, "%s-ad_len%d", __FUNCTION__, _adv_data_idx); if (_state != BLE_PERIPH_STATE_READY) return BLE_STATUS_WRONG_STATE; + // The V4.2 stack used the pointer to set the ADV type + if (_scan_rsp_data_idx > 0) + { + scan_rsp_data = _scan_rsp_data; + } + ret = bt_le_adv_start(&_adv_param, _adv_data, _adv_data_idx, - _scan_rsp_data, _scan_rsp_data_idx); + scan_rsp_data, _scan_rsp_data_idx); if (0 != ret) { pr_error(LOG_MODULE_APP, "[ADV] Start failed. Error: %d", ret); @@ -611,11 +693,9 @@ void BLEDeviceManager::_clearAdvertiseBuffer() } -bool BLEDeviceManager::startScanningWithDuplicates() +bool BLEDeviceManager::startScaning() { - _adv_duplicate_filter_enabled = false; _scan_param.filter_dup = BT_HCI_LE_SCAN_FILTER_DUP_ENABLE; - _clearAdvertiseBuffer(); int err = bt_le_scan_start(&_scan_param, ble_central_device_found); @@ -627,29 +707,27 @@ bool BLEDeviceManager::startScanningWithDuplicates() return true; } +bool BLEDeviceManager::startScanningWithDuplicates() +{ + _adv_duplicate_filter_enabled = false; + return startScaning(); +} + bool BLEDeviceManager::startScanningNewPeripherals() { + // Clear the filter old buffer _adv_duplicate_filter_enabled = true; - memset(_peer_duplicate_address_buffer, 0, sizeof(_peer_duplicate_address_buffer)); _duplicate_filter_header = _duplicate_filter_tail = 0; + memset(_peer_duplicate_address_buffer, 0, sizeof(_peer_duplicate_address_buffer)); - _clearAdvertiseBuffer(); - - _scan_param.filter_dup = BT_HCI_LE_SCAN_FILTER_DUP_ENABLE; - int err = bt_le_scan_start(&_scan_param, ble_central_device_found); - if (err) - { - pr_info(LOG_MODULE_BLE, "Scanning failed to start (err %d)\n", err); - return false; - } - return true; + return startScaning(); } bool BLEDeviceManager::stopScanning() { int err = bt_le_scan_stop(); - if (err) // Sid. TODO: KW detected bt_le_scan_stop return only 0. + if (err) { pr_info(LOG_MODULE_BLE, "Stop LE scan failed (err %d)\n", err); return false; @@ -765,17 +843,21 @@ bool BLEDeviceManager::hasLocalName(const BLEDevice* device) const const uint8_t* local_name = NULL; uint8_t local_name_len = 0; + + // Get local name bool retval = getDataFromAdvertiseByType(device, BT_DATA_NAME_COMPLETE, local_name, local_name_len); - if (false == retval) + if (true == retval) { - retval = getDataFromAdvertiseByType(device, - BT_DATA_NAME_SHORTENED, - local_name, - local_name_len); + return true; } + // Get shorten name + retval = getDataFromAdvertiseByType(device, + BT_DATA_NAME_SHORTENED, + local_name, + local_name_len); return retval; } @@ -811,6 +893,7 @@ bool BLEDeviceManager::getManufacturerData (const BLEDevice* device, manufactgurer_data_len); if (retval) { + // GL. KW warning acknowldged memcpy (manu_data, manufactgurer_data, manufactgurer_data_len); manu_data_len = manufactgurer_data_len; } @@ -936,13 +1019,13 @@ int BLEDeviceManager::advertisedServiceUuidCount(const BLEDevice* device) const return service_cnt; } - /* Sid, 2/15/2017. Sandeep reported that Apple devices may use - BT_DATA_UUID16_SOME and BT_DATA_UUID128_SOME in addition to ALL. - Practically, these types are same as ALL. */ + /* Sid, 2/15/2017. Sandeep reported that Apple devices may use + BT_DATA_UUID16_SOME and BT_DATA_UUID128_SOME in addition to ALL. + Practically, these types are same as ALL. */ if (type == BT_DATA_UUID16_ALL || type == BT_DATA_UUID128_ALL || - type == BT_DATA_UUID16_SOME || - type == BT_DATA_UUID128_SOME) + type == BT_DATA_UUID16_SOME || + type == BT_DATA_UUID128_SOME) { service_cnt++; } @@ -959,7 +1042,7 @@ String BLEDeviceManager::localName(const BLEDevice* device) const { return _local_name; } - + const uint8_t* local_name = NULL; uint8_t local_name_len = 0; String temp(""); @@ -982,7 +1065,7 @@ String BLEDeviceManager::localName(const BLEDevice* device) const { local_name_len = BLE_MAX_ADV_SIZE - 1; } - memcpy(local_name_buff, local_name, local_name_len); + memcpy(local_name_buff, local_name, local_name_len);// GL. KW warning acknowldged local_name_buff[local_name_len] = '\0'; temp = local_name_buff; } @@ -1037,8 +1120,8 @@ String BLEDeviceManager::advertisedServiceUuid(const BLEDevice* device, int inde if (type == BT_DATA_UUID16_ALL || type == BT_DATA_UUID128_ALL || - type == BT_DATA_UUID16_SOME || - type == BT_DATA_UUID128_SOME) + type == BT_DATA_UUID16_SOME || + type == BT_DATA_UUID128_SOME) { service_cnt++; } @@ -1046,15 +1129,15 @@ String BLEDeviceManager::advertisedServiceUuid(const BLEDevice* device, int inde if (index < service_cnt) { if (type == BT_DATA_UUID16_ALL || - type == BT_DATA_UUID16_SOME) + type == BT_DATA_UUID16_SOME) { service_uuid.uuid.type = BT_UUID_TYPE_16; - memcpy(&BT_UUID_16(&service_uuid.uuid)->val, &adv_data[2], 2); + memcpy(&BT_UUID_16(&service_uuid.uuid)->val, &adv_data[2], 2);// GL. KW warning acknowldged } else { service_uuid.uuid.type = BT_UUID_TYPE_128; - memcpy(service_uuid.val, &adv_data[2], 16); + memcpy(service_uuid.val, &adv_data[2], 16);// GL. KW warning acknowldged } BLEUtils::uuidBT2String(&service_uuid.uuid, uuid_string); @@ -1109,6 +1192,7 @@ bool BLEDeviceManager::connect(BLEDevice &device) bt_addr_le_copy(&_wait_for_connect_peripheral, device.bt_le_address()); // Buffer the ADV data + // GL. KW warning acknowldged memcpy(_wait_for_connect_peripheral_adv_data, _available_for_connect_peripheral_adv_data, BLE_MAX_ADV_SIZE); memcpy(_wait_for_connect_peripheral_scan_rsp_data, _available_for_connect_peripheral_scan_rsp_data, BLE_MAX_ADV_SIZE); _wait_for_connect_peripheral_adv_data_len = _available_for_connect_peripheral_adv_data_len; @@ -1155,7 +1239,7 @@ bool BLEDeviceManager::connectToDevice(BLEDevice &device) bool link_existed = false; bool retval = false; - pr_debug(LOG_MODULE_BLE, "%s-%d-1", __FUNCTION__, __LINE__); + //pr_debug(LOG_MODULE_BLE, "%s-%d-1", __FUNCTION__, __LINE__); // Find free peripheral Items for (int i = 0; i < BLE_MAX_CONN_CFG; i++) @@ -1177,6 +1261,7 @@ bool BLEDeviceManager::connectToDevice(BLEDevice &device) { unused = temp; // Buffer the ADV data + // GL. KW warning acknowldged memcpy(_peer_peripheral_adv_data[i], _wait_for_connect_peripheral_adv_data, BLE_MAX_ADV_SIZE); @@ -1189,7 +1274,7 @@ bool BLEDeviceManager::connectToDevice(BLEDevice &device) } } } - pr_debug(LOG_MODULE_BLE, "%s-%d:link_existed-%d unused-%p", __FUNCTION__, __LINE__, link_existed, unused); + //pr_debug(LOG_MODULE_BLE, "%s-%d:link_existed-%d unused-%p", __FUNCTION__, __LINE__, link_existed, unused); if (!link_existed && NULL != unused) { @@ -1198,6 +1283,7 @@ bool BLEDeviceManager::connectToDevice(BLEDevice &device) bt_conn_t* conn = bt_conn_create_le(device.bt_le_address(), device.bt_conn_param()); if (NULL != conn) { + // GL. KW warning acknowldged memcpy(unused, device.bt_le_address(), sizeof(bt_addr_le_t)); retval = true; _connecting = true; @@ -1213,12 +1299,12 @@ String BLEDeviceManager::deviceName(const BLEDevice* device) { return _device_name; } - return String(""); + return BLEProfileManager::instance()->getDeviceName(device); } int BLEDeviceManager::appearance() { - return _appearance; + return BLEProfileManager::instance()->getAppearance(); } BLEDeviceManager* BLEDeviceManager::instance() @@ -1246,6 +1332,7 @@ void BLEDeviceManager::handleConnectEvent(bt_conn_t *conn, uint8_t err) if (BT_CONN_ROLE_SLAVE == role_info.role) { // Central has established the connection with this peripheral device + // GL. KW warning acknowldged memcpy(&_peer_central, bt_conn_get_dst(conn), sizeof (bt_addr_le_t)); } else @@ -1319,12 +1406,6 @@ bool BLEDeviceManager::advertiseDataProc(uint8_t type, const uint8_t *dataPtr, uint8_t data_len) { - //Serial1.print("[AD]:"); - //Serial1.print(type); - //Serial1.print(" data_len "); - //Serial1.println(data_len); - - //const bt_data_t zero = {0, 0,0}; if (_adv_accept_critical.type == 0 && _adv_accept_critical.data_len == 0 && _adv_accept_critical.data == NULL) @@ -1332,6 +1413,7 @@ bool BLEDeviceManager::advertiseDataProc(uint8_t type, // Not set the critical. Accept all. return true; } + if (type == _adv_accept_critical.type && data_len == _adv_accept_critical.data_len && 0 == memcmp(dataPtr, _adv_accept_critical.data, data_len)) @@ -1388,7 +1470,9 @@ BLEDevice BLEDeviceManager::available() { uint64_t timestamp_delta = timestamp - _peer_adv_mill[i]; temp = &_peer_adv_buffer[i]; - if ((timestamp_delta <= 2000) && (max_delta < timestamp_delta) && (_peer_scan_rsp_data_len[i] >= 0 || !_peer_adv_connectable[i])) + if ((timestamp_delta >= 800 || _peer_scan_rsp_data_len[i] >= 0) && // Wait scan response coming + (timestamp_delta <= 2000) && // Check timeout + (max_delta < timestamp_delta)) { // Eable the duplicate filter if (_adv_duplicate_filter_enabled && @@ -1410,6 +1494,7 @@ BLEDevice BLEDeviceManager::available() { tempdevice.setAddress(*temp); bt_addr_le_copy(&_available_for_connect_peripheral, temp); + // GL. KW warning acknowldged memcpy(_available_for_connect_peripheral_adv_data, _peer_adv_data[index], BLE_MAX_ADV_SIZE); memcpy(_available_for_connect_peripheral_scan_rsp_data, _peer_scan_rsp_data[index], BLE_MAX_ADV_SIZE); _available_for_connect_peripheral_scan_rsp_data_len = _peer_scan_rsp_data_len[index]; @@ -1450,7 +1535,7 @@ bool BLEDeviceManager::setAdvertiseBuffer(const bt_addr_le_t* bt_addr, if (max_delta > 2000) // expired { index = i; - _peer_scan_rsp_data_len[index] = -1; // Invalid the scan response + _peer_scan_rsp_data_len[index] = 0; // Invalid the scan response } } @@ -1469,17 +1554,19 @@ bool BLEDeviceManager::setAdvertiseBuffer(const bt_addr_le_t* bt_addr, temp = &_peer_adv_buffer[index]; if (i >= BLE_MAX_ADV_BUFFER_CFG) { + // GL. KW warning acknowldged memcpy(temp, bt_addr, sizeof (bt_addr_le_t)); } if (data_len > BLE_MAX_ADV_SIZE) { data_len = BLE_MAX_ADV_SIZE; } - memcpy(_peer_adv_data[index], ad, data_len); + memcpy(_peer_adv_data[index], ad, data_len);// GL. KW warning acknowldged _peer_adv_data_len[index] = data_len; _peer_adv_rssi[index] = rssi; // Update the timestamp - _peer_adv_mill[index] = timestamp; + if (timestamp - _peer_adv_mill[index] > 1000) + _peer_adv_mill[index] = timestamp; _peer_adv_connectable[index] = connectable; retval = true; } @@ -1517,11 +1604,13 @@ bool BLEDeviceManager::setScanRespBuffer(const bt_addr_le_t* bt_addr, { data_len = BLE_MAX_ADV_SIZE; } + // GL. KW warning acknowldged memcpy(_peer_scan_rsp_data[index], ad, data_len); _peer_scan_rsp_data_len[index] = data_len; //_peer_adv_rssi[index] = rssi; // Update the timestamp - _peer_adv_mill[index] = timestamp; + if (timestamp - _peer_adv_mill[index] > 1000) + _peer_adv_mill[index] = timestamp; retval = true; } @@ -1562,13 +1651,13 @@ void BLEDeviceManager::setTempAdvertiseBuffer(const bt_addr_le_t* bt_addr, } temp = &_peer_temp_adv_buffer[i]; - memcpy(temp, bt_addr, sizeof (bt_addr_le_t)); + memcpy(temp, bt_addr, sizeof (bt_addr_le_t));// GL. KW warning acknowldged if (data_len > BLE_MAX_ADV_SIZE) { data_len = BLE_MAX_ADV_SIZE; } - memcpy(_peer_temp_adv_data[i], ad, data_len); + memcpy(_peer_temp_adv_data[i], ad, data_len);// GL. KW warning acknowldged _peer_temp_adv_data_len[i] = data_len; _peer_temp_adv_connectable[i] = connectable; @@ -1650,7 +1739,7 @@ void BLEDeviceManager::handleDeviceFound(const bt_addr_le_t *addr, //pr_debug(LOG_MODULE_BLE, "%s-%d", __FUNCTION__, __LINE__); // Filter address if (BLEUtils::macAddressValid(_adv_accept_device) == true && - (memcmp(addr->val, _adv_accept_device.val, sizeof (addr->val)) != 0)) + (memcmp(addr->a.val, _adv_accept_device.a.val, sizeof (addr->a.val)) != 0)) { pr_debug(LOG_MODULE_BLE, "%s-%d", __FUNCTION__, __LINE__); return; diff --git a/libraries/CurieBLE/src/internal/BLEDeviceManager.h b/libraries/CurieBLE/src/internal/BLEDeviceManager.h index 60aa6f17..f82aa944 100644 --- a/libraries/CurieBLE/src/internal/BLEDeviceManager.h +++ b/libraries/CurieBLE/src/internal/BLEDeviceManager.h @@ -340,6 +340,13 @@ class BLEDeviceManager BLE_STATUS_T setAdvertiseData (uint8_t type, const uint8_t* data, uint8_t length); + BLE_STATUS_T setAdvertiseSolicitService(); + BLE_STATUS_T setAdvertiseService(); + BLE_STATUS_T setAdvertiseManufacturerData(); + BLE_STATUS_T setAdvertiseLocalName(); + BLE_STATUS_T setAdvertiseServiceData(); + BLE_STATUS_T setAdvertiseFlagData(); + void clearPeripheralAdvertiseData(); BLE_STATUS_T _advDataInit(void); void _clearAdvertiseBuffer(); bool advertiseDataProc(uint8_t type, @@ -378,6 +385,7 @@ class BLEDeviceManager uint8_t data_len, bool connectable); uint8_t getTempAdvertiseIndexFromBuffer(const bt_addr_le_t* bt_addr); + bool startScaning(); private: uint16_t _min_conn_interval; @@ -392,7 +400,7 @@ class BLEDeviceManager uint8_t _peer_adv_data[BLE_MAX_ADV_BUFFER_CFG][BLE_MAX_ADV_SIZE]; uint8_t _peer_adv_data_len[BLE_MAX_ADV_BUFFER_CFG]; uint8_t _peer_scan_rsp_data[BLE_MAX_ADV_BUFFER_CFG][BLE_MAX_ADV_SIZE]; - int8_t _peer_scan_rsp_data_len[BLE_MAX_ADV_BUFFER_CFG]; + uint8_t _peer_scan_rsp_data_len[BLE_MAX_ADV_BUFFER_CFG]; int8_t _peer_adv_rssi[BLE_MAX_ADV_BUFFER_CFG]; bool _peer_adv_connectable[BLE_MAX_ADV_BUFFER_CFG]; @@ -431,7 +439,6 @@ class BLEDeviceManager bt_uuid_128_t _service_uuid; bool _has_service_solicit_uuid; bt_uuid_128_t _service_solicit_uuid; - uint16_t _appearance; uint8_t _manufacturer_data[BLE_MAX_ADV_SIZE]; uint8_t _manufacturer_data_length; bt_uuid_128_t _service_data_uuid; diff --git a/libraries/CurieBLE/src/internal/BLEProfileManager.cpp b/libraries/CurieBLE/src/internal/BLEProfileManager.cpp index aba7981b..94928a33 100644 --- a/libraries/CurieBLE/src/internal/BLEProfileManager.cpp +++ b/libraries/CurieBLE/src/internal/BLEProfileManager.cpp @@ -26,6 +26,8 @@ #include "BLEUtils.h" BLEDevice BLE(BLEUtils::bleGetLoalAddress()); +static BLEService gapService("1800"); +static BLEUnsignedShortCharacteristic appearenceChrc("2a01", BLERead); BLEProfileManager* BLEProfileManager::_instance = NULL; @@ -42,6 +44,7 @@ BLEProfileManager* BLEProfileManager::instance() BLEProfileManager::BLEProfileManager (): _start_discover(false), + _discover_gap_gatt(false), _discovering(false), _discover_rsp_timestamp(0), _cur_discover_service(NULL), @@ -67,6 +70,8 @@ BLEProfileManager::BLEProfileManager (): _service_header_array[i].value = NULL; } + addService(BLE, gapService); + gapService.addCharacteristic(appearenceChrc); pr_debug(LOG_MODULE_BLE, "%s-%d: Construct", __FUNCTION__, __LINE__); } @@ -100,17 +105,7 @@ BLEProfileManager::addService (BLEDevice &bledevice, BLEService& service) serviceheader = &_service_header_array[index]; bt_addr_le_copy(&_addresses[index], bledevice.bt_le_address()); } - BLEServiceImp *serviceImp = NULL;//this->service(bledevice, service.uuid()); - //if (NULL != serviceImp) - //{ - // The service alreay exist - // return serviceImp; - //} - - //if (NULL == serviceImp) // May trigger KW warning - { - serviceImp = service.fetchOutLocalServiceImp(); - } + BLEServiceImp *serviceImp = service.fetchOutLocalServiceImp(); if (NULL == serviceImp) { @@ -241,8 +236,6 @@ int BLEProfileManager::serviceCount(const BLEDevice &bledevice) const int BLEProfileManager::registerProfile(BLEDevice &bledevice) { - int ret = 0; - bt_gatt_attr_t *start; BleStatus err_code = BLE_STATUS_SUCCESS; @@ -288,35 +281,20 @@ int BLEProfileManager::registerProfile(BLEDevice &bledevice) { BLEServiceImp *service = node->value; start = _attr_base + _attr_index; - service->updateProfile(start, _attr_index); - node = node->next; - } - -#if 0 - // Start debug - int i; - - for (i = 0; i < _attr_index; i++) { + err_code = service->updateProfile(start, _attr_index); + if (BLE_STATUS_SUCCESS != err_code) { - pr_info(LOG_MODULE_APP, "gatt-: i %d, type %d, u16 0x%x", - i, - _attr_base[i].uuid->type, - BT_UUID_16(_attr_base[i].uuid)->val); + break; } + node = node->next; } - delay(1000); - // End for debug -#endif - - ret = bt_gatt_register(_attr_base, - _attr_index); - pr_debug(LOG_MODULE_APP, "%s: ret, %d,_attr_index-%d", __FUNCTION__, ret, _attr_index); - if (0 == ret) + // Will not regiter the profile if ARC registered any profile + if (_attr_index > 0) { _profile_registered = true; } - return ret; + return err_code; } void BLEProfileManager::clearProfile(BLEServiceLinkNodeHeader* serviceHeader) @@ -616,81 +594,29 @@ void BLEProfileManager::handleDisconnectedPutOffEvent() } } -bool BLEProfileManager::discoverAttributes(BLEDevice* device) +bool BLEProfileManager::discoverAllAttributes(BLEDevice* device, + bool discoverGapGatt) { - int err; - bt_conn_t* conn; - int i = getDeviceIndex(device); - bool ret = false; - bt_gatt_discover_params_t* temp = NULL; - - errno = 0; - pr_debug(LOG_MODULE_BLE, "%s-%d: index-%d,fun-%p", __FUNCTION__, __LINE__, i,profile_discover_process); - - if (_start_discover) - { - // Already in discover state - return false; - } - + _discover_gap_gatt = discoverGapGatt; + return discoverAttributes(device, NULL); +} - if (i >= BLE_MAX_CONN_CFG) - { - // The device already in the buffer. - // This function only be called after connection established. - return ret; - } - - conn = bt_conn_lookup_addr_le(device->bt_le_address()); - if (NULL == conn) - { - // Link lost - pr_debug(LOG_MODULE_BLE, "Can't find connection\n"); - return ret; - } - temp = &_discover_params[i]; - temp->start_handle = 1; - temp->end_handle = 0xFFFF; - temp->uuid = NULL; - temp->type = BT_GATT_DISCOVER_PRIMARY; - temp->func = profile_discover_process; +bool BLEProfileManager::discoverAttributesByService(BLEDevice* device, + const bt_uuid_t* svc_uuid) +{ + bool ret; + _discover_one_service = true; + ret = discoverAttributes(device, svc_uuid); + _discover_one_service = false; - err = bt_gatt_discover(conn, temp); - bt_conn_unref(conn); - if (err) - { - pr_debug(LOG_MODULE_BLE, "Discover failed(err %d)\n", err); - return ret; - } - // Block it - memcpy(&_discovering_ble_addresses, device->bt_le_address(), sizeof(_discovering_ble_addresses)); - _discover_rsp_timestamp = millis(); - _start_discover = true; - ret = true; - while (_start_discover) // Sid. KW warning acknowldged - { - delay(10); - if ((millis() - _discover_rsp_timestamp) > 5000) - { - // Doesn't receive the Service read response - _start_discover = false; - _cur_discover_service = NULL; - ret = false; - _reading = false; - } - - if (ENOMEM == errno) - { - pr_debug(LOG_MODULE_BLE, "%s-%d:Sys errno(err %d)\n", __FUNCTION__, __LINE__, errno); - ret = false; - break; - } - } return ret; } -bool BLEProfileManager::discoverAttributesByService(BLEDevice* device, const bt_uuid_t* svc_uuid) +bool BLEProfileManager::discoverAttributes(BLEDevice* device, + const bt_uuid_t* svc_uuid) { + bool ret = false; + errno = 0; if (_start_discover) { @@ -698,43 +624,42 @@ bool BLEProfileManager::discoverAttributesByService(BLEDevice* device, const bt_ return false; } - bool ret = discoverService(device, svc_uuid); + ret = discoverService(device, svc_uuid); if (false == ret) { return false; } + // Block it + // GL. KW warning acknowldged memcpy(&_discovering_ble_addresses, device->bt_le_address(), sizeof(_discovering_ble_addresses)); _discover_rsp_timestamp = millis(); _start_discover = true; - _discover_one_service = true; while (_start_discover) // Sid. KW warning acknowldged { delay(10); - if ((millis() - _discover_rsp_timestamp) > 5000) + if (BLEUtils::getElapsedMillSeconds(_discover_rsp_timestamp) > 5000) { // Doesn't receive the Service read response + // Timeout _start_discover = false; _cur_discover_service = NULL; ret = false; _reading = false; + break; } if (ENOMEM == errno) { - pr_debug(LOG_MODULE_BLE, "%s-%d:Sys errno(err %d)", __FUNCTION__, __LINE__, errno); + pr_debug(LOG_MODULE_BLE, "%s-%d:Sys errno(err %d)\n", __FUNCTION__, __LINE__, errno); ret = false; break; } } - pr_debug(LOG_MODULE_BLE, "%s-%d:Discover Done", __FUNCTION__, __LINE__); - _discover_one_service = false; - return ret; } - int BLEProfileManager::getDeviceIndex(const bt_addr_le_t* macAddr) { int i; @@ -768,22 +693,134 @@ void BLEProfileManager::setDiscovering(bool discover) _discovering = discover; } +void BLEProfileManager::singleServiceDiscoverResponseProc(BLEDevice &device, + BLEServiceImp* service) +{ + bool result = service->discoverAttributes(&device, true); + if (result == true) + { + // Record the current discovering service + _cur_discover_service = service; + } +} + +uint8_t BLEProfileManager::primaryServiceResponseProc(BLEDevice &device, + const bt_gatt_attr_t *attr, + bt_gatt_discover_params_t *params) +{ + uint16_t le16; + BLEServiceImp* service_tmp = NULL; + uint8_t retVal = BT_GATT_ITER_STOP; + struct bt_gatt_service *svc_value; + const bt_uuid_t* svc_uuid; + + if (NULL == attr) + { + // Service discover complete + return BT_GATT_ITER_STOP; + } + + // Get response data + svc_value = (struct bt_gatt_service *)attr->user_data; + svc_uuid = svc_value->uuid; + memcpy(&le16, &BT_UUID_16(svc_uuid)->val, sizeof(le16));// GL. KW warning acknowldged + + setDiscovering(false); + + if (svc_uuid->type == BT_UUID_TYPE_16 && + le16 == 0) + { + // Workaround: + // Discover failed. The service may unknow type. + // Need read the value and discovery again. + readService(device, attr->handle); + } + else + { + // Add to the buffer + service_tmp = addService(device, svc_value->uuid); + params->uuid = NULL; + + if (NULL != service_tmp) + { + service_tmp->setHandle(attr->handle); + service_tmp->setEndHandle(svc_value->end_handle); + + if (true == _discover_one_service) + { + singleServiceDiscoverResponseProc(device, service_tmp); + } + else + { + retVal = BT_GATT_ITER_CONTINUE; + } + } + else + { + pr_debug(LOG_MODULE_BLE, "%s-%d: Add service failed", + __FUNCTION__, __LINE__); + errno = ENOMEM; + } + } + + return retVal; +} + +void BLEProfileManager::discoverCompleteProc() +{ + _start_discover = false; + memset(&_discovering_ble_addresses, 0, sizeof(_discovering_ble_addresses)); +} + +bool BLEProfileManager::discoverNextService(BLEDevice &device) +{ + const BLEServiceLinkNodeHeader* serviceHeader = getServiceHeader(device); + BLEServiceImp* serviceCurImp = NULL; + if (NULL == serviceHeader) + { + // Doesn't find the service + return false; + } + BLEServiceNodePtr node = serviceHeader->next; + + // Discover next service + while (node != NULL) + { + serviceCurImp = node->value; + + if (NULL == _cur_discover_service) + { + bool result = serviceCurImp->discoverAttributes(&device, + _discover_gap_gatt); + if (result == true) + { + // Record the current discovering service + _cur_discover_service = serviceCurImp; + break; + } + } + else if (_cur_discover_service == serviceCurImp) + { + // Find next discoverable service + _cur_discover_service = NULL; + } + + node = node->next; + } + return (node != NULL); +} + uint8_t BLEProfileManager::discoverResponseProc(bt_conn_t *conn, const bt_gatt_attr_t *attr, bt_gatt_discover_params_t *params) { const bt_addr_le_t* dst_addr = bt_conn_get_dst(conn); - int i = getDeviceIndex(dst_addr); BLEDevice device(dst_addr); uint8_t retVal = BT_GATT_ITER_STOP; - BLEServiceImp* service_tmp = NULL; + _discover_rsp_timestamp = millis(); - //pr_debug(LOG_MODULE_BLE, "%s-%d: index-%d", __FUNCTION__, __LINE__, i); - if (i >= BLE_MAX_CONN_CFG) - { - return BT_GATT_ITER_STOP; - } + //pr_debug(LOG_MODULE_BLE, "%s-%d: index-%d", __FUNCTION__, __LINE__, i); // Process the service switch (params->type) @@ -801,48 +838,8 @@ uint8_t BLEProfileManager::discoverResponseProc(bt_conn_t *conn, } case BT_GATT_DISCOVER_PRIMARY: { - if (NULL != attr) - { - struct bt_gatt_service *svc_value = (struct bt_gatt_service *)attr->user_data; - const bt_uuid_t* svc_uuid = svc_value->uuid; - uint16_t le16; - memcpy(&le16, &BT_UUID_16(svc_uuid)->val, sizeof(le16)); - setDiscovering(false); - - if (svc_uuid->type == BT_UUID_TYPE_16 && - le16 == 0) - { - // Discover failed. The service may unknow type. - // Need read the value and discovery again. - readService(device, attr->handle); - retVal = BT_GATT_ITER_CONTINUE; - } - else - { - service_tmp = addService(device, svc_value->uuid); - params->uuid = NULL; - - if (NULL != service_tmp) - { - service_tmp->setHandle(attr->handle); - service_tmp->setEndHandle(svc_value->end_handle); - if (_discover_one_service == false) - retVal = BT_GATT_ITER_CONTINUE; - } - else - { - retVal = BT_GATT_ITER_STOP; - errno = ENOMEM; - pr_debug(LOG_MODULE_BLE, "%s-%d: Add service failed", - __FUNCTION__, __LINE__); - } - } - } - else - { - // Service discover complete - retVal = BT_GATT_ITER_STOP; - } + retVal = primaryServiceResponseProc(device, attr, params); + break; } default: { @@ -854,92 +851,20 @@ uint8_t BLEProfileManager::discoverResponseProc(bt_conn_t *conn, { if (errno == ENOMEM) { - // No memory. Stop discovery + // Out of memory. Stop discovery _cur_discover_service = NULL; _discover_one_service = false; - return retVal; - } - - pr_debug(LOG_MODULE_BLE, "%s-%d: Discover one service-%d", - __FUNCTION__, __LINE__, _discover_one_service); - if (true == _discover_one_service) - { - if (NULL != service_tmp) - { - pr_debug(LOG_MODULE_BLE, "%s-%d: Discover service", - __FUNCTION__, __LINE__); - bool result = service_tmp->discoverAttributes(&device); - if (result == true) - { - // Record the current discovering service - _cur_discover_service = service_tmp; - } - else - { - // Failed - _discover_one_service = false; - } - } - else - { - if (discovering() == false) - { - // Complete - _cur_discover_service = NULL; - _discover_one_service = false; - } - } - - if (_discover_one_service == false) - { - // Discover complete - _start_discover = false; - memset(&_discovering_ble_addresses, 0, sizeof(_discovering_ble_addresses)); - } - return retVal; + return BT_GATT_ITER_STOP; } checkReadService(); if (discovering() == false) { - const BLEServiceLinkNodeHeader* serviceHeader = getServiceHeader(device); - BLEServiceImp* serviceCurImp = NULL; - if (NULL == serviceHeader) - { - // Doesn't find the service - return BT_GATT_ITER_STOP; - } - BLEServiceNodePtr node = serviceHeader->next; - - // Discover next service - while (node != NULL) - { - serviceCurImp = node->value; - - if (NULL == _cur_discover_service) - { - bool result = serviceCurImp->discoverAttributes(&device); - if (result == true) - { - // Record the current discovering service - _cur_discover_service = serviceCurImp; - break; - } - } - else if (_cur_discover_service == serviceCurImp) - { - // Find next discoverable service - _cur_discover_service = NULL; - } - - node = node->next; - } - if (NULL == node) + if (false == discoverNextService(device)) { pr_debug(LOG_MODULE_BLE, "%s-%d: Discover completed", __FUNCTION__, __LINE__); - _start_discover = false; - memset(&_discovering_ble_addresses, 0, sizeof(_discovering_ble_addresses)); + discoverCompleteProc(); } } } @@ -970,17 +895,19 @@ void BLEProfileManager::serviceDiscoverComplete(const BLEDevice &bledevice) serviceCurImp = node->value; if (NULL != serviceCurImp) { - if (servicePrevImp) // KW issue: Chk for NULL. + if (servicePrevImp) + { servicePrevImp->setEndHandle(serviceCurImp->startHandle() - 1); + pr_debug(LOG_MODULE_BLE, "Pre: start-%d, end-%d", + servicePrevImp->startHandle(), + servicePrevImp->endHandle()); + pr_debug(LOG_MODULE_BLE, "Curr: start-%d, end-%d", + serviceCurImp->startHandle(), + serviceCurImp->endHandle()); + } } - if (servicePrevImp) - { - pr_debug(LOG_MODULE_BLE, "Curr: start-%d, end-%d", servicePrevImp->startHandle(), servicePrevImp->endHandle()); - } servicePrevImp = serviceCurImp; - if (servicePrevImp) // KW issue: Chk for NULL. - pr_debug(LOG_MODULE_BLE, "Curr: start-%d, end-%d", servicePrevImp->startHandle(), servicePrevImp->endHandle()); node = node->next; } return; @@ -1057,9 +984,8 @@ bool BLEProfileManager::discoverService(BLEDevice* device, const bt_uuid_t* svc_ { int err = 0; bt_conn_t* conn; - int i = getDeviceIndex(device); - bool ret = false; bt_gatt_discover_params_t* temp = NULL; + int i = getDeviceIndex(device); pr_debug(LOG_MODULE_BLE, "%s-%d: index-%d,fun-%p", __FUNCTION__, __LINE__, i,profile_discover_process); @@ -1067,38 +993,35 @@ bool BLEProfileManager::discoverService(BLEDevice* device, const bt_uuid_t* svc_ { // The device already in the buffer. // This function only be called after connection established. - return ret; - } - - //BLEServiceImp* serviceImp = service(device, svc_uuid); - //if (NULL == serviceImp) - { - //return ret; + return false; } conn = bt_conn_lookup_addr_le(device->bt_le_address()); if (NULL == conn) { // Link lost - pr_debug(LOG_MODULE_BLE, "Can't find connection\n"); - return ret; + pr_debug(LOG_MODULE_BLE, "Can't find connection, Link lost!\n"); + return false; } - memcpy(&_discover_uuid[i], svc_uuid, sizeof(bt_uuid_128_t)); - temp = &_discover_params[i]; temp->start_handle = 1; temp->end_handle = 0xFFFF; - temp->uuid = (bt_uuid_t*) &_discover_uuid[i]; temp->type = BT_GATT_DISCOVER_PRIMARY; temp->func = profile_discover_process; + temp->uuid = NULL; + if (NULL != svc_uuid) + { + memcpy(&_discover_uuid[i], svc_uuid, sizeof(bt_uuid_128_t));// GL. KW warning acknowldged + temp->uuid = (bt_uuid_t*) &_discover_uuid[i]; + } err = bt_gatt_discover(conn, temp); bt_conn_unref(conn); if (err) { pr_debug(LOG_MODULE_BLE, "Discover failed(err %d)\n", err); - return ret; + return false; } return true; } @@ -1122,7 +1045,7 @@ uint8_t BLEProfileManager::serviceReadRspProc(bt_conn_t *conn, { bt_uuid_128_t uuid_tmp; uuid_tmp.uuid.type = BT_UUID_TYPE_128; - memcpy(uuid_tmp.val, data, UUID_SIZE_128); + memcpy(uuid_tmp.val, data, UUID_SIZE_128);// GL. KW warning acknowldged BLEProfileManager::instance()->discoverService(&bleDevice, (const bt_uuid_t *)&uuid_tmp); } pr_debug(LOG_MODULE_BLE, "%s-%d", __FUNCTION__, __LINE__); @@ -1130,5 +1053,46 @@ uint8_t BLEProfileManager::serviceReadRspProc(bt_conn_t *conn, return BT_GATT_ITER_STOP; } +void BLEProfileManager::setAppearance(unsigned short appearance) +{ + if (false == hasRegisterProfile()) + { + appearenceChrc.setValue(appearance); + } +} + +unsigned short BLEProfileManager::getAppearance() +{ + return appearenceChrc.value(); +} +String BLEProfileManager::getDeviceName(const BLEDevice* device) +{ + String temp(""); + char device_name_buff[BLE_MAX_DEVICE_NAME]; + unsigned short device_name_len; + + BLEServiceImp* gap_service = service(*device, "1800"); + if (NULL == gap_service) + { + return temp; + } + BLECharacteristicImp* devicename_chrc = gap_service->characteristic("2a00"); + if (NULL == devicename_chrc) + { + return temp; + } + + // Read device name + if (false == devicename_chrc->read(true)) + { + return temp; + } + device_name_len = devicename_chrc->valueLength(); + memcpy(device_name_buff, devicename_chrc->value(), device_name_len);// GL. KW warning acknowldged + device_name_buff[device_name_len] = '\0'; + temp = device_name_buff; + + return temp; +} diff --git a/libraries/CurieBLE/src/internal/BLEProfileManager.h b/libraries/CurieBLE/src/internal/BLEProfileManager.h index 1c05fc99..a6ba0854 100644 --- a/libraries/CurieBLE/src/internal/BLEProfileManager.h +++ b/libraries/CurieBLE/src/internal/BLEProfileManager.h @@ -65,7 +65,7 @@ class BLEProfileManager{ * * @param[in] bledevice The BLE Device * - * @return int std C errno + * @return int BLE errno @BleStatus * * @note none */ @@ -107,7 +107,9 @@ class BLEProfileManager{ const bt_gatt_attr_t *attr, bt_gatt_discover_params_t *params); - bool discoverAttributes(BLEDevice* device); + // Default not discover the GAP/GATT service + bool discoverAllAttributes(BLEDevice* device, + bool discoverGapGatt = false); bool discoverAttributesByService(BLEDevice* device, const bt_uuid_t* svc_uuid); void handleConnectedEvent(const bt_addr_le_t* deviceAddr); void handleDisconnectedEvent(const bt_addr_le_t* deviceAddr); @@ -117,6 +119,22 @@ class BLEProfileManager{ bt_gatt_read_params_t *params, const void *data, uint16_t length); + /** + * @brief Set the appearance type for the BLE Peripheral Device + * + * See https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml + * for available options. + * + * @param[in] appearance Appearance category identifier as defined by BLE Standard + * + * @return BleStatus indicating success or error + * + * @note This method must be called before the begin method + */ + void setAppearance(unsigned short appearance); + unsigned short getAppearance(); + + String getDeviceName(const BLEDevice* device); protected: friend ssize_t profile_write_process(bt_conn_t *conn, const bt_gatt_attr_t *attr, @@ -191,7 +209,17 @@ class BLEProfileManager{ bool discovering(); void setDiscovering(bool discover); void checkReadService(); - + bool discoverNextService(BLEDevice &device); + void discoverCompleteProc(); + uint8_t primaryServiceResponseProc(BLEDevice &device, + const bt_gatt_attr_t *attr, + bt_gatt_discover_params_t *params); + void singleServiceDiscoverResponseProc(BLEDevice &device, + BLEServiceImp* service); + + bool discoverAttributes(BLEDevice* device, + const bt_uuid_t* svc_uuid); + private: // The last header is for local BLE BLEServiceLinkNodeHeader _service_header_array[BLE_MAX_CONN_CFG + 1]; // The connected devices' service and self service @@ -199,6 +227,7 @@ class BLEProfileManager{ bt_addr_le_t _discovering_ble_addresses; bool _start_discover; + bool _discover_gap_gatt; bool _discovering; uint64_t _discover_rsp_timestamp; diff --git a/libraries/CurieBLE/src/internal/BLEServiceImp.cpp b/libraries/CurieBLE/src/internal/BLEServiceImp.cpp index d5d7afe6..621ded0b 100644 --- a/libraries/CurieBLE/src/internal/BLEServiceImp.cpp +++ b/libraries/CurieBLE/src/internal/BLEServiceImp.cpp @@ -38,7 +38,8 @@ BLEServiceImp::BLEServiceImp(BLEService& service): _start_handle(0), _end_handle(0xFFFF), _reading(false), - _cur_discover_chrc(NULL) + _cur_discover_chrc(NULL), + _discovering(false) { memset(&_characteristics_header, 0, sizeof(_characteristics_header)); service.setServiceImp(this); @@ -49,7 +50,8 @@ BLEServiceImp::BLEServiceImp(const bt_uuid_t* uuid): _start_handle(0), _end_handle(0xFFFF), _reading(false), - _cur_discover_chrc(NULL) + _cur_discover_chrc(NULL), + _discovering(false) { memset(&_characteristics_header, 0, sizeof(_characteristics_header)); } @@ -120,6 +122,7 @@ int BLEServiceImp::updateProfile(bt_gatt_attr_t *attr_start, int& index) int base_index = index; int offset = 0; int counter = 0; + int ret = 0; start->uuid = BLEServiceImp::getPrimayUuid(); start->perm = BT_GATT_PERM_READ; start->read = bt_gatt_attr_read_service; @@ -139,7 +142,10 @@ int BLEServiceImp::updateProfile(bt_gatt_attr_t *attr_start, int& index) counter += offset; node = node->next; } - return counter; + ret = bt_gatt_register(attr_start, + counter); + + return errorno_to_ble_status(ret); } int BLEServiceImp::getAttributeCount() @@ -165,7 +171,7 @@ int BLEServiceImp::getCharacteristicCount() void BLEServiceImp::releaseCharacteristic() { BLECharacteristicNodePtr node = link_node_get_first(&_characteristics_header); - pr_debug(LOG_MODULE_BLE, "%s-%d", __FUNCTION__, __LINE__); + //pr_debug(LOG_MODULE_BLE, "%s-%d", __FUNCTION__, __LINE__); while (NULL != node) { BLECharacteristicImp* characteristicImp = node->value; @@ -173,7 +179,7 @@ void BLEServiceImp::releaseCharacteristic() link_node_remove_first(&_characteristics_header); node = link_node_get_first(&_characteristics_header); } - pr_debug(LOG_MODULE_BLE, "%s-%d", __FUNCTION__, __LINE__); + //pr_debug(LOG_MODULE_BLE, "%s-%d", __FUNCTION__, __LINE__); } @@ -268,17 +274,29 @@ BLECharacteristicImp* BLEServiceImp::characteristic(const char* uuid) bool BLEServiceImp::discovering() { - return (_cur_discover_chrc != NULL || _reading); + return (_cur_discover_chrc != NULL || + _reading || + _discovering); } -bool BLEServiceImp::discoverAttributes(BLEDevice* device) +void BLEServiceImp::setDiscovering(bool enable) { - return discoverAttributes(device, _start_handle, _end_handle); + _discovering = enable; +} + +bool BLEServiceImp::discoverAttributes(BLEDevice* device, + bool discoverGapGatt) +{ + return discoverAttributes(device, + _start_handle, + _end_handle, + discoverGapGatt); } bool BLEServiceImp::discoverAttributes(BLEDevice* device, uint16_t start_handle, - uint16_t end_handle) + uint16_t end_handle, + bool discoverGapGatt) { pr_debug(LOG_MODULE_BLE, "%s-%d", __FUNCTION__, __LINE__); int err; @@ -286,9 +304,11 @@ bool BLEServiceImp::discoverAttributes(BLEDevice* device, bt_gatt_discover_params_t* temp = NULL; const bt_uuid_t* service_uuid = bt_uuid(); - if (service_uuid->type == BT_UUID_TYPE_16) + // Filt out GAP/GATT service + if (discoverGapGatt == false && // Don't discover GAP and GATT service + service_uuid->type == BT_UUID_TYPE_16) { - uint16_t uuid_tmp;// = ((bt_uuid_16_t*)service_uuid)->val; + uint16_t uuid_tmp; memcpy(&uuid_tmp, &((bt_uuid_16_t*)service_uuid)->val, sizeof(uuid_tmp)); if (BT_UUID_GAP_VAL == uuid_tmp || @@ -305,6 +325,7 @@ bool BLEServiceImp::discoverAttributes(BLEDevice* device, pr_debug(LOG_MODULE_BLE, "Can't find connection\n"); return false; } + temp = &_discover_params; temp->start_handle = start_handle; temp->end_handle = end_handle; @@ -319,6 +340,7 @@ bool BLEServiceImp::discoverAttributes(BLEDevice* device, pr_debug(LOG_MODULE_BLE, "Discover failed(err %d)\n", err); return false; } + setDiscovering(true); return true; } @@ -337,6 +359,7 @@ uint8_t BLEServiceImp::discoverResponseProc(bt_conn_t *conn, { case BT_GATT_DISCOVER_CHARACTERISTIC: { + setDiscovering(false); if (NULL != attr) { //const bt_uuid_t* chrc_uuid = attr->uuid; @@ -351,7 +374,7 @@ uint8_t BLEServiceImp::discoverResponseProc(bt_conn_t *conn, { // Read the UUID readCharacteristic(device, chrc_handle); - retVal = BT_GATT_ITER_CONTINUE; + //retVal = BT_GATT_ITER_CONTINUE; } else { @@ -375,9 +398,7 @@ uint8_t BLEServiceImp::discoverResponseProc(bt_conn_t *conn, break; } case BT_GATT_DISCOVER_DESCRIPTOR: - { - // - + { if (NULL != _cur_discover_chrc) { retVal = _cur_discover_chrc->discoverResponseProc(conn, @@ -416,7 +437,6 @@ void BLEServiceImp::discoverNextCharacteristic(BLEDevice &bledevice) BLECharacteristicImp* chrcCurImp = NULL; BLECharacteristicNodePtr node = chrcHeader->next; - //pr_debug(LOG_MODULE_BLE, "%s-%d: node-%p",__FUNCTION__, __LINE__, node); // Discover next service while (node != NULL) { @@ -425,7 +445,6 @@ void BLEServiceImp::discoverNextCharacteristic(BLEDevice &bledevice) if (NULL == _cur_discover_chrc) { bool result = chrcCurImp->discoverAttributes(&bledevice); - pr_debug(LOG_MODULE_BLE, "%s-%d",__FUNCTION__, __LINE__); if (result == true) { // Record the current discovering service @@ -521,7 +540,10 @@ uint8_t BLEServiceImp::characteristicReadRspProc(bt_conn_t *conn, { if (false == discovering()) { - if (false == discoverAttributes(&bleDevice, chrc_handle + 1, _end_handle)) + if (false == discoverAttributes(&bleDevice, + chrc_handle + 1, + _end_handle, + true)) { discoverNextCharacteristic(bleDevice); } diff --git a/libraries/CurieBLE/src/internal/BLEServiceImp.h b/libraries/CurieBLE/src/internal/BLEServiceImp.h index f40ffd36..7ce7e804 100644 --- a/libraries/CurieBLE/src/internal/BLEServiceImp.h +++ b/libraries/CurieBLE/src/internal/BLEServiceImp.h @@ -69,7 +69,8 @@ class BLEServiceImp: public BLEAttribute{ inline uint16_t endHandle(){return _end_handle;} inline uint16_t startHandle(){return _start_handle;} - bool discoverAttributes(BLEDevice* device); + bool discoverAttributes(BLEDevice* device, + bool discoverGapGatt); uint8_t discoverResponseProc(bt_conn_t *conn, const bt_gatt_attr_t *attr, bt_gatt_discover_params_t *params); @@ -95,7 +96,9 @@ class BLEServiceImp: public BLEAttribute{ bool readCharacteristic(const BLEDevice &bledevice, uint16_t handle); bool discoverAttributes(BLEDevice* device, uint16_t start_handle, - uint16_t end_handle); + uint16_t end_handle, + bool discoverGapGatt); + void setDiscovering(bool enable); private: typedef LinkNode BLECharacteristicLinkNodeHeader; typedef LinkNode* BLECharacteristicNodePtr; @@ -114,6 +117,7 @@ class BLEServiceImp: public BLEAttribute{ bt_gatt_discover_params_t _discover_params; BLECharacteristicLinkNodeHeader _characteristics_header; // The characteristic link list + bool _discovering; }; #endif // _BLE_SERVICE_H_INCLUDED diff --git a/libraries/CurieBLE/src/internal/BLEUtils.cpp b/libraries/CurieBLE/src/internal/BLEUtils.cpp index 0142db07..85d12f96 100644 --- a/libraries/CurieBLE/src/internal/BLEUtils.cpp +++ b/libraries/CurieBLE/src/internal/BLEUtils.cpp @@ -26,8 +26,8 @@ String BLEUtils::macAddressBT2String(const bt_addr_le_t &bd_addr) { char mac_string[BT_ADDR_STR_LEN]; snprintf(mac_string, BT_ADDR_STR_LEN, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", - bd_addr.val[5], bd_addr.val[4], bd_addr.val[3], - bd_addr.val[2], bd_addr.val[1], bd_addr.val[0]); + bd_addr.a.val[5], bd_addr.a.val[4], bd_addr.a.val[3], + bd_addr.a.val[2], bd_addr.a.val[1], bd_addr.a.val[0]); String temp(mac_string); return temp; } @@ -51,7 +51,7 @@ void BLEUtils::macAddressString2BT(const char* mac_str, bt_addr_le_t &bd_addr) temp[0] = mac_str[i - 1]; temp[1] = mac_str[i]; - bd_addr.val[length] = strtoul(temp, NULL, 16); + bd_addr.a.val[length] = strtoul(temp, NULL, 16); length++; } @@ -65,7 +65,7 @@ bool BLEUtils::macAddressSame(const bt_addr_le_t &bd_addr1, #if 1 for (int i = 0; i < 6; i++) { - if (bd_addr1.val[i] != bd_addr2.val[i]) + if (bd_addr1.a.val[i] != bd_addr2.a.val[i]) { temp = false; break; @@ -85,7 +85,7 @@ bool BLEUtils::macAddressValid(const bt_addr_le_t &bd_addr) #else for (int i = 0; i < 6; i++) { - if (bd_addr.val[i] != 0) + if (bd_addr.a.val[i] != 0) { //pr_info(LOG_MODULE_BLE, "%s-idx %d-%.2x:%.2x", __FUNCTION__, i ,bd_addr.val[i], zero.val[i]); //pr_info(LOG_MODULE_BLE,"%s",BLEUtils::macAddressBT2String(zero).c_str()); @@ -100,7 +100,7 @@ bool BLEUtils::macAddressValid(const bt_addr_le_t &bd_addr) bt_addr_le_t* BLEUtils::bleGetLoalAddress() { - static bt_addr_le_t board_addr; + static bt_addr_le_t board_addr = {0, {0, 0, 0, 0, 0, 0}}; if (false == macAddressValid(board_addr)) ble_client_get_mac_address(&board_addr); return &board_addr; diff --git a/libraries/CurieBLE/src/internal/BLEUtils.h b/libraries/CurieBLE/src/internal/BLEUtils.h index e756843a..69f28319 100644 --- a/libraries/CurieBLE/src/internal/BLEUtils.h +++ b/libraries/CurieBLE/src/internal/BLEUtils.h @@ -32,5 +32,9 @@ namespace BLEUtils BLEDevice& getLoacalBleDevice(); bool isLocalBLE(const BLEDevice& device); + inline uint64_t getElapsedMillSeconds(uint64_t startMillSecond) + { + return (millis() - startMillSecond); + } } diff --git a/libraries/CurieBLE/src/internal/ble_client.c b/libraries/CurieBLE/src/internal/ble_client.c index 5a9e6164..7b4f0c61 100644 --- a/libraries/CurieBLE/src/internal/ble_client.c +++ b/libraries/CurieBLE/src/internal/ble_client.c @@ -42,6 +42,7 @@ #include "infra/version.h" #include "curie_factory_data.h" #include "portable.h" +#include "services/ble/ble_service.h" #include "uart.h" #include "ipc_uart_ns16550.h" @@ -112,10 +113,16 @@ static struct bt_conn_cb conn_callbacks = { .le_param_updated = on_le_param_updated }; +static void ble_fill_le_address_from_oem(bt_addr_le_t *bda, + const struct curie_oem_data *oem) +{ + bda->type = oem->bt_mac_address_type; + memcpy(&bda->a, oem->bt_address, sizeof(bda->a)); // GL. KW warning acknowldged +} + void ble_client_get_mac_address(bt_addr_le_t *bda) { struct curie_oem_data *p_oem = NULL; - unsigned i; /* Set the MAC address defined in Factory Data (if provided) * Otherwise, the device will default to a static random address */ @@ -124,9 +131,7 @@ void ble_client_get_mac_address(bt_addr_le_t *bda) if (!strncmp((char*)global_factory_data->oem_data.magic, FACTORY_DATA_MAGIC, 4)) { p_oem = (struct curie_oem_data *) &global_factory_data->oem_data.project_data; if (p_oem->bt_mac_address_type < 2) { - bda->type = p_oem->bt_mac_address_type; - for (i = 0; i < BLE_ADDR_LEN; i++) - bda->val[i] = p_oem->bt_address[BLE_ADDR_LEN - 1 - i]; + ble_fill_le_address_from_oem(bda, p_oem); } } } @@ -189,7 +194,9 @@ void ble_client_init(ble_client_connect_event_cb_t connect_cb, void* connect_par ble_client_disconnect_event_cb_t disconnect_cb, void* disconnect_param, ble_client_update_param_event_cb_t update_param_cb, void* update_param_param) { - //uint32_t delay_until; + // Enable the HW + ble_enable(); + pr_info(LOG_MODULE_BLE, "%s", __FUNCTION__); ble_client_connect_event_cb = connect_cb; ble_client_connect_event_param = connect_param; diff --git a/system/libarc32_arduino101/common/misc/slist.h b/system/libarc32_arduino101/common/misc/slist.h new file mode 100644 index 00000000..00248713 --- /dev/null +++ b/system/libarc32_arduino101/common/misc/slist.h @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * + * @brief Header where single linked list utility code is found + */ + +#ifndef __SLIST_H__ +#define __SLIST_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +struct _snode { + struct _snode *next; +}; + +typedef struct _snode sys_snode_t; + +struct _slist { + sys_snode_t *head; + sys_snode_t *tail; +}; + +typedef struct _slist sys_slist_t; + +/** + * @brief Provide the primitive to iterate on a list + * Note: the loop is unsafe and thus __sn should not be removed + * + * User _MUST_ add the loop statement curly braces enclosing its own code: + * + * SYS_SLIST_FOR_EACH_NODE(l, n) { + * + * } + * + * @param __sl A pointer on a sys_list_t to iterate on + * @param __sn A sys_snode_t pointer to peek each node of the list + */ +#define SYS_SLIST_FOR_EACH_NODE(__sl, __sn) \ + for (__sn = sys_slist_peek_head(__sl); __sn; \ + __sn = sys_slist_peek_next(__sn)) + +/** + * @brief Provide the primitive to safely iterate on a list + * Note: __sn can be removed, it will not break the loop. + * + * User _MUST_ add the loop statement curly braces enclosing its own code: + * + * SYS_SLIST_FOR_EACH_NODE_SAFE(l, n, s) { + * + * } + * + * @param __sl A pointer on a sys_list_t to iterate on + * @param __sn A sys_snode_t pointer to peek each node of the list + * @param __sns A sys_snode_t pointer for the loop to run safely + */ +#define SYS_SLIST_FOR_EACH_NODE_SAFE(__sl, __sn, __sns) \ + for (__sn = sys_slist_peek_head(__sl), \ + __sns = sys_slist_peek_next(__sn); \ + __sn; __sn = __sns, \ + __sns = sys_slist_peek_next(__sn)) + +/** + * @brief Initialize a list + * + * @param list A pointer on the list to initialize + */ +static inline void sys_slist_init(sys_slist_t *list) +{ + list->head = NULL; + list->tail = NULL; +} + +/** + * @brief Test if the given list is empty + * + * @param list A pointer on the list to test + * + * @return a boolean, true if it's empty, false otherwise + */ +static inline bool sys_slist_is_empty(sys_slist_t *list) +{ + return (!list->head); +} + +/** + * @brief Peek the first node from the list + * + * @param list A point on the list to peek the first node from + * + * @return A pointer on the first node of the list (or NULL if none) + */ +static inline sys_snode_t *sys_slist_peek_head(sys_slist_t *list) +{ + return list->head; +} + +/** + * @brief Peek the last node from the list + * + * @param list A point on the list to peek the last node from + * + * @return A pointer on the last node of the list (or NULL if none) + */ +static inline sys_snode_t *sys_slist_peek_tail(sys_slist_t *list) +{ + return list->tail; +} + +/** + * @brief Peek the next node from current node + * + * @param node A pointer on the node where to peek the next node + * + * @return a pointer on the next node (or NULL if none) + */ +static inline sys_snode_t *sys_slist_peek_next(sys_snode_t *node) +{ + return !node ? NULL : node->next; +} + +/** + * @brief Prepend a node to the given list + * + * @param list A pointer on the list to affect + * @param node A pointer on the node to prepend + */ +static inline void sys_slist_prepend(sys_slist_t *list, + sys_snode_t *node) +{ + node->next = list->head; + list->head = node; + + if (!list->tail) { + list->tail = list->head; + } +} + +/** + * @brief Append a node to the given list + * + * @param list A pointer on the list to affect + * @param node A pointer on the node to append + */ +static inline void sys_slist_append(sys_slist_t *list, + sys_snode_t *node) +{ + node->next = NULL; + + if (!list->tail) { + list->tail = node; + list->head = node; + } else { + list->tail->next = node; + list->tail = node; + } +} + +/** + * @brief Insert a node to the given list + * + * @param list A pointer on the list to affect + * @param prev A pointer on the previous node + * @param node A pointer on the node to insert + */ +static inline void sys_slist_insert(sys_slist_t *list, + sys_snode_t *prev, + sys_snode_t *node) +{ + if (!prev) { + sys_slist_prepend(list, node); + } else if (!prev->next) { + sys_slist_append(list, node); + } else { + node->next = prev->next; + prev->next = node; + } +} + +/** + * @brief Remove a node + * + * @param list A pointer on the list to affect + * @param prev_node A pointer on the previous node + * (can be NULL, which means the node is the list's head) + * @param node A pointer on the node to remove + */ +static inline void sys_slist_remove(sys_slist_t *list, + sys_snode_t *prev_node, + sys_snode_t *node) +{ + if (!prev_node) { + list->head = node->next; + + /* Was node also the tail? */ + if (list->tail == node) { + list->tail = list->head; + } + } else { + prev_node->next = node->next; + + /* Was node the tail? */ + if (list->tail == node) { + list->tail = prev_node; + } + } + + node->next = NULL; +} + +/** + * @brief Find and remove a node from a list + * + * @param list A pointer on the list to affect + * @param node A pointer on the node to remove from the list + */ +static inline void sys_slist_find_and_remove(sys_slist_t *list, + sys_snode_t *node) +{ + sys_snode_t *prev = NULL; + sys_snode_t *test; + + SYS_SLIST_FOR_EACH_NODE(list, test) { + if (test == node) { + sys_slist_remove(list, prev, node); + break; + } + + prev = test; + } +} + + +#ifdef __cplusplus +} +#endif + +#endif /* __SLIST_H__ */ diff --git a/system/libarc32_arduino101/common/misc/util.h b/system/libarc32_arduino101/common/misc/util.h index ab45bbb1..974f92d3 100644 --- a/system/libarc32_arduino101/common/misc/util.h +++ b/system/libarc32_arduino101/common/misc/util.h @@ -101,6 +101,7 @@ static inline int _IsPowerOfTwo(unsigned int x) #define MHZ(x) (KHZ(x) * 1000) #define _BV(bit) (1U << (bit)) +#define BIT(n) (1UL << (n)) #ifdef __cplusplus } diff --git a/system/libarc32_arduino101/drivers/bluetooth/bluetooth.h b/system/libarc32_arduino101/drivers/bluetooth/bluetooth.h index faf03b2f..5a091e1a 100644 --- a/system/libarc32_arduino101/drivers/bluetooth/bluetooth.h +++ b/system/libarc32_arduino101/drivers/bluetooth/bluetooth.h @@ -24,6 +24,7 @@ #include #include +#include #include #ifdef __cplusplus @@ -88,25 +89,18 @@ struct bt_data { BT_DATA(_type, ((uint8_t []) { _bytes }), \ sizeof((uint8_t []) { _bytes })) -/** Local advertising address type */ +/** Advertising options */ enum { - /** Use local identity address for advertising. Unless a static - * random address has been configured this will be the public - * address. - */ - BT_LE_ADV_ADDR_IDENTITY, - - /** Use local Non-resolvable Private Address (NRPA) for advertising */ - BT_LE_ADV_ADDR_NRPA, + /** Advertise as connectable. Type of advertising is determined by + * providing SCAN_RSP data and/or enabling local privacy support. + */ + BT_LE_ADV_OPT_CONNECTABLE = BIT(0), }; /** LE Advertising Parameters. */ struct bt_le_adv_param { - /** Advertising type */ - uint8_t type; - - /** Which type of own address to use for advertising */ - uint8_t addr_type; + /** Bit-field of advertising options */ + uint8_t options; /** Minimum Advertising Interval (N * 0.625) */ uint16_t interval_min; @@ -117,22 +111,23 @@ struct bt_le_adv_param { /** Helper to declare advertising parameters inline * - * @param _type Advertising Type - * @param _addr_type Local address type to use for advertising + * @param _options Advertising Options * @param _int_min Minimum advertising interval * @param _int_max Maximum advertising interval */ -#define BT_LE_ADV_PARAM(_type, _addr_type, _int_min, _int_max) \ +#define BT_LE_ADV_PARAM(_options, _int_min, _int_max) \ (&(struct bt_le_adv_param) { \ - .type = (_type), \ - .addr_type = (_addr_type), \ + .options = (_options), \ .interval_min = (_int_min), \ .interval_max = (_int_max), \ }) -#define BT_LE_ADV(t) BT_LE_ADV_PARAM(t, BT_LE_ADV_ADDR_IDENTITY, \ - BT_GAP_ADV_FAST_INT_MIN_2, \ - BT_GAP_ADV_FAST_INT_MAX_2) +#define BT_LE_ADV_CONN BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE, \ + BT_GAP_ADV_FAST_INT_MIN_2, \ + BT_GAP_ADV_FAST_INT_MAX_2) + +#define BT_LE_ADV_NCONN BT_LE_ADV_PARAM(0, BT_GAP_ADV_FAST_INT_MIN_2, \ + BT_GAP_ADV_FAST_INT_MAX_2) /** @brief Start advertising * @@ -247,6 +242,92 @@ int bt_le_scan_start(const struct bt_le_scan_param *param, bt_le_scan_cb_t cb); */ int bt_le_scan_stop(void); +struct bt_le_oob { + /** LE address. If local privacy is enabled this is Resolvable Private + * Address. + */ + bt_addr_le_t addr; +}; + +/** + * @brief Get LE local Out Of Band information + * + * This function allows to get local information that are useful for Out Of Band + * pairing or connection creation process. + * + * If privacy is enabled this will result in generating new Resolvable Private + * Address that is valid for CONFIG_BLUETOOTH_RPA_TIMEOUT seconds. This address + * will be used for advertising, active scanning and connection creation. + * + * @param oob LE related information + */ +int bt_le_oob_get_local(struct bt_le_oob *oob); + +/** @brief BR/EDR discovery result structure */ +struct bt_br_discovery_result { + /** private */ + + uint8_t private_b[4]; + + /** Remote device address */ + bt_addr_t addr; + + /** RSSI from inquiry */ + int8_t rssi; + + /** Class of Device */ + uint8_t cod[3]; + + /** Extended Inquiry Response */ + uint8_t eir[240]; +}; + +/** @brief Define a type allowing user to implement a function that can + * be used to get back BR/EDR discovery (inquiry) results. + * + * A function of this type will be called back when user application + * triggers BR/EDR discovery and discovery process completes. + * + * @param results Storage used for discovery results + * @param count Number of valid discovery results. + */ +typedef void bt_br_discovery_cb_t(struct bt_br_discovery_result *results, + size_t count); + +/** BR/EDR discovery parameters */ +struct bt_br_discovery_param { + /** True if limited discovery procedure is to be used. */ + bool limited_discovery; +}; + +/** @brief Start BR/EDR discovery + * + * Start BR/EDR discovery (inquiry) and provide results through the specified + * callback. When bt_br_discovery_cb_t is called it indicates that discovery + * has completed. + * + * @param param Discovery parameters. + * @param results Storage for discovery results. + * @param count Number of results in storage + * @param cb Callback to notify discovery results. + * + * @return Zero on success or error code otherwise, positive in case + * of protocol error or negative (POSIX) in case of stack internal error + */ +int bt_br_discovery_start(const struct bt_br_discovery_param *param, + struct bt_br_discovery_result *results, size_t count, + bt_br_discovery_cb_t cb); + +/** @brief Stop BR/EDR discovery. + * + * Stops ongoing BR/EDR discovery. If discovery was stopped by this call + * results won't be reported + * + * @return Zero on success or error code otherwise, positive in case + * of protocol error or negative (POSIX) in case of stack internal error + */ +int bt_br_discovery_stop(void); + /** @def BT_ADDR_STR_LEN * * @brief Recommended length of user string buffer for Bluetooth address @@ -312,8 +393,8 @@ static inline int bt_addr_le_to_str(const bt_addr_le_t *addr, char *str, } return snprintf(str, len, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X (%s)", - addr->val[5], addr->val[4], addr->val[3], - addr->val[2], addr->val[1], addr->val[0], type); + addr->a.val[5], addr->a.val[4], addr->a.val[3], + addr->a.val[2], addr->a.val[1], addr->a.val[0], type); } #if defined(CONFIG_BLUETOOTH_BREDR) diff --git a/system/libarc32_arduino101/drivers/bluetooth/conn.h b/system/libarc32_arduino101/drivers/bluetooth/conn.h index 1b710d6f..a4cf9a9d 100644 --- a/system/libarc32_arduino101/drivers/bluetooth/conn.h +++ b/system/libarc32_arduino101/drivers/bluetooth/conn.h @@ -20,6 +20,13 @@ #ifndef __BT_CONN_H #define __BT_CONN_H +/** + * @brief Connection management + * @defgroup bt_conn Connection management + * @ingroup bluetooth + * @{ + */ + #ifdef __cplusplus extern "C" { #endif @@ -246,7 +253,7 @@ typedef enum __packed { */ } bt_security_t; -#if defined(CONFIG_BLUETOOTH_SMP) +#if defined(CONFIG_BLUETOOTH_SMP) || defined(CONFIG_BLUETOOTH_BREDR) /** @brief Set security level for a connection. * * This function enable security (encryption) for a connection. If device is @@ -279,20 +286,7 @@ int bt_conn_security(struct bt_conn *conn, bt_security_t sec); * @return Encryption key size. */ uint8_t bt_conn_enc_key_size(struct bt_conn *conn); - -/** @brief Clear device information (bonding, keys). - * - * Clears all a bonding information (keys, etc). A bonded connection is - * disconnected. - * BT_ADDR_LE_ANY removes the of all bonded devices - * - * @param addr identity address of a bonded device - * - * @return 0 in success, error code otherwise - * - */ -int bt_conn_remove_info(const bt_addr_le_t *addr); -#endif /* CONFIG_BLUETOOTH_SMP */ +#endif /* CONFIG_BLUETOOTH_SMP || CONFIG_BLUETOOTH_BREDR */ /** Connection callback structure */ struct bt_conn_cb { @@ -304,8 +298,10 @@ struct bt_conn_cb { void (*identity_resolved)(struct bt_conn *conn, const bt_addr_le_t *rpa, const bt_addr_le_t *identity); +#endif /* CONFIG_BLUETOOTH_SMP */ +#if defined(CONFIG_BLUETOOTH_SMP) || defined(CONFIG_BLUETOOTH_BREDR) void (*security_changed)(struct bt_conn *conn, bt_security_t level); -#endif +#endif /* defined(CONFIG_BLUETOOTH_SMP) || defined(CONFIG_BLUETOOTH_BREDR) */ struct bt_conn_cb *_next; }; @@ -326,6 +322,7 @@ struct bt_conn_auth_cb { void (*passkey_entry)(struct bt_conn *conn); void (*passkey_confirm)(struct bt_conn *conn, unsigned int passkey); void (*cancel)(struct bt_conn *conn); + void (*pairing_confirm)(struct bt_conn *conn); #if defined(CONFIG_BLUETOOTH_BREDR) void (*pincode_entry)(struct bt_conn *conn, bool highsec); #endif @@ -364,18 +361,27 @@ int bt_conn_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey); */ int bt_conn_auth_cancel(struct bt_conn *conn); -/** @brief Reply if passkey was confirmed by user. +/** @brief Reply if passkey was confirmed to match by user. * * This function should be called only after passkey_confirm callback from - * bt_conn_auth_cb structure was called. If passkey is confirmed to match - * then match should be true. Otherwise match should be false. + * bt_conn_auth_cb structure was called. + * + * @param conn Connection object. + * + * @return Zero on success or negative error code otherwise + */ +int bt_conn_auth_passkey_confirm(struct bt_conn *conn); + +/** @brief Reply if incoming pairing was confirmed by user. + * + * This function should be called only after pairing_confirm callback from + * bt_conn_auth_cb structure was called if user confirmed incoming pairing. * * @param conn Connection object. - * @param match True if passkey was confirmed to match, false otherwise. * * @return Zero on success or negative error code otherwise */ -int bt_conn_auth_passkey_confirm(struct bt_conn *conn, bool match); +int bt_conn_auth_pairing_confirm(struct bt_conn *conn); #if defined(CONFIG_BLUETOOTH_BREDR) /** @brief Reply with entered PIN code. @@ -392,8 +398,47 @@ int bt_conn_auth_pincode_entry(struct bt_conn *conn, const char *pin); #endif /* CONFIG_BLUETOOTH_BREDR */ #endif /* CONFIG_BLUETOOTH_SMP || CONFIG_BLUETOOTH_BREDR */ +#if defined(CONFIG_BLUETOOTH_BREDR) +/** Connection parameters for BR/EDR connections */ +struct bt_br_conn_param { + bool allow_role_switch; +}; + +/** Helper to declare BR/EDR connection parameters inline + * + * @param role_switch True if role switch is allowed + */ +#define BT_BR_CONN_PARAM(role_switch) \ + (&(struct bt_br_conn_param) { \ + .allow_role_switch = (role_switch), \ + }) + +/** Default BR/EDR connection parameters: + * Role switch allowed + */ +#define BT_BR_CONN_PARAM_DEFAULT BT_BR_CONN_PARAM(true) + + +/** @brief Initiate an BR/EDR connection to a remote device. + * + * Allows initiate new BR/EDR link to remote peer using its address. + * Returns a new reference that the the caller is responsible for managing. + * + * @param peer Remote address. + * @param param Initial connection parameters. + * + * @return Valid connection object on success or NULL otherwise. + */ +struct bt_conn *bt_conn_create_br(const bt_addr_t *peer, + const struct bt_br_conn_param *param); +#endif /* CONFIG_BLUETOOTH_BREDR */ + #ifdef __cplusplus } #endif +/** + * @} + */ + #endif /* __BT_CONN_H */ diff --git a/system/libarc32_arduino101/drivers/bluetooth/dtm.h b/system/libarc32_arduino101/drivers/bluetooth/dtm.h new file mode 100644 index 00000000..b7a72002 --- /dev/null +++ b/system/libarc32_arduino101/drivers/bluetooth/dtm.h @@ -0,0 +1,77 @@ +/* + * INTEL CONFIDENTIAL + * + * Copyright (c) 2016, Intel Corporation. All rights reserved. + * + * The source code contained or described herein and all documents related to + * the source code ("Material") are owned by Intel Corporation or its suppliers + * or licensors. + * Title to the Material remains with Intel Corporation or its suppliers and + * licensors. + * The Material contains trade secrets and proprietary and confidential + * information of Intel or its suppliers and licensors. The Material is + * protected by worldwide copyright and trade secret laws and treaty provisions. + * No part of the Material may be used, copied, reproduced, modified, published, + * uploaded, posted, transmitted, distributed, or disclosed in any way without + * Intel's prior express written permission. + * + * No license under any patent, copyright, trade secret or other intellectual + * property right is granted to or conferred upon you by disclosure or delivery + * of the Materials, either expressly, by implication, inducement, estoppel or + * otherwise. + * + * Any license under such intellectual property rights must be express and + * approved by Intel in writing + */ + +#ifndef DTM_H_ +#define DTM_H_ + +#include + +struct dtm_cmd_params; + +struct ble_dtm_rsp { + int status; + uint16_t nb; +}; + +typedef void (*dtm_rsp_func_t)(struct ble_dtm_rsp *rsp, + void *user_data); + +enum { + DTM_START_RX = 0, + DTM_START_TX, + DTM_SET_TXPOWER, + DTM_START_TX_CARRIER, + DTM_END, +}; + +struct dtm_rx_cmd { + uint8_t freq; +}; + +struct dtm_tx_cmd { + uint8_t freq; + uint8_t len; + uint8_t pattern; +}; + +struct dtm_set_txpower_cmd { + int8_t dbm; +}; + +struct dtm_cmd_params { + uint8_t cmd_type; + union { + struct dtm_rx_cmd rx; + struct dtm_tx_cmd tx; + struct dtm_set_txpower_cmd tx_pwr; + }; + dtm_rsp_func_t func; + void *user_data; +}; + +int ble_dtm_cmd(struct dtm_cmd_params *params); + +#endif diff --git a/system/libarc32_arduino101/drivers/bluetooth/gatt.h b/system/libarc32_arduino101/drivers/bluetooth/gatt.h index e9eac613..b5a05cb1 100644 --- a/system/libarc32_arduino101/drivers/bluetooth/gatt.h +++ b/system/libarc32_arduino101/drivers/bluetooth/gatt.h @@ -20,6 +20,13 @@ #ifndef __BT_GATT_H #define __BT_GATT_H +/** + * @brief Generic Attribute Profile (GATT) + * @defgroup bt_gatt Generic Attribute Profile (GATT) + * @ingroup bluetooth + * @{ + */ + #ifdef __cplusplus extern "C" { #endif @@ -28,6 +35,7 @@ extern "C" { #include #include #include +#include #include #include #include @@ -66,18 +74,13 @@ extern "C" { * If set, requires encryption using authenticated link-key for write access. */ #define BT_GATT_PERM_WRITE_AUTHEN 0x20 -/** @def BT_GATT_PERM_READ_AUTHOR - * @brief Attribute read permission with authorization. - * - * If set, requires authorization for read access. - */ -#define BT_GATT_PERM_READ_AUTHOR 0x40 -/** @def BT_GATT_PERM_WRITE_AUTHOR - * @brief Attribute write permission with authorization. +/** @def BT_GATT_PERM_PREPARE_WRITE + * @brief Attribute prepare write permission. * - * If set, requires authorization for write access. + * If set, allows prepare writes with use of BT_GATT_WRITE_FLAG_PREPARE + * passed to write callback. */ -#define BT_GATT_PERM_WRITE_AUTHOR 0x80 +#define BT_GATT_PERM_PREPARE_WRITE 0x40 /* GATT attribute flush flags */ /** @def BT_GATT_FLUSH_DISCARD @@ -100,6 +103,14 @@ extern "C" { */ #define BT_GATT_ERR(_att_err) (-(_att_err)) +/** @def BT_GATT_WRITE_FLAG_PREPARE + * @brif Attribute prepare write flag + * + * If set, write callback should only check if the device is + * authorized but no data shall be written. + */ +#define BT_GATT_WRITE_FLAG_PREPARE 0x01 + /** @brief GATT Attribute structure. */ struct bt_gatt_attr { /** Attribute UUID */ @@ -135,7 +146,7 @@ struct bt_gatt_attr { ssize_t (*write)(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, uint16_t len, - uint16_t offset); + uint16_t offset, uint8_t flags); /** Attribute flush callback * @@ -151,9 +162,11 @@ struct bt_gatt_attr { * @return Number of bytes flushed, or in case of an error * BT_GATT_ERR() with a specific ATT error code. */ +#ifdef CONFIG_BLUETOOTH_STACK_HCI ssize_t (*flush)(struct bt_conn *conn, const struct bt_gatt_attr *attr, uint8_t flags); +#endif /** Attribute user data */ void *user_data; @@ -450,16 +463,16 @@ ssize_t bt_gatt_attr_read_included(struct bt_conn *conn, /** @def BT_GATT_INCLUDE_SERVICE * @brief Include Service Declaration Macro. * - * Helper macro to declare a include service attribute. + * Helper macro to declare database internal include service attribute. * - * @param _service Service attribute value. + * @param _service_incl, the first service attribute of service to include */ -#define BT_GATT_INCLUDE_SERVICE(_service) \ +#define BT_GATT_INCLUDE_SERVICE(_service_incl) \ { \ .uuid = BT_UUID_GATT_INCLUDE, \ .perm = BT_GATT_PERM_READ, \ .read = bt_gatt_attr_read_included, \ - .user_data = _service, \ + .user_data = _service_incl, \ } /** @brief Read Characteristic Attribute helper. @@ -513,7 +526,8 @@ struct _bt_gatt_ccc { struct bt_gatt_ccc_cfg *cfg; size_t cfg_len; uint16_t value; - void (*cfg_changed)(uint16_t value); + void *user_data; + void (*cfg_changed)(void *user_data, uint16_t value); }; /** @brief Read Client Characteristic Configuration Attribute helper. @@ -551,7 +565,7 @@ ssize_t bt_gatt_attr_read_ccc(struct bt_conn *conn, */ ssize_t bt_gatt_attr_write_ccc(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, - uint16_t len, uint16_t offset); + uint16_t len, uint16_t offset, uint8_t flags); /** @def BT_GATT_CCC * @brief Client Characteristic Configuration Declaration Macro. @@ -751,11 +765,11 @@ int bt_gatt_notify(struct bt_conn *conn, const struct bt_gatt_attr *attr, * * @param conn Connection object. * @param attr Attribute object. - * @param err: 0 success, error in the other case + * @param err ATT error code */ typedef void (*bt_gatt_indicate_func_t)(struct bt_conn *conn, const struct bt_gatt_attr *attr, - int err); + uint8_t err); /** @brief GATT Indicate Value parameters */ struct bt_gatt_indicate_params { @@ -792,9 +806,10 @@ int bt_gatt_indicate(struct bt_conn *conn, /** @brief Response callback function * * @param conn Connection object. - * @param err Error code. + * @param err ATT error code. */ -typedef void (*bt_gatt_rsp_func_t)(struct bt_conn *conn, uint8_t err); +typedef void (*bt_gatt_rsp_func_t)(struct bt_conn *conn, uint8_t err, + const void *data); /** @brief Exchange MTU * @@ -881,12 +896,12 @@ struct bt_gatt_read_params; /** @brief Read callback function * * @param conn Connection object. - * @param err Error code. + * @param err ATT error code. * @param params Read parameters used. * @param data Attribute value data. NULL means read has completed. * @param length Attribute value length. */ -typedef uint8_t (*bt_gatt_read_func_t)(struct bt_conn *conn, int err, +typedef uint8_t (*bt_gatt_read_func_t)(struct bt_conn *conn, uint8_t err, struct bt_gatt_read_params *params, const void *data, uint16_t length); @@ -926,30 +941,35 @@ struct bt_gatt_read_params { */ int bt_gatt_read(struct bt_conn *conn, struct bt_gatt_read_params *params); -/** @brief Write Response callback function - * - * @param conn Connection object. - * @param err Error code. - * @param data Data pointer in the write request. - */ -typedef void (*bt_gatt_write_rsp_func_t)(struct bt_conn *conn, uint8_t err, const void *data); + +/** @brief GATT Write parameters */ +struct bt_gatt_write_params { + /** Response callback */ + bt_gatt_rsp_func_t func; + /** Attribute handle */ + uint16_t handle; + /** Attribute data offset */ + uint16_t offset; + /** Data to be written */ + const void *data; + /** Length of the data */ + uint16_t length; +}; /** @brief Write Attribute Value by handle * * This procedure write the attribute value and return the result in the * callback. * + * Note: This procedure is asynchronous therefore the parameters need to + * remains valid while it is active. + * * @param conn Connection object. - * @param handle Attribute handle. - * @param offset Attribute data offset. - * @param data Data to be written. - * @param length Data length. - * @param func Callback function. + * @param params Write parameters. * * @return 0 in case of success or negative value in case of error. */ -int bt_gatt_write(struct bt_conn *conn, uint16_t handle, uint16_t offset, - const void *data, uint16_t length, bt_gatt_write_rsp_func_t func); +int bt_gatt_write(struct bt_conn *conn, struct bt_gatt_write_params *params); /** @brief Write Attribute Value by handle without response * @@ -1042,4 +1062,8 @@ void bt_gatt_cancel(struct bt_conn *conn); } #endif +/** + * @} + */ + #endif /* __BT_GATT_H */ diff --git a/system/libarc32_arduino101/drivers/bluetooth/hci.h b/system/libarc32_arduino101/drivers/bluetooth/hci.h index f7ff52c1..dae8d04d 100644 --- a/system/libarc32_arduino101/drivers/bluetooth/hci.h +++ b/system/libarc32_arduino101/drivers/bluetooth/hci.h @@ -34,12 +34,12 @@ typedef struct { } bt_addr_t; typedef struct { - uint8_t type; - uint8_t val[6]; + uint8_t type; + bt_addr_t a; } bt_addr_le_t; #define BT_ADDR_ANY (&(bt_addr_t) {{0, 0, 0, 0, 0, 0} }) -#define BT_ADDR_LE_ANY (&(bt_addr_le_t) { 0, {0, 0, 0, 0, 0, 0} }) +#define BT_ADDR_LE_ANY (&(bt_addr_le_t) { 0, { {0, 0, 0, 0, 0, 0} } }) static inline int bt_addr_cmp(const bt_addr_t *a, const bt_addr_t *b) { @@ -65,6 +65,7 @@ static inline void bt_addr_le_copy(bt_addr_le_t *dst, const bt_addr_le_t *src) #define BT_HCI_ERR_UNKNOWN_CONN_ID 0x02 #define BT_HCI_ERR_AUTHENTICATION_FAIL 0x05 #define BT_HCI_ERR_INSUFFICIENT_RESOURCES 0x0d +#define BT_HCI_ERR_UNSUPP_FEATURE_PARAMS_VAL 0x11 #define BT_HCI_ERR_REMOTE_USER_TERM_CONN 0x13 #define BT_HCI_ERR_PAIRING_NOT_ALLOWED 0x18 #define BT_HCI_ERR_UNSUPP_REMOTE_FEATURE 0x1a @@ -138,6 +139,12 @@ struct bt_hci_cmd_hdr { #define BT_HCI_GENERAL_BONDING 0x04 #define BT_HCI_GENERAL_BONDING_MITM 0x05 +/* + * MITM protection is enabled in SSP authentication requirements octet when + * LSB bit is set. + */ +#define BT_MITM 0x01 + /* I/O capabilities */ #define BT_IO_DISPLAY_ONLY 0x00 #define BT_IO_DISPLAY_YESNO 0x01 @@ -174,12 +181,40 @@ struct bt_hci_cmd_hdr { /* Construct OpCode from OGF and OCF */ #define BT_OP(ogf, ocf) ((ocf) | ((ogf) << 10)) +#define BT_HCI_OP_INQUIRY BT_OP(BT_OGF_LINK_CTRL, 0x0001) +struct bt_hci_op_inquiry { + uint8_t lap[3]; + uint8_t length; + uint8_t num_rsp; +} __packed; + +#define BT_HCI_OP_INQUIRY_CANCEL BT_OP(BT_OGF_LINK_CTRL, 0x0002) + +#define BT_HCI_OP_CONNECT BT_OP(BT_OGF_LINK_CTRL, 0x0005) +struct bt_hci_cp_connect { + bt_addr_t bdaddr; + uint16_t packet_type; + uint8_t pscan_rep_mode; + uint8_t reserved; + uint16_t clock_offset; + uint8_t allow_role_switch; +} __packed; + #define BT_HCI_OP_DISCONNECT BT_OP(BT_OGF_LINK_CTRL, 0x0006) struct bt_hci_cp_disconnect { uint16_t handle; uint8_t reason; } __packed; +#define BT_HCI_OP_CONNECT_CANCEL BT_OP(BT_OGF_LINK_CTRL, 0x0008) +struct bt_hci_cp_connect_cancel { + bt_addr_t bdaddr; +} __packed; +struct bt_hci_rp_connect_cancel { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + #define BT_HCI_OP_ACCEPT_CONN_REQ BT_OP(BT_OGF_LINK_CTRL, 0x0009) struct bt_hci_cp_accept_conn_req { bt_addr_t bdaddr; @@ -223,6 +258,34 @@ struct bt_hci_rp_pin_code_neg_reply { bt_addr_t bdaddr; } __packed; +#define BT_HCI_OP_AUTH_REQUESTED BT_OP(BT_OGF_LINK_CTRL, 0x0011) +struct bt_hci_cp_auth_requested { + uint16_t handle; +} __packed; + +#define BT_HCI_OP_SET_CONN_ENCRYPT BT_OP(BT_OGF_LINK_CTRL, 0x0013) +struct bt_hci_cp_set_conn_encrypt { + uint16_t handle; + uint8_t encrypt; +} __packed; + +#define BT_HCI_OP_REMOTE_NAME_REQUEST BT_OP(BT_OGF_LINK_CTRL, 0x0019) +struct bt_hci_cp_remote_name_request { + bt_addr_t bdaddr; + uint8_t pscan_rep_mode; + uint8_t reserved; + uint16_t clock_offset; +} __packed; + +#define BT_HCI_OP_REMOTE_NAME_CANCEL BT_OP(BT_OGF_LINK_CTRL, 0x001a) +struct bt_hci_cp_remote_name_cancel { + bt_addr_t bdaddr; +} __packed; +struct bt_hci_rp_remote_name_cancel { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + #define BT_HCI_OP_IO_CAPABILITY_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x002b) struct bt_hci_cp_io_capability_reply { bt_addr_t bdaddr; @@ -231,6 +294,27 @@ struct bt_hci_cp_io_capability_reply { uint8_t authentication; } __packed; +#define BT_HCI_OP_USER_CONFIRM_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x002c) +#define BT_HCI_OP_USER_CONFIRM_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x002d) +struct bt_hci_cp_user_confirm_reply { + bt_addr_t bdaddr; +} __packed; +struct bt_hci_rp_user_confirm_reply { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_USER_PASSKEY_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x002e) +struct bt_hci_cp_user_passkey_reply { + bt_addr_t bdaddr; + uint32_t passkey; +} __packed; + +#define BT_HCI_OP_USER_PASSKEY_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x002f) +struct bt_hci_cp_user_passkey_neg_reply { + bt_addr_t bdaddr; +} __packed; + #define BT_HCI_OP_IO_CAPABILITY_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x0034) struct bt_hci_cp_io_capability_neg_reply { bt_addr_t bdaddr; @@ -271,6 +355,11 @@ struct bt_hci_cp_host_num_completed_packets { struct bt_hci_handle_count h[0]; } __packed; +#define BT_HCI_OP_WRITE_INQUIRY_MODE BT_OP(BT_OGF_BASEBAND, 0x0045) +struct bt_hci_cp_write_inquiry_mode { + uint8_t mode; +} __packed; + #define BT_HCI_OP_WRITE_SSP_MODE BT_OP(BT_OGF_BASEBAND, 0x0056) struct bt_hci_cp_write_ssp_mode { uint8_t mode; @@ -351,8 +440,8 @@ struct bt_hci_rp_le_read_local_features { /* Needed in advertising reports when getting info about */ #define BT_LE_ADV_SCAN_RSP 0x04 -#define BT_HCI_OP_LE_SET_ADV_PARAMETERS BT_OP(BT_OGF_LE, 0x0006) -struct bt_hci_cp_le_set_adv_parameters { +#define BT_HCI_OP_LE_SET_ADV_PARAM BT_OP(BT_OGF_LE, 0x0006) +struct bt_hci_cp_le_set_adv_param { uint16_t min_interval; uint16_t max_interval; uint8_t type; @@ -502,6 +591,13 @@ struct bt_hci_cp_le_generate_dhkey { /* Event definitions */ +#define BT_HCI_EVT_VENDOR 0xff + +#define BT_HCI_EVT_INQUIRY_COMPLETE 0x01 +struct bt_hci_evt_inquiry_complete { + uint8_t status; +} __packed; + #define BT_HCI_EVT_CONN_COMPLETE 0x03 struct bt_hci_evt_conn_complete { uint8_t status; @@ -525,6 +621,19 @@ struct bt_hci_evt_disconn_complete { uint8_t reason; } __packed; +#define BT_HCI_EVT_AUTH_COMPLETE 0x06 +struct bt_hci_evt_auth_complete { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_EVT_REMOTE_NAME_REQ_COMPLETE 0x07 +struct bt_hci_evt_remote_name_req_complete { + uint8_t status; + bt_addr_t bdaddr; + uint8_t name[248]; +} __packed; + #define BT_HCI_EVT_ENCRYPT_CHANGE 0x08 struct bt_hci_evt_encrypt_change { uint8_t status; @@ -579,6 +688,28 @@ struct bt_hci_ev_link_key_notify { uint8_t key_type; } __packed; +#define BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI 0x22 +struct bt_hci_evt_inquiry_result_with_rssi { + bt_addr_t addr; + uint8_t pscan_rep_mode; + uint8_t reserved; + uint8_t cod[3]; + uint16_t clock_offset; + int8_t rssi; +} __packed; + +#define BT_HCI_EVT_EXTENDED_INQUIRY_RESULT 0x2f +struct bt_hci_evt_extended_inquiry_result { + uint8_t num_reports; + bt_addr_t addr; + uint8_t pscan_rep_mode; + uint8_t reserved; + uint8_t cod[3]; + uint16_t clock_offset; + int8_t rssi; + uint8_t eir[240]; +} __packed; + #define BT_HCI_EVT_ENCRYPT_KEY_REFRESH_COMPLETE 0x30 struct bt_hci_evt_encrypt_key_refresh_complete { uint8_t status; @@ -598,12 +729,29 @@ struct bt_hci_evt_io_capa_resp { uint8_t authentication; } __packed; +#define BT_HCI_EVT_USER_CONFIRM_REQ 0x33 +struct bt_hci_evt_user_confirm_req { + bt_addr_t bdaddr; + uint32_t passkey; +} __packed; + +#define BT_HCI_EVT_USER_PASSKEY_REQ 0x34 +struct bt_hci_evt_user_passkey_req { + bt_addr_t bdaddr; +} __packed; + #define BT_HCI_EVT_SSP_COMPLETE 0x36 struct bt_hci_evt_ssp_complete { uint8_t status; bt_addr_t bdaddr; } __packed; +#define BT_HCI_EVT_USER_PASSKEY_NOTIFY 0x3b +struct bt_hci_evt_user_passkey_notify { + bt_addr_t bdaddr; + uint32_t passkey; +} __packed; + #define BT_HCI_EVT_LE_META_EVENT 0x3e struct bt_hci_evt_le_meta_event { uint8_t subevent; diff --git a/system/libarc32_arduino101/drivers/bluetooth/storage.h b/system/libarc32_arduino101/drivers/bluetooth/storage.h new file mode 100644 index 00000000..e86d2f92 --- /dev/null +++ b/system/libarc32_arduino101/drivers/bluetooth/storage.h @@ -0,0 +1,152 @@ +/** @file + * @brief Bluetooth subsystem persistent storage APIs. + */ + +/* + * Copyright (c) 2016 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __BT_STORAGE_H +#define __BT_STORAGE_H + +/** + * @brief Persistent Storage + * @defgroup bt_storage Persistent Storage + * @ingroup bluetooth + * @{ + */ + +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Well known storage keys */ +enum { + /** Identity Address. + * Type: bt_addr_le_t (7 bytes) + */ + BT_STORAGE_ID_ADDR, + + /** Local Identity Resolving Key. + * Type: uint8_t key[16] + */ + BT_STORAGE_LOCAL_IRK, + + /** List of addresses of remote devices. + * Type: bt_addr_le_t addrs[n] (length is variable). + * + * This is only used for reading. Modification of the list happens + * implicitly by writing entries for each remote device. This value + * is only used with the local storage, i.e. NULL as the target + * bt_addr_le_t passed to the read callback. + */ + BT_STORAGE_ADDRESSES, + + /** Slave Long Term Key for legacy pairing. + * Type: struct bt_storage_ltk + */ + BT_STORAGE_SLAVE_LTK, + + /** Long Term Key for legacy pairing. + * Type: struct bt_storage_ltk + */ + BT_STORAGE_LTK, + + /** Identity Resolving Key + * Type: uint8_t key[16] + */ + BT_STORAGE_IRK, +}; + +/** LTK key flags */ +enum { + /* Key has been generated with MITM protection */ + BT_STORAGE_LTK_AUTHENTICATED = BIT(0), + + /* Key has been generated using the LE Secure Connection pairing */ + BT_STORAGE_LTK_SC = BIT(1), +}; + +struct bt_storage_ltk { + uint8_t flags; + /* Encryption key size used to generate key */ + uint8_t size; + uint16_t ediv; + uint8_t rand[8]; + uint8_t val[16]; +}; + +struct bt_storage { + /** Read the value of a key from storage. + * + * @param addr Remote address or NULL for local storage + * @param key BT_STORAGE_* key to read + * @param data Memory location to place the data + * @param length Maximum number of bytes to read + * + * @return Number of bytes read or negative error value on + * failure. + */ + ssize_t (*read)(const bt_addr_le_t *addr, uint16_t key, + void *data, size_t length); + + /** Write the value of a key to storage. + * + * @param addr Remote address or NULL for local storage + * @param key BT_STORAGE_* key to write + * @param data Memory location of the data + * @param length Number of bytes to write + * + * @return Number of bytes written or negative error value on + * failure. + */ + ssize_t (*write)(const bt_addr_le_t *addr, uint16_t key, + const void *data, size_t length); + + /** Clear all keys for a specific address + * + * @param addr Remote address, BT_ADDR_LE_ANY for all + * remote devices, or NULL for local storage. + * + * @return 0 on success or negative error value on failure. + */ + int (*clear)(const bt_addr_le_t *addr); + +}; + +void bt_storage_register(const struct bt_storage *storage); + +/** Clear all storage keys for a specific address + * + * @param addr Remote address, NULL for local storage or + * BT_ADDR_LE_ANY to clear all remote devices. + * + * @return 0 on success or negative error value on failure. + */ +int bt_storage_clear(bt_addr_le_t *addr); + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* __BT_STORAGE_H */ diff --git a/system/libarc32_arduino101/drivers/rpc/rpc.h b/system/libarc32_arduino101/drivers/rpc/rpc.h index 5d45d463..7fea08e9 100644 --- a/system/libarc32_arduino101/drivers/rpc/rpc.h +++ b/system/libarc32_arduino101/drivers/rpc/rpc.h @@ -18,6 +18,7 @@ #define RPC_H_ #include +#include /** Identifiers of the signature supported by the RPC */ enum { @@ -25,106 +26,108 @@ enum { SIG_TYPE_S, SIG_TYPE_P, SIG_TYPE_S_B, - SIG_TYPE_B_B_P, SIG_TYPE_S_P, - SIG_TYPE_S_B_P, - SIG_TYPE_S_B_B_P + SIG_TYPE_CONTROL = 0xFF }; /** * RPC memory allocation function, must be implemented by the user of the RPC. * - * This function is called by the RPC mechanism to allocate a buffer for transmission - * of a serialized function. The function should not fail. + * This function is called by the RPC mechanism to allocate a buffer for + * transmission of a serialized function. The function should not fail. * - * @param length Length of the buffer to allocate + * @param length Length of the buffer to allocate. * - * @return Pointer to the allocated buffer, the allocation shall not fail, error must - * be handled internally + * @return Pointer to the allocated buffer, the allocation shall not fail, + * error must be handled internally */ -uint8_t * rpc_alloc_cb(uint16_t length); +uint8_t *rpc_alloc_cb(uint16_t length); /** - * RPC transmission function, must be implemented by the user of the RPC. + * RPC memory free function, must be implemented by the user of the RPC. + * + * This function is called by the RPC mechanism to free a buffer passed to the + * deserialization function as soon as all the data was consumed. * - * @param p_buf Pointer to the buffer allocated for transmission by @ref rpc_alloc_cb - * @param length Length of the buffer to transmit + * @param buf Pointer to the buffer passed to the deserialization function. */ -void rpc_transmit_cb(uint8_t * p_buf, uint16_t length); +void rpc_free_cb(const uint8_t *buf); /** - * RPC serialization function to serialize a function that does not require any parameter. + * RPC transmission function, must be implemented by the user of the RPC. * - * @param fn_index Index of the function + * @param buf Pointer to the buffer allocated for transmission + * by @ref rpc_alloc_cb */ -void rpc_serialize_none(uint8_t fn_index); +void rpc_transmit_cb(uint8_t *buf); /** - * RPC serialization function to serialize a function that expects a structure as parameter. + * RPC initialization function that notifies the peer with an initialization + * packet containing the information to check the compatibility of the + * frameworks. * - * @param fn_index Index of the function - * @param struct_data Pointer to the structure to serialize - * @param struct_length Length of the structure to serialize + * @param version Local version to send to the peer. */ -void rpc_serialize_s(uint8_t fn_index, const void * struct_data, uint8_t struct_length); +void rpc_init(uint32_t version); /** - * RPC serialization function to serialize a function that expects a structure as parameter. + * RPC initialization packet reception function, can optionally be implemented + * by the user of the RPC. If this function is not implemented, it will default + * to an empty function. * - * @param fn_index Index of the function - * @param struct_data Pointer to the structure to serialize - * @param struct_length Length of the structure to serialize - * @param p_priv Pointer to serialize + * This function is called by the RPC mechanism when an initialization packet is + * received from the connected peer. + * + * @param version Peer advertised version. + * @param compatible True if the peer runs a compatible RPC framework. + */ +void rpc_init_cb(uint32_t version, bool compatible); + +/** RPC serialize hash number generation. + * + * @return The unique identifier of the RPC deserialization. */ -void rpc_serialize_s_p(uint8_t fn_index, const void * struct_data, uint8_t struct_length, void * p_priv); +uint32_t rpc_serialize_hash(void); /** - * RPC serialization function to serialize a function that expects a pointer as parameter. + * RPC serialization function to serialize a function that does not require any + * parameter. * * @param fn_index Index of the function - * @param p_priv Pointer to serialize */ -void rpc_serialize_p(uint8_t fn_index, void * p_priv); +void rpc_serialize_none(uint8_t fn_index); /** * RPC serialization function to serialize a function that expects a structure - * and a buffer as parameters. + * as parameter. * * @param fn_index Index of the function * @param struct_data Pointer to the structure to serialize * @param struct_length Length of the structure to serialize - * @param vbuf Pointer to the buffer to serialize - * @param vbuf_length Length of the buffer to serialize */ -void rpc_serialize_s_b(uint8_t fn_index, const void * struct_data, uint8_t struct_length, const void * vbuf, uint16_t vbuf_length); +void rpc_serialize_s(uint8_t fn_index, const void *struct_data, + uint8_t struct_length); /** - * RPC serialization function to serialize a function that expects a structure - * and a buffer as parameters. + * RPC serialization function to serialize a function that expects a pointer as + * parameter. * * @param fn_index Index of the function - * @param vbuf1 Pointer to the buffer1 to serialize - * @param vbuf1_length Length of the buffer1 to serialize - * @param vbuf2 Pointer to the buffer2 to serialize - * @param vbuf2_length Length of the buffer2 to serialize * @param p_priv Pointer to serialize */ -void rpc_serialize_b_b_p(uint8_t fn_index, const void * vbuf1, uint16_t vbuf1_length, - const void * vbuf2, uint16_t vbuf2_length, void * p_priv); +void rpc_serialize_p(uint8_t fn_index, void *p_priv); /** * RPC serialization function to serialize a function that expects a structure - * and a buffer as parameters. + * and a pointer as parameters. * * @param fn_index Index of the function * @param struct_data Pointer to the structure to serialize * @param struct_length Length of the structure to serialize - * @param vbuf Pointer to the buffer to serialize - * @param vbuf_length Length of the buffer to serialize * @param p_priv Pointer to serialize */ -void rpc_serialize_s_b_p(uint8_t fn_index, const void * struct_data, uint8_t struct_length, - const void * vbuf, uint16_t vbuf_length, void * p_priv); +void rpc_serialize_s_p(uint8_t fn_index, const void *struct_data, + uint8_t struct_length, void *p_priv); /** * RPC serialization function to serialize a function that expects a structure @@ -133,20 +136,25 @@ void rpc_serialize_s_b_p(uint8_t fn_index, const void * struct_data, uint8_t str * @param fn_index Index of the function * @param struct_data Pointer to the structure to serialize * @param struct_length Length of the structure to serialize - * @param vbuf1 Pointer to the buffer1 to serialize - * @param vbuf1_length Length of the buffer1 to serialize - * @param vbuf2 Pointer to the buffer2 to serialize - * @param vbuf2_length2 Length of the buffer2 to serialize - * @param p_priv Pointer to serialize + * @param vbuf Pointer to the buffer to serialize + * @param vbuf_length Length of the buffer to serialize */ -void rpc_serialize_s_b_b_p(uint8_t fn_index, const void * struct_data, uint8_t struct_length, - const void * vbuf1, uint16_t vbuf1_length, const void * vbuf2, uint16_t vbuf2_length, void * p_priv); +void rpc_serialize_s_b(uint8_t fn_index, const void *struct_data, + uint8_t struct_length, const void *vbuf, + uint16_t vbuf_length); -/** RPC deserialization function, shall be invoked when a buffer is received over the transport interface. +/** + * RPC deserialization function, shall be invoked when a buffer is received + * over the transport interface. * * @param p_buf Pointer to the received buffer * @param length Length of the received buffer */ -void rpc_deserialize(const uint8_t * p_buf, uint16_t length); +void rpc_deserialize(const uint8_t *p_buf, uint16_t length); +/** RPC deserialize hash number generation. + * + * @return The unique identifier of the RPC deserialization. + */ +uint32_t rpc_deserialize_hash(void); #endif /* RPC_H_*/ diff --git a/system/libarc32_arduino101/drivers/rpc/rpc_deserialize.c b/system/libarc32_arduino101/drivers/rpc/rpc_deserialize.c index e3f568d0..04870957 100644 --- a/system/libarc32_arduino101/drivers/rpc/rpc_deserialize.c +++ b/system/libarc32_arduino101/drivers/rpc/rpc_deserialize.c @@ -19,6 +19,10 @@ #include "rpc.h" +#ifndef __weak +#define __weak __attribute__((weak)) +#endif + extern void panic(int err); /* Include the functions offered */ @@ -33,425 +37,352 @@ extern void panic(int err); #error "File is compiled but should not" #endif -/* Build the list of prototypes and check that list are made only of matching signatures */ -#define FN_SIG_NONE(__fn) void __fn(void); +/* Build the list of prototypes and check that list are made only of matching + * signatures + */ +#define FN_SIG_NONE(__fn) void __fn(void); LIST_FN_SIG_NONE #undef FN_SIG_NONE -#define FN_SIG_S(__fn, __s) void __fn(__s p_s); +#define FN_SIG_S(__fn, __s) void __fn(__s p_s); LIST_FN_SIG_S #undef FN_SIG_S -#define FN_SIG_P(__fn, __type) void __fn(__type p_priv); +#define FN_SIG_P(__fn, __type) void __fn(__type priv); LIST_FN_SIG_P #undef FN_SIG_P -#define FN_SIG_S_B(__fn, __s, __type, __length) void __fn(__s p_s, __type p_buf, __length length); +#define FN_SIG_S_B(__fn, __s, __type, __length) \ + void __fn(__s p_s, __type buf, __length length); LIST_FN_SIG_S_B #undef FN_SIG_S_B -#define FN_SIG_B_B_P(__fn, __type1, __length1, __type2, __length2, __type3) \ - void __fn(__type1 p_buf1, __length1 length1, __type2 p_buf2, __length2 length2, __type3 p_priv); -LIST_FN_SIG_B_B_P -#undef FN_SIG_B_B_P - -#define FN_SIG_S_P(__fn, __s, __type) void __fn(__s p_s, __type p_priv); +#define FN_SIG_S_P(__fn, __s, __type) void __fn(__s p_s, __type priv); LIST_FN_SIG_S_P #undef FN_SIG_S_P -#define FN_SIG_S_B_P(__fn, __s, __type, __length, __type_ptr) \ - void __fn(__s p_s, __type p_buf, __length length, __type_ptr p_priv); -LIST_FN_SIG_S_B_P -#undef FN_SIG_S_B_P - -#define FN_SIG_S_B_B_P(__fn, __s, __type1, __length1, __type2, __length2, __type_ptr) \ - void __fn(__s p_s, __type1 p_buf1, __length1 length1, __type2 p_buf2, __length2 length2, __type_ptr p_priv); -LIST_FN_SIG_S_B_B_P -#undef FN_SIG_S_B_B_P - - - /* 1 - define the size check arrays */ #define FN_SIG_NONE(__fn) -#define FN_SIG_S(__fn, __s) sizeof(*((__s)0)), +#define FN_SIG_S(__fn, __s) sizeof(*((__s)0)), #define FN_SIG_P(__fn, __type) -#define FN_SIG_S_B(__fn, __s, __type, __length) sizeof(*((__s)0)), - -#define FN_SIG_B_B_P(__fn, __type1, __length1, __type2, __length2, __type3) sizeof(*((__s)0)), - -#define FN_SIG_S_P(__fn, __s, __type) sizeof(*((__s)0)), +#define FN_SIG_S_B(__fn, __s, __type, __length) sizeof(*((__s)0)), -#define FN_SIG_S_B_P(__fn, __s, __type, __length, __type_ptr) sizeof(*((__s)0)), - -#define FN_SIG_S_B_B_P(__fn, __s, __type1, __length1, __type2, __length2, __type3) sizeof(*((__s)0)), +#define FN_SIG_S_P(__fn, __s, __type) sizeof(*((__s)0)), static uint8_t m_size_s[] = { LIST_FN_SIG_S }; static uint8_t m_size_s_b[] = { LIST_FN_SIG_S_B }; static uint8_t m_size_s_p[] = { LIST_FN_SIG_S_P }; -static uint8_t m_size_s_b_p[] = { LIST_FN_SIG_S_B_P }; -static uint8_t m_size_s_b_b_p[] = { LIST_FN_SIG_S_B_B_P }; #undef FN_SIG_NONE #undef FN_SIG_S #undef FN_SIG_P #undef FN_SIG_S_B -#undef FN_SIG_B_B_P #undef FN_SIG_S_P -#undef FN_SIG_S_B_P -#undef FN_SIG_S_B_B_P /* 2- build the enumerations list */ -#define FN_SIG_NONE(__fn) fn_index_##__fn, -#define FN_SIG_S(__fn, __s) FN_SIG_NONE(__fn) -#define FN_SIG_P(__fn, __type) FN_SIG_NONE(__fn) -#define FN_SIG_S_B(__fn, __s, __type, __length) FN_SIG_NONE(__fn) -#define FN_SIG_B_B_P(__fn, __type1, __length1, __type2, __length2, __type3) FN_SIG_NONE(__fn) -#define FN_SIG_S_P(__fn, __s, __type) FN_SIG_NONE(__fn) -#define FN_SIG_S_B_P(__fn, __s, __type, __length, __type_ptr) FN_SIG_NONE(__fn) -#define FN_SIG_S_B_B_P(__fn, __s, __type1, __length1, __type2, __length2, __type3) FN_SIG_NONE(__fn) +#define FN_SIG_NONE(__fn) fn_index_##__fn, +#define FN_SIG_S(__fn, __s) FN_SIG_NONE(__fn) +#define FN_SIG_P(__fn, __type) FN_SIG_NONE(__fn) +#define FN_SIG_S_B(__fn, __s, __type, __length) FN_SIG_NONE(__fn) +#define FN_SIG_S_P(__fn, __s, __type) FN_SIG_NONE(__fn) /* Build the list of function indexes in the deserialization array */ enum { LIST_FN_SIG_NONE fn_none_index_max }; enum { LIST_FN_SIG_S fn_s_index_max }; enum { LIST_FN_SIG_P fn_p_index_max }; enum { LIST_FN_SIG_S_B fn_s_b_index_max }; -enum { LIST_FN_SIG_B_B_P fn_b_b_p_index_max }; enum { LIST_FN_SIG_S_P fn_s_p_index_max }; -enum { LIST_FN_SIG_S_B_P fn_s_b_p_index_max }; -enum { LIST_FN_SIG_S_B_B_P fn_s_b_b_p_index_max }; #undef FN_SIG_NONE #undef FN_SIG_S #undef FN_SIG_P #undef FN_SIG_S_B -#undef FN_SIG_B_B_P #undef FN_SIG_S_P -#undef FN_SIG_S_B_P -#undef FN_SIG_S_B_B_P /* 3- build the array */ -#define FN_SIG_NONE(__fn) [fn_index_##__fn] = (void*)__fn, -#define FN_SIG_S(__fn, __s) FN_SIG_NONE(__fn) -#define FN_SIG_P(__fn, __type) FN_SIG_NONE(__fn) -#define FN_SIG_S_B(__fn, __s, __type, __length) FN_SIG_NONE(__fn) -#define FN_SIG_B_B_P(__fn, __type1, __length1, __type2, __length2, __type3) FN_SIG_NONE(__fn) -#define FN_SIG_S_P(__fn, __s, __type) FN_SIG_NONE(__fn) -#define FN_SIG_S_B_P(__fn, __s, __type, __length, __type_ptr) FN_SIG_NONE(__fn) -#define FN_SIG_S_B_B_P(__fn, __s, __type1, __length1, __type2, __length2, __type3) FN_SIG_NONE(__fn) +#define FN_SIG_NONE(__fn) [fn_index_##__fn] = \ + (void *)__fn, +#define FN_SIG_S(__fn, __s) FN_SIG_NONE(__fn) +#define FN_SIG_P(__fn, __type) FN_SIG_NONE(__fn) +#define FN_SIG_S_B(__fn, __s, __type, __length) \ + FN_SIG_NONE(__fn) +#define FN_SIG_S_P(__fn, __s, __type) FN_SIG_NONE(__fn) static void (*m_fct_none[])(void) = { LIST_FN_SIG_NONE }; -static void (*m_fct_s[])(void * structure) = { LIST_FN_SIG_S }; -static void (*m_fct_p[])(void * pointer) = { LIST_FN_SIG_P }; -static void (*m_fct_s_b[])(void * structure, void * buffer, uint8_t length) = { LIST_FN_SIG_S_B }; -static void (*m_fct_b_b_p[])(void * buffer1, uint8_t length1, void * buffer2, uint8_t length2, void * pointer) = { LIST_FN_SIG_B_B_P }; -static void (*m_fct_s_p[])(void * structure, void * pointer) = { LIST_FN_SIG_S_P }; -static void (*m_fct_s_b_p[])(void * structure, void * buffer, uint8_t length, void * pointer) = { LIST_FN_SIG_S_B_P }; -static void (*m_fct_s_b_b_p[])(void * structure, void * buffer1, uint8_t length1, void * buffer2, uint8_t length2, void * pointer) = { LIST_FN_SIG_S_B_B_P }; - -static const uint8_t * deserialize_struct(const uint8_t *p, const uint8_t **pp_struct, uint8_t *p_struct_length) { - uint8_t struct_length; +static void (*m_fct_s[])(void *structure) = { LIST_FN_SIG_S }; +static void (*m_fct_p[])(void *pointer) = { LIST_FN_SIG_P }; +static void (*m_fct_s_b[])(void *structure, void *buffer, + uint16_t length) = { LIST_FN_SIG_S_B }; +static void (*m_fct_s_p[])(void *structure, + void *pointer) = { LIST_FN_SIG_S_P }; + +#undef FN_SIG_NONE +#undef FN_SIG_S +#undef FN_SIG_P +#undef FN_SIG_S_B +#undef FN_SIG_S_P + +#define DJB2_HASH(__h, __v) ((__h << 5) + __h) + __v + +#define FN_SIG_NONE(__fn) \ + hash = DJB2_HASH(hash, 1); + +#define FN_SIG_S(__fn, __s) \ + hash = DJB2_HASH(hash, 2); \ + hash = DJB2_HASH(hash, sizeof(*((__s)0))); + +#define FN_SIG_P(__fn, __type) \ + hash = DJB2_HASH(hash, 3); + +#define FN_SIG_S_B(__fn, __s, __type, __length) \ + hash = DJB2_HASH(hash, 4); \ + hash = DJB2_HASH(hash, sizeof(*((__s)0))); + +#define FN_SIG_S_P(__fn, __s, __type) \ + hash = DJB2_HASH(hash, 6); \ + hash = DJB2_HASH(hash, sizeof(*((__s)0))); + +uint32_t rpc_deserialize_hash(void) +{ + uint32_t hash = 5381; - struct_length = *p++; - *pp_struct = p; - *p_struct_length = struct_length; + LIST_FN_SIG_NONE; + LIST_FN_SIG_S; + LIST_FN_SIG_P; + LIST_FN_SIG_S_B; + LIST_FN_SIG_S_P; - return p + struct_length; + return hash; } -static const uint8_t * deserialize_buf(const uint8_t *p, const uint8_t **pp_buf, uint16_t *p_buflen) { +static const uint8_t *deserialize_struct(const uint8_t *p, + const uint8_t **struct_ptr, + uint8_t *struct_length) +{ + *struct_length = *p++; + *struct_ptr = p; + + return p + *struct_length; +} + +static const uint8_t *deserialize_buf(const uint8_t *p, const uint8_t **buf_ptr, + uint16_t *buf_len) +{ uint8_t b; - uint16_t buflen; /* Get the current byte */ b = *p++; - buflen = b & 0x7F; + *buf_len = b & 0x7F; if (b & 0x80) { /* Get the current byte */ b = *p++; - buflen += (uint16_t)b << 7; + *buf_len += (uint16_t)b << 7; } /* Return the values */ - *pp_buf = p; - *p_buflen = buflen; - p += buflen; + *buf_ptr = p; + p += *buf_len; return p; } -static void deserialize_none(uint8_t fn_index, const uint8_t * p_buf, uint16_t length) { - (void)p_buf; +static const uint8_t *deserialize_ptr(const uint8_t *p, uintptr_t *priv) +{ + *priv = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); + p += 4; + return p; +} + +static void deserialize_none(uint8_t fn_index, const uint8_t *buf, + uint16_t length) +{ if (length != 0) panic(-1); + + rpc_free_cb(buf - 2); + m_fct_none[fn_index](); } -static void deserialize_s(uint8_t fn_index, const uint8_t * p_buf, uint16_t length) { - const uint8_t *p_struct_data; +static void deserialize_s(uint8_t fn_index, const uint8_t *buf, + uint16_t length) +{ + const uint8_t *struct_ptr; uint8_t struct_length; - const uint8_t *p; + const uint8_t *p = buf; - p = deserialize_struct(p_buf, &p_struct_data, &struct_length); + p = deserialize_struct(p, &struct_ptr, &struct_length); - if ((length != (p - p_buf)) || - (struct_length != m_size_s[fn_index])) + if ((length != (p - buf)) || (struct_length != m_size_s[fn_index])) panic(-1); { /* Always align structures on word boundary */ - uintptr_t struct_data[(struct_length + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; + uintptr_t struct_data[(struct_length + + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; - memcpy(struct_data, p_struct_data, struct_length); + memcpy(struct_data, struct_ptr, struct_length); + + rpc_free_cb(buf - 2); m_fct_s[fn_index](struct_data); } } -static void deserialize_p(uint8_t fn_index, const uint8_t * p_buf, uint16_t length) { - uintptr_t p_priv; +static void deserialize_p(uint8_t fn_index, const uint8_t *buf, + uint16_t length) +{ + uintptr_t priv; + const uint8_t *p = buf; + + p = deserialize_ptr(p, &priv); - if (length != 4) + if (length != (p - buf)) panic(-1); - /* little endian conversion */ - p_priv = p_buf[0] | (p_buf[1] << 8) | (p_buf[2] << 16) | (p_buf[3] << 24); + rpc_free_cb(buf - 2); - m_fct_p[fn_index]((void *)p_priv); + m_fct_p[fn_index]((void *)priv); } -static void deserialize_s_b(uint8_t fn_index, const uint8_t * p_buf, uint16_t length) { +static void deserialize_s_b(uint8_t fn_index, const uint8_t *buf, + uint16_t length) +{ const uint8_t *p_struct_data; uint8_t struct_length; const uint8_t *p_vbuf; uint16_t vbuf_length; - const uint8_t *p; + const uint8_t *p = buf; - p = deserialize_struct(p_buf, &p_struct_data, &struct_length); + p = deserialize_struct(p, &p_struct_data, &struct_length); p = deserialize_buf(p, &p_vbuf, &vbuf_length); - if ((length != (p - p_buf)) || - (struct_length != m_size_s_b[fn_index])) + if ((length != (p - buf)) || (struct_length != m_size_s_b[fn_index])) panic(-1); { /* Always align structures on word boundary */ - uintptr_t struct_data[(struct_length + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; - uintptr_t vbuf[(vbuf_length + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; - void * buf = NULL; + uintptr_t struct_data[(struct_length + + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; + uintptr_t vbuf[(vbuf_length + + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; memcpy(struct_data, p_struct_data, struct_length); if (vbuf_length) { memcpy(vbuf, p_vbuf, vbuf_length); - buf = vbuf; - } - - m_fct_s_b[fn_index](struct_data, buf, vbuf_length); - } -} - -static void deserialize_b_b_p(uint8_t fn_index, const uint8_t * p_buf, uint16_t length) { - const uint8_t *p_vbuf1; - uint16_t vbuf1_length; - const uint8_t *p_vbuf2; - uint16_t vbuf2_length; - uintptr_t p_priv; - const uint8_t *p; - - p = deserialize_buf(p_buf, &p_vbuf1, &vbuf1_length); - p = deserialize_buf(p, &p_vbuf2, &vbuf2_length); - p += 4; - - if (length != (p - p_buf)) - panic(-1); - - { - /* Always align structures on word boundary */ - uintptr_t vbuf1[(vbuf1_length + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; - uintptr_t vbuf2[(vbuf2_length + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; - void * buf1 = NULL; - void * buf2 = NULL; - - if (vbuf1_length) { - memcpy(vbuf1, p_vbuf1, vbuf1_length); - buf1 = vbuf1; } - if (vbuf2_length) { - memcpy(vbuf2, p_vbuf2, vbuf2_length); - buf2 = vbuf2; - } - p = p_vbuf2 + vbuf2_length; + rpc_free_cb(buf - 2); - /* little endian conversion */ - p_priv = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); - - m_fct_b_b_p[fn_index](buf1, vbuf1_length, buf2, vbuf2_length, (void *)p_priv); + m_fct_s_b[fn_index](struct_data, (void *)vbuf, vbuf_length); } } -static void deserialize_s_p(uint8_t fn_index, const uint8_t * p_buf, uint16_t length) +static void deserialize_s_p(uint8_t fn_index, const uint8_t *buf, + uint16_t length) { const uint8_t *p_struct_data; uint8_t struct_length; - uintptr_t p_priv; - const uint8_t *p; + uintptr_t priv; + const uint8_t *p = buf; - p = deserialize_struct(p_buf, &p_struct_data, &struct_length); - p += 4; + p = deserialize_struct(p, &p_struct_data, &struct_length); + p = deserialize_ptr(p, &priv); - if ((length != (p - p_buf)) || - (struct_length != m_size_s_p[fn_index])) + if ((length != (p - buf)) || (struct_length != m_size_s_p[fn_index])) panic(-1); { /* Always align structures on word boundary */ - uintptr_t struct_data[(struct_length + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; + uintptr_t struct_data[(struct_length + + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; memcpy(struct_data, p_struct_data, struct_length); - p = p_struct_data + struct_length; - - /* little endian conversion */ - p_priv = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); - m_fct_s_p[fn_index](struct_data, (void *)p_priv); + rpc_free_cb(buf - 2); + m_fct_s_p[fn_index](struct_data, (void *)priv); } } -static void deserialize_s_b_p(uint8_t fn_index, const uint8_t * p_buf, uint16_t length) +static void deserialize_control(uint8_t fn_index, const uint8_t *buf, + uint16_t length) { const uint8_t *p_struct_data; uint8_t struct_length; - const uint8_t *p_vbuf; - uint16_t vbuf_length; - uintptr_t p_priv; - const uint8_t *p; - - p = deserialize_struct(p_buf, &p_struct_data, &struct_length); - p = deserialize_buf(p, &p_vbuf, &vbuf_length); - p += 4; - - if ((length != (p - p_buf)) || - (struct_length != m_size_s_b_p[fn_index])) - panic(-1); - - { - /* Always align structures on word boundary */ - uintptr_t struct_data[(struct_length + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; - uintptr_t vbuf[(vbuf_length + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; - void * buf = NULL; - - memcpy(struct_data, p_struct_data, struct_length); - - if (vbuf_length) { - memcpy(vbuf, p_vbuf, vbuf_length); - buf = vbuf; - } - p = p_vbuf + vbuf_length; - - /* little endian conversion */ - p_priv = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); - - m_fct_s_b_p[fn_index](struct_data, buf, vbuf_length, (void *)p_priv); - } -} - -static void deserialize_s_b_b_p(uint8_t fn_index, const uint8_t * p_buf, uint16_t length) { - const uint8_t *p_struct_data; - uint8_t struct_length; - const uint8_t *p_vbuf1; - uint16_t vbuf1_length; - const uint8_t *p_vbuf2; - uint16_t vbuf2_length; - uintptr_t p_priv; - const uint8_t *p; - - p = deserialize_struct(p_buf, &p_struct_data, &struct_length); - p = deserialize_buf(p, &p_vbuf1, &vbuf1_length); - p = deserialize_buf(p, &p_vbuf2, &vbuf2_length); - p += 4; - if ((length != (p - p_buf)) || - (struct_length != m_size_s_b_b_p[fn_index])) - panic(-1); - - { - /* Always align structures on word boundary */ - uintptr_t struct_data[(struct_length + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; - uintptr_t vbuf1[(vbuf1_length + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; - uintptr_t vbuf2[(vbuf2_length + (sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))]; - void * buf1 = NULL; - void * buf2 = NULL; + const uint8_t *p = buf; + struct { + uint32_t version; + uint32_t ser_hash; + uint32_t des_hash; + } struct_data; + + switch(fn_index) { + case 0: + p = deserialize_struct(p, &p_struct_data, &struct_length); + + if ((length != (p - buf)) || (struct_length != sizeof(struct_data))) + panic(-1); + memcpy(&struct_data, p_struct_data, struct_length); - memcpy(struct_data, p_struct_data, struct_length); + rpc_free_cb(buf - 2); - if (vbuf1_length) { - memcpy(vbuf1, p_vbuf1, vbuf1_length); - buf1 = vbuf1; - } - if (vbuf2_length) { - memcpy(vbuf2, p_vbuf2, vbuf2_length); - buf2 = vbuf2; + if (struct_data.ser_hash != rpc_deserialize_hash() || + struct_data.des_hash != rpc_serialize_hash()) { + rpc_init_cb(struct_data.version, false); + } else { + rpc_init_cb(struct_data.version, true); } - - p = p_vbuf2 + vbuf2_length; - - /* little endian conversion */ - p_priv = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); - - m_fct_s_b_b_p[fn_index](struct_data, buf1, vbuf1_length, buf2, vbuf2_length, (void *)p_priv); + break; } } -void rpc_deserialize(const uint8_t * p_buf, uint16_t length) { - +void rpc_deserialize(const uint8_t *buf, uint16_t length) +{ uint8_t fn_index; uint8_t sig_type; - if (NULL != p_buf) { - sig_type = p_buf[0]; - fn_index = p_buf[1]; - - p_buf += 2; - length -= 2; - - switch(sig_type) { - case SIG_TYPE_NONE: - if (sizeof(m_fct_none)) - deserialize_none(fn_index, p_buf, length); - break; - case SIG_TYPE_S: - if (sizeof(m_fct_s)) - deserialize_s(fn_index, p_buf, length); - break; - case SIG_TYPE_P: - if (sizeof(m_fct_p)) - deserialize_p(fn_index, p_buf, length); - break; - case SIG_TYPE_S_B: - if (sizeof(m_fct_s_b)) - deserialize_s_b(fn_index, p_buf, length); - break; - case SIG_TYPE_B_B_P: - if (sizeof(m_fct_b_b_p)) - deserialize_b_b_p(fn_index, p_buf, length); - break; - case SIG_TYPE_S_P: - if (sizeof(m_fct_s_p)) - deserialize_s_p(fn_index, p_buf, length); - break; - case SIG_TYPE_S_B_P: - if (sizeof(m_fct_s_b_p)) - deserialize_s_b_p(fn_index, p_buf, length); - break; - case SIG_TYPE_S_B_B_P: - if (sizeof(m_fct_s_b_b_p)) - deserialize_s_b_b_p(fn_index, p_buf, length); - break; - default: - panic(-1); - break; - } + if (!buf) return; + + sig_type = buf[0]; + fn_index = buf[1]; + + buf += 2; + length -= 2; + + switch(sig_type) { + case SIG_TYPE_NONE: + if (sizeof(m_fct_none)) + deserialize_none(fn_index, buf, length); + break; + case SIG_TYPE_S: + if (sizeof(m_fct_s)) + deserialize_s(fn_index, buf, length); + break; + case SIG_TYPE_P: + if (sizeof(m_fct_p)) + deserialize_p(fn_index, buf, length); + break; + case SIG_TYPE_S_B: + if (sizeof(m_fct_s_b)) + deserialize_s_b(fn_index, buf, length); + break; + case SIG_TYPE_S_P: + if (sizeof(m_fct_s_p)) + deserialize_s_p(fn_index, buf, length); + break; + case SIG_TYPE_CONTROL: + deserialize_control(fn_index, buf, length); + break; + default: + panic(-1); + break; } } + +__weak +void rpc_init_cb(uint32_t version, bool compatible) +{ +} diff --git a/system/libarc32_arduino101/drivers/rpc/rpc_functions_to_ble_core.h b/system/libarc32_arduino101/drivers/rpc/rpc_functions_to_ble_core.h index 5f742208..3801da01 100644 --- a/system/libarc32_arduino101/drivers/rpc/rpc_functions_to_ble_core.h +++ b/system/libarc32_arduino101/drivers/rpc/rpc_functions_to_ble_core.h @@ -19,6 +19,8 @@ #include "gap_internal.h" #include "gatt_internal.h" +#include "dtm_internal.h" +#include "storage_internal.h" /* declare the list of functions sorted by signature */ #define LIST_FN_SIG_NONE \ @@ -27,80 +29,82 @@ #define LIST_FN_SIG_S \ FN_SIG_S(nble_gap_set_adv_data_req, \ - struct nble_gap_ad_data_params *) \ + struct nble_gap_set_adv_data_req *) \ FN_SIG_S(nble_gap_set_adv_params_req, \ - struct nble_gap_adv_params *) \ + struct nble_gap_set_adv_params_req *) \ FN_SIG_S(nble_gap_start_scan_req, \ - const struct nble_gap_scan_params *) \ - FN_SIG_S(nble_gap_sm_config_req, \ - const struct nble_gap_sm_config_params *) \ - FN_SIG_S(nble_gap_sm_passkey_reply_req, \ - const struct nble_gap_sm_key_reply_req_params *) \ - FN_SIG_S(nble_gap_sm_bond_info_req, \ - const struct nble_gap_sm_bond_info_param *) \ - FN_SIG_S(nble_gap_sm_security_req, \ - const struct nble_gap_sm_security_params *) \ - FN_SIG_S(nble_gap_sm_clear_bonds_req, \ - const struct nble_gap_sm_clear_bond_req_params *) \ - FN_SIG_S(nble_set_bda_req, const struct nble_set_bda_params *) \ + const struct nble_gap_start_scan_req *) \ + FN_SIG_S(nble_sm_passkey_reply_req, \ + const struct nble_sm_passkey_reply_req *) \ + FN_SIG_S(nble_sm_bond_info_req, \ + const struct nble_sm_bond_info_req *) \ + FN_SIG_S(nble_sm_security_req, \ + const struct nble_sm_security_req *) \ + FN_SIG_S(nble_sm_clear_bonds_req, \ + const struct nble_sm_clear_bonds_req *) \ + FN_SIG_S(nble_set_bda_req, const struct nble_set_bda_req *) \ + FN_SIG_S(nble_get_bda_req, const struct nble_get_bda_req *) \ FN_SIG_S(nble_gap_conn_update_req, \ - const struct nble_gap_connect_update_params *) \ + const struct nble_gap_conn_update_req *) \ FN_SIG_S(nble_gattc_discover_req, \ - const struct nble_discover_params *) \ - FN_SIG_S(nble_gatts_wr_reply_req, \ - const struct nble_gatts_wr_reply_params *) \ + const struct nble_gattc_discover_req *) \ FN_SIG_S(nble_uas_rssi_calibrate_req, \ - const struct nble_uas_rssi_calibrate *) \ - FN_SIG_S(nble_gap_service_write_req, \ - const struct nble_gap_service_write_params *) \ + const struct nble_uas_rssi_calibrate_req *) \ + FN_SIG_S(nble_gap_service_req, \ + const struct nble_gap_service_req *) \ FN_SIG_S(nble_gap_disconnect_req, \ - const struct nble_gap_disconnect_req_params *) \ + const struct nble_gap_disconnect_req *) \ FN_SIG_S(nble_gattc_read_req, \ - const struct ble_gattc_read_params *) \ - FN_SIG_S(nble_gap_tx_power_req, \ - const struct nble_gap_tx_power_params *) \ - FN_SIG_S(nble_get_version_req, \ - const struct nble_gap_get_version_param *) + const struct nble_gattc_read_req *) \ + FN_SIG_S(nble_gap_set_tx_power_req, \ + const struct nble_gap_set_tx_power_req *) \ + FN_SIG_S(nble_dbg_req, const struct nble_dbg_req *) \ + FN_SIG_S(nble_sm_pairing_response_req, \ + const struct nble_sm_pairing_response_req *) \ + FN_SIG_S(nble_sm_error_req, \ + const struct nble_sm_error_req *) \ + FN_SIG_S(nble_dtm_cmd_req, \ + const struct nble_dtm_cmd_req *) #define LIST_FN_SIG_P \ - FN_SIG_P(nble_gap_dtm_init_req, void *) \ - FN_SIG_P(nble_gap_read_bda_req, void *) \ FN_SIG_P(nble_gap_stop_adv_req, void *) \ - FN_SIG_P(nble_gap_cancel_connect_req, void *) + FN_SIG_P(nble_get_version_req, ble_get_version_cb_t) \ + FN_SIG_P(nble_gap_cancel_connect_req, void *) \ + FN_SIG_P(nble_panic_req, void *) #define LIST_FN_SIG_S_B \ - FN_SIG_S_B(nble_gatt_register_req, \ - const struct nble_gatt_register_req *, \ + FN_SIG_S_B(nble_gatts_register_req, \ + const struct nble_gatts_register_req *, \ uint8_t *, uint16_t) \ - FN_SIG_S_B(nble_gatt_send_notif_req, \ - const struct nble_gatt_send_notif_params *, \ + FN_SIG_S_B(nble_gatts_notify_req, \ + const struct nble_gatts_notify_req *, \ const uint8_t *, uint16_t) \ - FN_SIG_S_B(nble_gatt_send_ind_req, \ - const struct nble_gatt_send_ind_params *, \ + FN_SIG_S_B(nble_gatts_indicate_req, \ + const struct nble_gatts_indicate_req *, \ const uint8_t *, uint8_t) \ - FN_SIG_S_B(nble_gatts_rd_reply_req, \ - const struct nble_gatts_rd_reply_params *, \ + FN_SIG_S_B(nble_gatts_read_reply_req, \ + const struct nble_gatts_read_reply_req *, \ uint8_t *, uint16_t) \ FN_SIG_S_B(nble_gattc_write_req, \ - const struct ble_gattc_write_params *, \ + const struct nble_gattc_write_req *, \ + const uint8_t *, uint16_t) \ + FN_SIG_S_B(nble_gattc_read_multi_req, \ + const struct nble_gattc_read_multi_req *, \ + const uint16_t *, uint16_t) \ + FN_SIG_S_B(nble_uart_test_req, \ + const struct nble_uart_test_req *, \ const uint8_t *, uint8_t) \ - FN_SIG_S_B(nble_gattc_read_multiple_req, \ - const struct ble_gattc_read_multiple_params *, \ - const uint16_t *, uint16_t) - -#define LIST_FN_SIG_B_B_P + FN_SIG_S_B(nble_gatts_write_reply_req, \ + const struct nble_gatts_write_reply_req *, \ + const uint8_t *, uint8_t) \ + FN_SIG_S_B(nble_storage_read_rsp_req, \ + const struct nble_storage_read_rsp_req *, \ + const uint8_t *, uint16_t) #define LIST_FN_SIG_S_P \ FN_SIG_S_P(nble_gap_connect_req, \ - const struct nble_gap_connect_req_params *, void *) \ + const struct nble_gap_connect_req *, void *) \ FN_SIG_S_P(nble_gap_set_rssi_report_req, \ - const struct nble_rssi_report_params *, void *) \ - FN_SIG_S_P(nble_gap_dbg_req, \ - const struct nble_debug_params *, \ - void *) - -#define LIST_FN_SIG_S_B_P - -#define LIST_FN_SIG_S_B_B_P + const struct nble_gap_set_rssi_report_req *, void *) #endif /* RPC_FUNCTIONS_TO_BLE_CORE_H_ */ diff --git a/system/libarc32_arduino101/drivers/rpc/rpc_functions_to_quark.h b/system/libarc32_arduino101/drivers/rpc/rpc_functions_to_quark.h index b08005e6..c2b345bd 100644 --- a/system/libarc32_arduino101/drivers/rpc/rpc_functions_to_quark.h +++ b/system/libarc32_arduino101/drivers/rpc/rpc_functions_to_quark.h @@ -20,81 +20,91 @@ #include "gap_internal.h" #include "gatt_internal.h" #include "gap_internal.h" +#include "dtm_internal.h" +#include "storage_internal.h" /* declare the list of functions sorted by signature */ -#define LIST_FN_SIG_NONE \ - FN_SIG_NONE(on_nble_up) +#define LIST_FN_SIG_NONE #define LIST_FN_SIG_S \ FN_SIG_S(on_nble_get_version_rsp, \ - const struct nble_version_response *) \ + const struct nble_get_version_rsp *) \ FN_SIG_S(on_nble_gap_connect_evt, \ const struct nble_gap_connect_evt *) \ FN_SIG_S(on_nble_gap_disconnect_evt, \ const struct nble_gap_disconnect_evt *) \ FN_SIG_S(on_nble_gap_conn_update_evt, \ const struct nble_gap_conn_update_evt *) \ - FN_SIG_S(on_nble_gap_sm_status_evt, \ - const struct nble_gap_sm_status_evt *) \ - FN_SIG_S(on_nble_gap_sm_passkey_display_evt, \ - const struct nble_gap_sm_passkey_disp_evt *) \ - FN_SIG_S(on_nble_gap_sm_passkey_req_evt, \ - const struct nble_gap_sm_passkey_req_evt *) \ + FN_SIG_S(on_nble_sm_status_evt, \ + const struct nble_sm_status_evt *) \ + FN_SIG_S(on_nble_sm_passkey_disp_evt, \ + const struct nble_sm_passkey_disp_evt *) \ + FN_SIG_S(on_nble_sm_passkey_req_evt, \ + const struct nble_sm_passkey_req_evt *) \ FN_SIG_S(on_nble_gap_rssi_evt, \ const struct nble_gap_rssi_evt *) \ FN_SIG_S(on_nble_common_rsp, \ - const struct nble_response *) \ + const struct nble_common_rsp *) \ FN_SIG_S(on_nble_gap_connect_rsp, \ - const struct nble_response *) \ + const struct nble_common_rsp *) \ FN_SIG_S(on_nble_gap_cancel_connect_rsp, \ - const struct nble_response *) \ - FN_SIG_S(on_nble_gap_read_bda_rsp, \ - const struct nble_service_read_bda_response *) \ - FN_SIG_S(on_nble_gap_sm_config_rsp, \ - struct nble_gap_sm_config_rsp *) \ - FN_SIG_S(on_nble_gap_sm_common_rsp, \ - const struct nble_gap_sm_response *) \ + const struct nble_common_rsp *) \ + FN_SIG_S(on_nble_get_bda_rsp, \ + const struct nble_get_bda_rsp *) \ + FN_SIG_S(on_nble_sm_config_rsp, \ + struct nble_sm_config_rsp *) \ + FN_SIG_S(on_nble_sm_common_rsp, \ + const struct nble_sm_common_rsp *) \ FN_SIG_S(on_nble_set_bda_rsp, \ const struct nble_set_bda_rsp *) \ FN_SIG_S(on_nble_gap_set_rssi_report_rsp, \ - const struct nble_response *) \ - FN_SIG_S(on_nble_gap_dbg_rsp, \ - const struct nble_debug_resp *) \ + const struct nble_common_rsp *) \ + FN_SIG_S(on_nble_dbg_rsp, \ + const struct nble_dbg_rsp *) \ FN_SIG_S(on_nble_gap_dir_adv_timeout_evt, \ const struct nble_gap_dir_adv_timeout_evt *) \ - FN_SIG_S(on_nble_gatts_send_notif_rsp, \ - const struct nble_gatt_notif_rsp *) \ - FN_SIG_S(on_nble_gatts_send_ind_rsp, \ - const struct nble_gatt_ind_rsp *) \ - FN_SIG_S(on_nble_gap_start_advertise_rsp, \ - const struct nble_response *) \ + FN_SIG_S(on_nble_gatts_notify_tx_evt, \ + const struct nble_gatts_notify_tx_evt *) \ + FN_SIG_S(on_nble_gatts_indicate_rsp, \ + const struct nble_gatts_indicate_rsp *) \ + FN_SIG_S(on_nble_gap_start_adv_rsp, \ + const struct nble_common_rsp *) \ FN_SIG_S(on_nble_gap_scan_start_stop_rsp, \ - const struct nble_response *) \ + const struct nble_common_rsp *) \ FN_SIG_S(on_nble_gatts_read_evt, \ - const struct nble_gatt_rd_evt *) \ + const struct nble_gatts_read_evt *) \ FN_SIG_S(on_nble_gatts_write_exec_evt, \ - const struct nble_gatt_wr_exec_evt *) \ + const struct nble_gatts_write_exec_evt *) \ FN_SIG_S(on_nble_uas_bucket_change, \ - const struct nble_uas_bucket_change *) \ + const struct nble_uas_bucket_change *) \ FN_SIG_S(on_nble_gattc_write_rsp, \ - const struct ble_gattc_write_rsp *) \ - FN_SIG_S(on_nble_gap_tx_power_rsp, \ - const struct nble_response *) + const struct nble_gattc_write_rsp *) \ + FN_SIG_S(on_nble_gap_set_tx_power_rsp, \ + const struct nble_common_rsp *) \ + FN_SIG_S(on_nble_sm_pairing_request_evt, \ + const struct nble_sm_pairing_request_evt *) \ + FN_SIG_S(on_nble_sm_security_request_evt, \ + const struct nble_sm_security_request_evt *) \ + FN_SIG_S(on_nble_dtm_rsp, \ + const struct nble_dtm_rsp *) \ + FN_SIG_S(on_nble_gap_rpa_update_evt, \ + const struct nble_gap_rpa_update_evt *) \ + FN_SIG_S(on_nble_storage_read_evt, \ + const struct nble_storage_read_evt *) -#define LIST_FN_SIG_P \ - FN_SIG_P(on_nble_gap_dtm_init_rsp, void *) +#define LIST_FN_SIG_P #define LIST_FN_SIG_S_B \ FN_SIG_S_B(nble_log, const struct nble_log_s *, char *, \ uint8_t) \ FN_SIG_S_B(on_nble_gattc_value_evt, \ - const struct ble_gattc_value_evt *, \ + const struct nble_gattc_value_evt *, \ uint8_t *, uint8_t) \ FN_SIG_S_B(on_nble_gatts_write_evt, \ - const struct nble_gatt_wr_evt *, \ + const struct nble_gatts_write_evt *, \ const uint8_t *, uint8_t) \ - FN_SIG_S_B(on_nble_gatt_register_rsp, \ - const struct nble_gatt_register_rsp *, \ + FN_SIG_S_B(on_nble_gatts_register_rsp, \ + const struct nble_gatts_register_rsp *, \ const struct nble_gatt_attr_handles *, \ uint8_t) \ FN_SIG_S_B(on_nble_gattc_discover_rsp, \ @@ -103,22 +113,22 @@ FN_SIG_S_B(on_nble_gap_adv_report_evt, \ const struct nble_gap_adv_report_evt *, \ const uint8_t *, uint8_t) \ - FN_SIG_S_B(on_nble_gap_sm_bond_info_rsp, \ - const struct nble_gap_sm_bond_info_rsp*, \ + FN_SIG_S_B(on_nble_sm_bond_info_rsp, \ + const struct nble_sm_bond_info_rsp *, \ const bt_addr_le_t *, uint16_t) \ FN_SIG_S_B(on_nble_gattc_read_rsp, \ - const struct ble_gattc_read_rsp *, \ - uint8_t *, uint8_t) \ - FN_SIG_S_B(on_nble_gattc_read_multiple_rsp, \ - const struct ble_gattc_read_rsp *, \ - uint8_t *, uint8_t) - -#define LIST_FN_SIG_B_B_P + const struct nble_gattc_read_rsp *, \ + uint8_t *, uint8_t) \ + FN_SIG_S_B(on_nble_gattc_read_multi_rsp, \ + const struct nble_gattc_read_rsp *, \ + uint8_t *, uint8_t) \ + FN_SIG_S_B(on_nble_uart_test_evt, \ + const struct nble_uart_test_evt *, \ + const uint8_t *, uint8_t) \ + FN_SIG_S_B(on_nble_storage_write_evt, \ + const struct nble_storage_write_evt *, \ + const uint8_t *, uint16_t) #define LIST_FN_SIG_S_P -#define LIST_FN_SIG_S_B_P - -#define LIST_FN_SIG_S_B_B_P - #endif /* RPC_FUNCTIONS_TO_QUARK_H_ */ diff --git a/system/libarc32_arduino101/drivers/rpc/rpc_serialize.c b/system/libarc32_arduino101/drivers/rpc/rpc_serialize.c index e2144ee3..c4a5e910 100644 --- a/system/libarc32_arduino101/drivers/rpc/rpc_serialize.c +++ b/system/libarc32_arduino101/drivers/rpc/rpc_serialize.c @@ -32,124 +32,151 @@ /* Build the functions exposed */ /* Define the functions identifiers per signature */ -#define FN_SIG_NONE(__fn) fn_index_##__fn, -#define FN_SIG_S(__fn, __s) FN_SIG_NONE(__fn) -#define FN_SIG_P(__fn, __type) FN_SIG_NONE(__fn) -#define FN_SIG_S_B(__fn, __s, __type, __length) FN_SIG_NONE(__fn) -#define FN_SIG_B_B_P(__fn, __type1, __length1, __type2, __length2,__type3) FN_SIG_NONE(__fn) -#define FN_SIG_S_P(__fn, __s, __type) FN_SIG_NONE(__fn) -#define FN_SIG_S_B_P(__fn, __s, __type, __length, __type_ptr) FN_SIG_NONE(__fn) -#define FN_SIG_S_B_B_P(__fn, __s, __type1, __length1, __type2, __length2,__type3) FN_SIG_NONE(__fn) - -/* Build the list of function indexes -> this should match the array at deserialization */ +#define FN_SIG_NONE(__fn) fn_index_##__fn, +#define FN_SIG_S(__fn, __s) FN_SIG_NONE(__fn) +#define FN_SIG_P(__fn, __type) FN_SIG_NONE(__fn) +#define FN_SIG_S_B(__fn, __s, __type, __length) FN_SIG_NONE(__fn) +#define FN_SIG_S_P(__fn, __s, __type) FN_SIG_NONE(__fn) + +/* Build the list of function indexes -> this should match the array at + * deserialization + */ enum { LIST_FN_SIG_NONE fn_none_index_max }; enum { LIST_FN_SIG_S fn_s_index_max }; enum { LIST_FN_SIG_P fn_p_index_max }; enum { LIST_FN_SIG_S_B fn_s_b_index_max }; -enum { LIST_FN_SIG_B_B_P fn_b_b_p_index_max }; enum { LIST_FN_SIG_S_P fn_s_p_index_max }; -enum { LIST_FN_SIG_S_B_P fn_s_b_p_index_max }; -enum { LIST_FN_SIG_S_B_B_P fn_s_b_b_p_index_max }; /* Implement the functions using serialization API */ #undef FN_SIG_NONE #undef FN_SIG_S #undef FN_SIG_P #undef FN_SIG_S_B -#undef FN_SIG_B_B_P #undef FN_SIG_S_P -#undef FN_SIG_S_B_P -#undef FN_SIG_S_B_B_P - -#define FN_SIG_NONE(__fn) \ - void __fn(void) { \ - rpc_serialize_none(fn_index_##__fn); \ - } \ - -#define FN_SIG_S(__fn, __s) \ - void __fn(__s p_s) { \ - rpc_serialize_s(fn_index_##__fn, p_s, sizeof(*p_s)); \ - } \ - -#define FN_SIG_P(__fn, __type) \ - void __fn(__type p_priv) { \ - rpc_serialize_p(fn_index_##__fn, p_priv); \ - } \ - -#define FN_SIG_S_B(__fn, __s, __type, __length) \ - void __fn(__s p_s, __type p_buf, __length length) { \ - rpc_serialize_s_b(fn_index_##__fn, p_s, sizeof(*p_s), p_buf, length); \ - } \ - -#define FN_SIG_B_B_P(__fn, __type1, __length1, __type2, __length2, __type3) \ - void __fn(__type1 p_buf1, __length1 length1, __type2 p_buf2, __length2 length2, __type3 p_priv) { \ - rpc_serialize_b_b_p(fn_index_##__fn, p_buf1, length1, p_buf2, length2, p_priv); \ - } \ - -#define FN_SIG_S_P(__fn, __s, __type) \ - void __fn(__s p_s, __type p_priv) { \ - rpc_serialize_s_p(fn_index_##__fn, p_s, sizeof(*p_s), p_priv); \ - } \ - -#define FN_SIG_S_B_P(__fn, __s, __type, __length, __type_ptr) \ - void __fn(__s p_s, __type p_buf, __length length, __type_ptr p_priv) { \ - rpc_serialize_s_b_p(fn_index_##__fn, p_s, sizeof(*p_s), p_buf, length, p_priv); \ - } - -#define FN_SIG_S_B_B_P(__fn, __s, __type1, __length1, __type2, __length2, __type3) \ - void __fn(__s p_s, __type1 p_buf1, __length1 length1, __type2 p_buf2, __length2 length2, __type3 p_priv) { \ - rpc_serialize_s_b_b_p(fn_index_##__fn, p_s, sizeof(*p_s), p_buf1, length1, p_buf2, length2, p_priv); \ - } \ +#define FN_SIG_NONE(__fn) \ + void __fn(void) \ + { \ + rpc_serialize_none(fn_index_##__fn); \ + } + +#define FN_SIG_S(__fn, __s) \ + void __fn(__s p_s) \ + { \ + rpc_serialize_s(fn_index_##__fn, p_s, sizeof(*p_s)); \ + } + +#define FN_SIG_P(__fn, __type) \ + void __fn(__type p_priv) \ + { \ + rpc_serialize_p(fn_index_##__fn, p_priv); \ + } + +#define FN_SIG_S_B(__fn, __s, __type, __length) \ + void __fn(__s p_s, __type p_buf, __length length) \ + { \ + rpc_serialize_s_b(fn_index_##__fn, p_s, sizeof(*p_s), \ + p_buf, length); \ + } + +#define FN_SIG_S_P(__fn, __s, __type) \ + void __fn(__s p_s, __type p_priv) \ + { \ + rpc_serialize_s_p(fn_index_##__fn, p_s, sizeof(*p_s), \ + p_priv); \ + } /* Build the functions */ LIST_FN_SIG_NONE LIST_FN_SIG_S LIST_FN_SIG_P LIST_FN_SIG_S_B -LIST_FN_SIG_B_B_P LIST_FN_SIG_S_P -LIST_FN_SIG_S_B_P -LIST_FN_SIG_S_B_B_P -#define SIG_TYPE_SIZE 1 -#define FN_INDEX_SIZE 1 -#define POINTER_SIZE 4 +#undef FN_SIG_NONE +#undef FN_SIG_S +#undef FN_SIG_P +#undef FN_SIG_S_B +#undef FN_SIG_S_P + +#define DJB2_HASH(__h, __v) ((__h << 5) + __h) + __v -static void _send(uint8_t *buf, uint16_t length) { - rpc_transmit_cb(buf, length); +#define FN_SIG_NONE(__fn) \ + hash = DJB2_HASH(hash, 1); + +#define FN_SIG_S(__fn, __s) \ + hash = DJB2_HASH(hash, 2); \ + hash = DJB2_HASH(hash, sizeof(*((__s)0))); + +#define FN_SIG_P(__fn, __type) \ + hash = DJB2_HASH(hash, 3); + +#define FN_SIG_S_B(__fn, __s, __type, __length) \ + hash = DJB2_HASH(hash, 4); \ + hash = DJB2_HASH(hash, sizeof(*((__s)0))); + +#define FN_SIG_S_P(__fn, __s, __type) \ + hash = DJB2_HASH(hash, 6); \ + hash = DJB2_HASH(hash, sizeof(*((__s)0))); + +uint32_t rpc_serialize_hash(void) +{ + uint32_t hash = 5381; + + LIST_FN_SIG_NONE; + LIST_FN_SIG_S; + LIST_FN_SIG_P; + LIST_FN_SIG_S_B; + LIST_FN_SIG_S_P; + + return hash; } -static uint16_t encoded_structlen(uint8_t structlen) { +#define SIG_TYPE_SIZE 1 +#define FN_INDEX_SIZE 1 +#define POINTER_SIZE 4 + +static void _send(uint8_t *buf) +{ + rpc_transmit_cb(buf); +} + +static uint16_t encoded_structlen(uint8_t structlen) +{ return 1 + structlen; } -static uint8_t *serialize_struct(uint8_t *p, const uint8_t *struct_data, uint8_t struct_length) { +static uint8_t *serialize_struct(uint8_t *p, const uint8_t *struct_data, + uint8_t struct_length) +{ *p++ = struct_length; memcpy(p, struct_data, struct_length); p += struct_length; return p; } -static uint16_t encoded_buflen(const uint8_t *buf, uint16_t buflen) { - if (NULL == buf) +static uint16_t encoded_buflen(const uint8_t *buf, uint16_t buflen) +{ + if (!buf) { return 1; - else { - if (buflen < (1 << 7)) { - return 1 + buflen; - } - else - return 2 + buflen; + } + + if (buflen < (1 << 7)) { + return 1 + buflen; + } else { + return 2 + buflen; } } -static uint8_t *serialize_buf(uint8_t *p, const uint8_t *buf, uint16_t buflen) { +static uint8_t *serialize_buf(uint8_t *p, const uint8_t *data, uint16_t len) +{ uint16_t varint; - if (NULL == buf) - buflen = 0; + if (!data) { + len = 0; + } - varint = buflen; + varint = len; *p = varint & 0x7F; if (varint >= (1 << 7)) { @@ -158,166 +185,125 @@ static uint8_t *serialize_buf(uint8_t *p, const uint8_t *buf, uint16_t buflen) { *p = varint >> 7; } p++; - memcpy(p, buf, buflen); - p += buflen; + memcpy(p, data, len); + p += len; return p; } -static uint8_t *serialize_p(uint8_t *p, uintptr_t priv) { - *p++ = priv; - *p++ = (priv >> 8); - *p++ = (priv >> 16); - *p++ = (priv >> 24); +static uint8_t *serialize_p(uint8_t *p, void *ptr) +{ + uintptr_t val = (uintptr_t)ptr; + + *p++ = val; + *p++ = (val >> 8); + *p++ = (val >> 16); + *p++ = (val >> 24); return p; } -void rpc_serialize_none(uint8_t fn_index) { - uint16_t length; - uint8_t * buf; - uint8_t * p; - - length = SIG_TYPE_SIZE + FN_INDEX_SIZE; +void rpc_serialize_none(uint8_t fn_index) +{ + uint8_t *buf; + uint8_t *p; - p = buf = rpc_alloc_cb(length); + buf = rpc_alloc_cb(SIG_TYPE_SIZE + FN_INDEX_SIZE); + p = buf; *p++ = SIG_TYPE_NONE; *p = fn_index; - _send(buf, length); + _send(buf); } -void rpc_serialize_s(uint8_t fn_index, const void * struct_data, uint8_t struct_length) { - uint16_t length; - uint8_t * buf; - uint8_t * p; +void rpc_serialize_s(uint8_t fn_index, const void *struct_data, + uint8_t struct_length) +{ + uint8_t *buf; + uint8_t *p; - length = SIG_TYPE_SIZE + FN_INDEX_SIZE + encoded_structlen(struct_length); - - p = buf = rpc_alloc_cb(length); + buf = rpc_alloc_cb(SIG_TYPE_SIZE + FN_INDEX_SIZE + + encoded_structlen(struct_length)); + p = buf; *p++ = SIG_TYPE_S; *p++ = fn_index; p = serialize_struct(p, struct_data, struct_length); - _send(buf, length); + _send(buf); } +void rpc_serialize_p(uint8_t fn_index, void *priv) +{ + uint8_t *buf; + uint8_t *p; -void rpc_serialize_p(uint8_t fn_index, void * p_priv) { - uint16_t length; - uint8_t * buf; - uint8_t * p; - uintptr_t priv = (uintptr_t) p_priv; - - length = SIG_TYPE_SIZE + FN_INDEX_SIZE + POINTER_SIZE; - - p = buf = rpc_alloc_cb(length); + buf = rpc_alloc_cb(SIG_TYPE_SIZE + FN_INDEX_SIZE + POINTER_SIZE); + p = buf; *p++ = SIG_TYPE_P; *p++ = fn_index; p = serialize_p(p, priv); - _send(buf, length); + _send(buf); } -void rpc_serialize_s_b(uint8_t fn_index, const void * struct_data, uint8_t struct_length, const void * vbuf, uint16_t vbuf_length) { - uint16_t length; - uint8_t * buf; - uint8_t * p; - - length = SIG_TYPE_SIZE + FN_INDEX_SIZE + encoded_structlen(struct_length) + - encoded_buflen(vbuf, vbuf_length); +void rpc_serialize_s_b(uint8_t fn_index, const void *struct_data, + uint8_t struct_length, const void *vbuf, + uint16_t vbuf_length) +{ + uint8_t *buf; + uint8_t *p; - p = buf = rpc_alloc_cb(length); + buf = rpc_alloc_cb(SIG_TYPE_SIZE + FN_INDEX_SIZE + + encoded_structlen(struct_length) + + encoded_buflen(vbuf, vbuf_length)); + p = buf; *p++ = SIG_TYPE_S_B; *p++ = fn_index; p = serialize_struct(p, struct_data, struct_length); p = serialize_buf(p, vbuf, vbuf_length); - _send(buf, length); -} - -void rpc_serialize_b_b_p(uint8_t fn_index, const void * vbuf1, uint16_t vbuf1_length, const void * vbuf2, uint16_t vbuf2_length, void * p_priv) { - uint16_t length; - uint8_t * buf; - uint8_t * p; - uintptr_t priv = (uintptr_t) p_priv; - - length = SIG_TYPE_SIZE + FN_INDEX_SIZE + encoded_buflen(vbuf1, vbuf1_length) + - encoded_buflen(vbuf2, vbuf2_length) + POINTER_SIZE; - - p = buf = rpc_alloc_cb(length); - - *p++ = SIG_TYPE_B_B_P; - *p++ = fn_index; - p = serialize_buf(p, vbuf1, vbuf1_length); - p = serialize_buf(p, vbuf2, vbuf2_length); - p = serialize_p(p, priv); - - _send(buf, length); + _send(buf); } -void rpc_serialize_s_p(uint8_t fn_index, const void * struct_data, uint8_t struct_length, void * p_priv) { - uint16_t length; - uint8_t * buf; - uint8_t * p; - uintptr_t priv = (uintptr_t) p_priv; +void rpc_serialize_s_p(uint8_t fn_index, const void *struct_data, + uint8_t struct_length, void *priv) +{ + uint8_t *buf; + uint8_t *p; - length = SIG_TYPE_SIZE + FN_INDEX_SIZE + encoded_structlen(struct_length) - + POINTER_SIZE; - - p = buf = rpc_alloc_cb(length); + buf = rpc_alloc_cb(SIG_TYPE_SIZE + FN_INDEX_SIZE + + encoded_structlen(struct_length) + POINTER_SIZE); + p = buf; *p++ = SIG_TYPE_S_P; *p++ = fn_index; p = serialize_struct(p, struct_data, struct_length); p = serialize_p(p, priv); - _send(buf, length); + _send(buf); } -void rpc_serialize_s_b_p(uint8_t fn_index, const void * struct_data, uint8_t struct_length, - const void * vbuf, uint16_t vbuf_length, void * p_priv) { - uint16_t length; - uint8_t * buf; - uint8_t * p; - uintptr_t priv = (uintptr_t) p_priv; - - length = SIG_TYPE_SIZE + FN_INDEX_SIZE + encoded_structlen(struct_length) + - encoded_buflen(vbuf, vbuf_length) + POINTER_SIZE; - - p = buf = rpc_alloc_cb(length); - - *p++ = SIG_TYPE_S_B_P; - *p++ = fn_index; - p = serialize_struct(p, struct_data, struct_length); - p = serialize_buf(p, vbuf, vbuf_length); - p = serialize_p(p, priv); - - _send(buf, length); -} - -void rpc_serialize_s_b_b_p(uint8_t fn_index, const void * struct_data, uint8_t struct_length, - const void * vbuf1, uint16_t vbuf1_length, const void * vbuf2, uint16_t vbuf2_length, void * p_priv) { - - uint16_t length; - uint8_t * buf; - uint8_t * p; - uintptr_t priv = (uintptr_t) p_priv; - - length = SIG_TYPE_SIZE + FN_INDEX_SIZE + encoded_structlen(struct_length) + - encoded_buflen(vbuf1, vbuf1_length) + - encoded_buflen(vbuf2, vbuf2_length) + POINTER_SIZE; - - p = buf = rpc_alloc_cb(length); - - *p++ = SIG_TYPE_S_B_B_P; - *p++ = fn_index; - p = serialize_struct(p, struct_data, struct_length); - p = serialize_buf(p, vbuf1, vbuf1_length); - p = serialize_buf(p, vbuf2, vbuf2_length); - p = serialize_p(p, priv); - - _send(buf, length); +void rpc_init(uint32_t version) +{ + uint8_t *buf; + uint8_t *p; + struct { + uint32_t version; + uint32_t ser_hash; + uint32_t des_hash; + } struct_data; + + struct_data.version = version; + struct_data.ser_hash = rpc_serialize_hash(); + struct_data.des_hash = rpc_deserialize_hash(); + buf = rpc_alloc_cb(SIG_TYPE_SIZE + FN_INDEX_SIZE + + encoded_structlen(sizeof(struct_data))); + + p = buf; + *p++ = SIG_TYPE_CONTROL; + *p++ = 0; + p = serialize_struct(p, (uint8_t *)&struct_data, sizeof(struct_data)); + _send(buf); } diff --git a/system/libarc32_arduino101/framework/include/os/os.h b/system/libarc32_arduino101/framework/include/os/os.h index 7f5103d9..6e92b5eb 100644 --- a/system/libarc32_arduino101/framework/include/os/os.h +++ b/system/libarc32_arduino101/framework/include/os/os.h @@ -202,4 +202,11 @@ extern OS_ERR_TYPE mutex_lock (T_MUTEX mutex, int timeout); /** @} */ +struct os_fifo { + T_QUEUE queue; +}; +void fifo_init(struct os_fifo *fifo); +void *fifo_get(struct os_fifo *fifo, int32_t timeout); +void fifo_put(struct os_fifo *fifo, void *data); + #endif diff --git a/system/libarc32_arduino101/framework/include/services/ble/ble_service.h b/system/libarc32_arduino101/framework/include/services/ble/ble_service.h index 8917e61c..99f91daf 100644 --- a/system/libarc32_arduino101/framework/include/services/ble/ble_service.h +++ b/system/libarc32_arduino101/framework/include/services/ble/ble_service.h @@ -217,20 +217,7 @@ struct ble_dbg_req_rsp { uint32_t u1; }; -/** Enable/Disable BLE stack. To be called before any BLE service related call. - * - * @param p_service_conn client service connection (cfw service connection) - * @param enable 1: enable BLE stack 0: disable BLE stack - * @param p_config configuration parameters when enabling BLE. shall be null in case of BLE disable. @ref ble_enable_config - * @param p_priv pointer to private structure returned in a response - * - * @return @ref OS_ERR_TYPE - * @note Expected notification: - * - Message with @ref MSG_ID_BLE_ENABLE_RSP and type @ref ble_enable_rsp. - */ -int ble_service_enable(cfw_service_conn_t * p_service_conn, uint8_t enable, - const struct ble_enable_config * p_config, - void *p_priv); +void ble_enable(); /** @endcond */ /** @}*/ diff --git a/system/libarc32_arduino101/framework/src/os/os.c b/system/libarc32_arduino101/framework/src/os/os.c index f9e6faa3..4bf4f0cd 100644 --- a/system/libarc32_arduino101/framework/src/os/os.c +++ b/system/libarc32_arduino101/framework/src/os/os.c @@ -30,52 +30,11 @@ #include "cfw/cfw.h" #include "os/os.h" - -/************************* MEMORY *************************/ - - -#if 0 - -#ifdef TRACK_ALLOCS #include "infra/log.h" -int alloc_count = 0; -#endif +#include "misc/util.h" -void * cfw_alloc(int size, OS_ERR_TYPE * err) { - void * ptr; - unsigned int flags = interrupt_lock(); - ptr = malloc(size+sizeof(void*)); - if (ptr != NULL) { - (*(int*) ptr) = size; -#ifdef TRACK_ALLOCS - alloc_count++; - pr_info(0, "alloc_count - %d", alloc_count); -#endif - interrupt_unlock(flags); - return ptr; - } else - return 0; -} - -void cfw_free(void * ptr, OS_ERR_TYPE * err) { - int flags = interrupt_lock(); -#ifdef TRACK_ALLOCS - alloc_count--; - pr_info(0, "alloc_countf - %d", alloc_count); -#endif - free(ptr); - interrupt_unlock(flags); -} - -void * balloc(uint32_t size, OS_ERR_TYPE *err) { - return cfw_alloc(size, err); -} - -OS_ERR_TYPE bfree(void *ptr) { - cfw_free(ptr, NULL); - return E_OS_OK; -} -#endif +/************************* MEMORY *************************/ +// See the balloc.c /************************* QUEUES *************************/ @@ -85,7 +44,7 @@ typedef struct queue_ { int used; } q_t; -q_t q_pool[10]; +static q_t q_pool[10]; void queue_put(void *queue, void *msg) { q_t * q = (q_t*) queue; @@ -116,15 +75,24 @@ void queue_send_message (T_QUEUE queue, T_QUEUE_MESSAGE message, OS_ERR_TYPE* er T_QUEUE queue_create(uint32_t max_size, OS_ERR_TYPE*err) { int i, found=0; - q_t * q; - for (i=0;i<10; i++) { + q_t * q = NULL; + + for (i = 0; i < ARRAY_SIZE(q_pool); i++) + { q = &q_pool[i]; - if (q->used == 0) { + if (q->used == 0) + { q->used = 1; found = 1; + break; } } - if (!found) return (T_QUEUE)NULL; + + if (!found) + { + return (T_QUEUE)NULL; + } + list_init(&q->lh); q->count = 0; return (T_QUEUE) q; @@ -161,3 +129,23 @@ OS_ERR_TYPE mutex_lock(T_MUTEX mutex, int timeout) { return E_OS_OK; } + +// FIFO +void fifo_init(struct os_fifo *fifo) +{ + if (fifo->queue == NULL) + { + fifo->queue = queue_create (10, NULL); + } +} + +void *fifo_get(struct os_fifo *fifo, int32_t timeout) +{ + return queue_wait(fifo->queue); +} + +void fifo_put(struct os_fifo *fifo, void *data) +{ + queue_put(fifo->queue, data); +} + diff --git a/system/libarc32_arduino101/framework/src/services/ble/conn.c b/system/libarc32_arduino101/framework/src/services/ble/conn.c index c0aa9014..b17c7f07 100644 --- a/system/libarc32_arduino101/framework/src/services/ble/conn.c +++ b/system/libarc32_arduino101/framework/src/services/ble/conn.c @@ -30,19 +30,18 @@ /* #define BT_GATT_DEBUG 1 */ -extern void on_nble_curie_log(char *fmt, ...); extern void __assert_fail(void); #ifdef BT_GATT_DEBUG -#define BT_DBG(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_ERR(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_WARN(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_INFO(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_DBG(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_ERR(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_WARN(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_INFO(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) #define BT_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) #else #define BT_DBG(fmt, ...) do {} while (0) -#define BT_ERR(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_WARN(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_INFO(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_ERR(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_WARN(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_INFO(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) #define BT_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) #endif @@ -89,6 +88,23 @@ void notify_le_param_updated(struct bt_conn *conn) } #if defined(CONFIG_BLUETOOTH_SMP) +void bt_conn_identity_resolved(struct bt_conn *conn) +{ + const bt_addr_le_t *rpa; + struct bt_conn_cb *cb; + + if (conn->role == BT_HCI_ROLE_MASTER) { + rpa = &conn->le.resp_addr; + } else { + rpa = &conn->le.init_addr; + } + + for (cb = callback_list; cb; cb = cb->_next) { + if (cb->identity_resolved) { + cb->identity_resolved(conn, rpa, &conn->le.dst); + } + } +} void bt_conn_security_changed(struct bt_conn *conn) { @@ -311,6 +327,7 @@ void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state) /* Actions needed for entering the new state */ switch (conn->state) { case BT_CONN_CONNECTED: + atomic_clear_bit(conn->flags, BT_CONN_DIR_ADV_CONNECT); bt_l2cap_connected(conn); notify_connected(conn); break; @@ -326,6 +343,9 @@ void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state) } else if (old_state == BT_CONN_CONNECT) { /* conn->err will be set in this case */ notify_connected(conn); + } else if (old_state == BT_CONN_CONNECT_SCAN && conn->err) { + /* this indicate LE Create Connection failed */ + notify_connected(conn); } /* Release the reference we took for the very first @@ -403,7 +423,7 @@ struct bt_conn *bt_conn_lookup_state_le(const bt_addr_le_t *peer, continue; } - if (bt_addr_le_cmp(peer, BT_ADDR_LE_ANY) && + if (peer && bt_addr_le_cmp(peer, BT_ADDR_LE_ANY) && bt_addr_le_cmp(peer, &conns[i].le.dst)) { continue; } @@ -416,6 +436,24 @@ struct bt_conn *bt_conn_lookup_state_le(const bt_addr_le_t *peer, return NULL; } +void bt_conn_disconnect_all(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(conns); i++) { + struct bt_conn *conn = &conns[i]; + + if (!atomic_get(&conn->ref)) { + continue; + } + + if (conn->state == BT_CONN_CONNECTED) { + bt_conn_disconnect(conn, + BT_HCI_ERR_REMOTE_USER_TERM_CONN); + } + } +} + struct bt_conn *bt_conn_ref(struct bt_conn *conn) { atomic_inc(&conn->ref); @@ -441,19 +479,11 @@ int bt_conn_get_info(const struct bt_conn *conn, struct bt_conn_info *info) switch (conn->type) { case BT_CONN_TYPE_LE: if (conn->role == BT_HCI_ROLE_MASTER) { -#if 0 info->le.src = &conn->le.init_addr; info->le.dst = &conn->le.resp_addr; -#else - info->le.dst = &conn->le.dst; -#endif } else { -#if 0 info->le.src = &conn->le.resp_addr; info->le.dst = &conn->le.init_addr; -#else - info->le.src = &conn->le.dst; -#endif } info->le.interval = conn->le.interval; info->le.latency = conn->le.latency; @@ -472,11 +502,11 @@ int bt_conn_get_info(const struct bt_conn *conn, struct bt_conn_info *info) static int bt_hci_disconnect(struct bt_conn *conn, uint8_t reason) { - struct nble_gap_disconnect_req_params ble_gap_disconnect; + struct nble_gap_disconnect_req params; - ble_gap_disconnect.conn_handle = conn->handle; - ble_gap_disconnect.reason = reason; - nble_gap_disconnect_req(&ble_gap_disconnect); + params.conn_handle = conn->handle; + params.reason = reason; + nble_gap_disconnect_req(¶ms); bt_conn_set_state(conn, BT_CONN_DISCONNECT); return 0; @@ -488,9 +518,9 @@ static int bt_hci_connect_le_cancel(struct bt_conn *conn) return 0; } -void on_nble_gap_cancel_connect_rsp(const struct nble_response *params) +void on_nble_gap_cancel_connect_rsp(const struct nble_common_rsp *par) { - struct bt_conn *conn = params->user_data; + struct bt_conn *conn = par->user_data; conn->err = BT_HCI_ERR_INSUFFICIENT_RESOURCES; bt_conn_set_state(conn, BT_CONN_DISCONNECTED); @@ -513,9 +543,15 @@ int bt_conn_disconnect(struct bt_conn *conn, uint8_t reason) case BT_CONN_CONNECT_SCAN: conn->err = BT_HCI_ERR_INSUFFICIENT_RESOURCES; bt_conn_set_state(conn, BT_CONN_DISCONNECTED); - /* scan update not yet implemented */ + bt_le_scan_update(false); return 0; case BT_CONN_CONNECT: + /* Check if directed advertising was initiated */ + if (atomic_test_and_clear_bit(conn->flags, BT_CONN_DIR_ADV_CONNECT)) { + conn->err = BT_HCI_ERR_REMOTE_USER_TERM_CONN; + bt_conn_set_state(conn, BT_CONN_DISCONNECTED); + return bt_le_adv_stop(); + } return bt_hci_connect_le_cancel(conn); case BT_CONN_CONNECTED: return bt_hci_disconnect(conn, reason); @@ -527,56 +563,52 @@ int bt_conn_disconnect(struct bt_conn *conn, uint8_t reason) } } -static bool valid_adv_params(const struct nble_gap_adv_params *params) +static bool valid_adv_params(const struct bt_le_adv_param *param) { - if (params->type == BT_LE_ADV_DIRECT_IND) { - /* If high duty, ensure interval is 0 */ - if (params->interval_max != 0) - return false; - - if (params->timeout != 0) - return false; - } else if (params->type == BT_LE_ADV_DIRECT_IND_LOW_DUTY) { - if (params->interval_min < 0x20) - return false; - } else { + if (!(param->options & BT_LE_ADV_OPT_CONNECTABLE)) return false; - } - if (params->interval_min > params->interval_max) - return false; + /* In case of high duty cycle, interval is 0 */ + if (param->interval_min == 0) + return true; - if (params->interval_max > 0x4000) + if (param->interval_min > param->interval_max || + param->interval_min < 0x0020 || param->interval_max > 0x4000) { return false; + } return true; } +#if defined(CONFIG_BLUETOOTH_CENTRAL) +int bt_le_set_auto_conn(bt_addr_le_t *addr, + const struct bt_le_conn_param *param) +{ + return -EINVAL; +} +#endif /* CONFIG_BLUETOOTH_CENTRAL */ + struct bt_conn *bt_conn_create_slave_le(const bt_addr_le_t *peer, const struct bt_le_adv_param *param) { struct bt_conn *conn; /* Timeout is handled by application timer */ /* forced to none currently (no whitelist support) */ - struct nble_gap_adv_params params = { + struct nble_gap_set_adv_params_req params = { .interval_max = param->interval_max, .interval_min = param->interval_min, - .type = param->type, + .type = BT_LE_ADV_DIRECT_IND, .timeout = 0, .filter_policy = 0 }; - bt_addr_le_copy(¶ms.peer_bda, peer); - - if (!valid_adv_params(¶ms)) { + if (!valid_adv_params(param)) { return NULL; } - if (param->type == BT_LE_ADV_DIRECT_IND_LOW_DUTY) { - params.type = BT_LE_ADV_DIRECT_IND; - } + bt_addr_le_copy(¶ms.peer_bda, peer); - if (atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { + if (atomic_test_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING)) { return NULL; } @@ -586,37 +618,20 @@ struct bt_conn *bt_conn_create_slave_le(const bt_addr_le_t *peer, return NULL; } + atomic_set_bit(conn->flags, BT_CONN_DIR_ADV_CONNECT); + bt_conn_set_state(conn, BT_CONN_CONNECT); nble_gap_set_adv_params_req(¶ms); - nble_gap_start_adv_req(); + set_advertise_enable(); + + atomic_set_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING); return conn; } #if defined(CONFIG_BLUETOOTH_CENTRAL) -static int hci_le_create_conn(struct bt_conn *conn) -{ - struct nble_gap_connect_req_params conn_params; - - conn_params.bda = conn->le.dst; - conn_params.conn_params.interval_min = conn->le.interval_min; - conn_params.conn_params.interval_max = conn->le.interval_max; - conn_params.conn_params.slave_latency = conn->le.latency; - conn_params.conn_params.link_sup_to = conn->le.timeout; - - conn_params.scan_params.interval = sys_cpu_to_le16(BT_GAP_SCAN_FAST_INTERVAL); - conn_params.scan_params.window = conn_params.scan_params.interval; - conn_params.scan_params.selective = 0; - conn_params.scan_params.active = 1; - conn_params.scan_params.timeout = 0; - - nble_gap_connect_req(&conn_params, conn); - - return 0; -} - -void on_nble_gap_connect_rsp(const struct nble_response *params) +void on_nble_gap_connect_rsp(const struct nble_common_rsp *params) { struct bt_conn *conn = params->user_data; @@ -632,13 +647,23 @@ struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer, { struct bt_conn *conn; + BT_ERR("%s %d", __FUNCTION__, __LINE__); + BT_ERR("%s %d: min-%d, max-%d, latency-%d, timeout-%d", __FUNCTION__, __LINE__, + param->interval_min, param->interval_max, + param->latency, param->timeout); + if (!bt_le_conn_params_valid(param->interval_min, param->interval_max, param->latency, param->timeout)) { return NULL; } - /* if (atomic_test_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) */ - /* return NULL; */ + BT_ERR("%s %d", __FUNCTION__, __LINE__); + + if (atomic_test_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) { + return NULL; + } + + BT_ERR("%s %d", __FUNCTION__, __LINE__); conn = bt_conn_lookup_addr_le(peer); if (conn) { @@ -655,33 +680,26 @@ struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer, } } + BT_ERR("%s %d", __FUNCTION__, __LINE__); + conn = bt_conn_add_le(peer); if (!conn) { return NULL; } -#if 0 - bt_conn_set_state(conn, BT_CONN_CONNECT_SCAN); - bt_le_scan_update(true); -#endif - - bt_addr_le_copy(&conn->le.dst, peer); + BT_ERR("%s %d", __FUNCTION__, __LINE__); bt_conn_set_param_le(conn, param); - /* for the time being, the implementation bypassed the scan procedure */ - if (hci_le_create_conn(conn)) { - goto done; - } + bt_conn_set_state(conn, BT_CONN_CONNECT_SCAN); - bt_conn_set_state(conn, BT_CONN_CONNECT); + bt_le_scan_update(true); -done: return conn; } #else -void on_nble_gap_connect_rsp(const struct nble_response *params) +void on_nble_gap_connect_rsp(const struct nble_common_rsp *params) { } @@ -815,14 +833,14 @@ int bt_conn_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey) return -EINVAL; } -int bt_conn_auth_passkey_confirm(struct bt_conn *conn, bool match) +int bt_conn_auth_passkey_confirm(struct bt_conn *conn) { if (!bt_auth) { return -EINVAL; }; #if defined(CONFIG_BLUETOOTH_SMP) if (conn->type == BT_CONN_TYPE_LE) { - return bt_smp_auth_passkey_confirm(conn, match); + return bt_smp_auth_passkey_confirm(conn); } #endif /* CONFIG_BLUETOOTH_SMP */ @@ -848,24 +866,24 @@ int bt_conn_auth_cancel(struct bt_conn *conn) return -EINVAL; } -int bt_conn_remove_info(const bt_addr_le_t *addr) +int bt_conn_auth_pairing_confirm(struct bt_conn *conn) { - struct bt_conn *conn; - - /* TODO: implement address specific removal */ - if (bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) + if (!bt_auth) { return -EINVAL; + } - do { - conn = bt_conn_lookup_state_le(addr, BT_CONN_CONNECTED); - if (conn) { - bt_conn_unref(conn); - bt_conn_disconnect(conn, - BT_HCI_ERR_REMOTE_USER_TERM_CONN); - } - } while(conn); - - return bt_smp_remove_info(addr); + switch (conn->type) { +#if defined(CONFIG_BLUETOOTH_SMP) + case BT_CONN_TYPE_LE: + return bt_smp_auth_pairing_confirm(conn); +#endif /* CONFIG_BLUETOOTH_SMP */ +#if defined(CONFIG_BLUETOOTH_BREDR) + case BT_CONN_TYPE_BR: + return ssp_confirm_reply(conn); +#endif /* CONFIG_BLUETOOTH_BREDR */ + default: + return -EINVAL; + } } #endif /* CONFIG_BLUETOOTH_SMP || CONFIG_BLUETOOTH_BREDR */ @@ -896,7 +914,7 @@ int bt_conn_init(void) int bt_conn_le_conn_update(struct bt_conn *conn, const struct bt_le_conn_param *param) { - struct nble_gap_connect_update_params ble_gap_connect_update; + struct nble_gap_conn_update_req params; #if 0 struct hci_cp_le_conn_update *conn_update; struct net_buf *buf; @@ -915,13 +933,13 @@ int bt_conn_le_conn_update(struct bt_conn *conn, conn_update->conn_latency = sys_cpu_to_le16(param->latency); conn_update->supervision_timeout = sys_cpu_to_le16(param->timeout); #endif - ble_gap_connect_update.conn_handle = conn->handle; - ble_gap_connect_update.params.interval_min = param->interval_min; - ble_gap_connect_update.params.interval_max = param->interval_max; - ble_gap_connect_update.params.slave_latency = param->latency; - ble_gap_connect_update.params.link_sup_to = param->timeout; + params.conn_handle = conn->handle; + params.params.interval_min = param->interval_min; + params.params.interval_max = param->interval_max; + params.params.slave_latency = param->latency; + params.params.link_sup_to = param->timeout; - nble_gap_conn_update_req(&ble_gap_connect_update); + nble_gap_conn_update_req(¶ms); return 0; } diff --git a/system/libarc32_arduino101/framework/src/services/ble/conn_internal.h b/system/libarc32_arduino101/framework/src/services/ble/conn_internal.h index 04c08839..7846da76 100644 --- a/system/libarc32_arduino101/framework/src/services/ble/conn_internal.h +++ b/system/libarc32_arduino101/framework/src/services/ble/conn_internal.h @@ -25,15 +25,15 @@ typedef enum { /* bt_conn flags: the flags defined here represent connection parameters */ enum { BT_CONN_AUTO_CONNECT, + BT_CONN_DIR_ADV_CONNECT, }; struct bt_conn_le { bt_addr_le_t dst; -#if 0 bt_addr_le_t init_addr; bt_addr_le_t resp_addr; -#endif + uint16_t interval; uint16_t interval_min; uint16_t interval_max; @@ -55,6 +55,7 @@ struct bt_conn { uint16_t handle; uint8_t type; uint8_t role; + atomic_t flags[1]; #if defined(CONFIG_BLUETOOTH_SMP) uint8_t encrypt; @@ -87,6 +88,8 @@ struct bt_conn *bt_conn_add_br(const bt_addr_t *peer); struct bt_conn *bt_conn_lookup_addr_br(const bt_addr_t *peer); #endif +void bt_conn_disconnect_all(void); + /* Look up an existing connection */ struct bt_conn *bt_conn_lookup_handle(uint16_t handle); diff --git a/system/libarc32_arduino101/framework/src/services/ble/dtm.c b/system/libarc32_arduino101/framework/src/services/ble/dtm.c new file mode 100644 index 00000000..9517c713 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble/dtm.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include + +#include +#include "dtm_internal.h" + +extern void __assert_fail(void); +#define BT_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) + +void on_nble_dtm_rsp(const struct nble_dtm_rsp *rsp) { + struct ble_dtm_rsp ret; + + ret.status = rsp->status; + ret.nb = rsp->nb; + + rsp->func(&ret, rsp->user_data); +} + +int ble_dtm_cmd(struct dtm_cmd_params *params) { + + struct nble_dtm_cmd_req req; + + if (!params || !params->func) { + return -EINVAL; + } + + memset(&req, 0, sizeof(req)); + switch(params->cmd_type) { + case DTM_START_RX: + req.tx_rx_freq = params->rx.freq; + break; + case DTM_START_TX: + req.tx_rx_freq = params->tx.freq; + req.tx_len = params->tx.len; + req.tx_pattern = params->tx.pattern; + break; + case DTM_SET_TXPOWER: + req.pwr_dbm = params->tx_pwr.dbm; + break; + case DTM_START_TX_CARRIER: + req.tx_rx_freq = params->tx.freq; + break; + case DTM_END: + break; + default: + return -EINVAL; + } + + req.cmd_type = params->cmd_type; + req.func = params->func; + req.user_data = params->user_data; + + nble_dtm_cmd_req(&req); + + return 0; +} diff --git a/system/libarc32_arduino101/framework/src/services/ble/gap.c b/system/libarc32_arduino101/framework/src/services/ble/gap.c index 26858281..6ea60a85 100644 --- a/system/libarc32_arduino101/framework/src/services/ble/gap.c +++ b/system/libarc32_arduino101/framework/src/services/ble/gap.c @@ -20,6 +20,8 @@ #include #include +#include +#include "storage_internal.h" #include "gap_internal.h" #include "conn_internal.h" @@ -31,29 +33,33 @@ /* #define BT_GATT_DEBUG 1 */ -extern void on_nble_curie_log(char *fmt, ...); +#ifndef __weak +#define __weak __attribute__((weak)) +#endif + extern void __assert_fail(void); #ifdef BT_GATT_DEBUG -#define BT_DBG(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_ERR(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_WARN(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_INFO(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_DBG(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_ERR(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_WARN(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_INFO(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) #define BT_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) #else #define BT_DBG(fmt, ...) do {} while (0) -#define BT_ERR(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_WARN(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_INFO(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_ERR(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_WARN(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_INFO(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) #define BT_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) #endif static bt_ready_cb_t bt_ready_cb; static bt_le_scan_cb_t *scan_dev_found_cb; static rssi_report_t rssi_report_cb; +static const struct bt_storage *bt_storage; struct bt_dev bt_dev; -static int set_advertise_enable(void) +int set_advertise_enable(void) { #if 0 struct net_buf *buf; @@ -106,24 +112,20 @@ static int set_advertise_disable(void) return 0; } -void ble_gap_get_bonding_info(ble_bond_info_cb_t func, void *user_data, - bool include_bonded_addrs) +void ble_gap_get_bda_info(struct bt_local_addr *addr) { - struct nble_gap_sm_bond_info_param params; - - params.cb = func; - params.user_data = user_data; - params.include_bonded_addrs = include_bonded_addrs; - - nble_gap_sm_bond_info_req(¶ms); + bt_addr_le_copy(&addr->id_addr, &bt_dev.id_addr); +#if defined(CONFIG_BLUETOOTH_PRIVACY) + bt_addr_le_copy(&addr->rpa, &bt_dev.random_addr); +#endif } -void on_nble_gap_start_advertise_rsp(const struct nble_response *params) +void on_nble_gap_start_adv_rsp(const struct nble_common_rsp *par) { - if (params->status == 0) + if (par->status == 0) atomic_set_bit(bt_dev.flags, BT_DEV_ADVERTISING); else - BT_WARN("start advertise failed with %d", params->status); + BT_WARN("start advertise failed with %d", par->status); } void on_nble_gap_disconnect_evt(const struct nble_gap_disconnect_evt *evt) @@ -230,21 +232,27 @@ void on_nble_gap_connect_evt(const struct nble_gap_connect_evt *evt) conn->le.timeout = evt->conn_values.supervision_to; conn->role = evt->role_slave; -#if 0 - src.type = BT_ADDR_LE_PUBLIC; - memcpy(src.val, bt_dev.bdaddr.val, sizeof(bt_dev.bdaddr.val)); - /* use connection address (instead of identity address) as initiator * or responder address */ + if (conn->role == BT_HCI_ROLE_MASTER) { - bt_addr_le_copy(&conn->le.init_addr, &src); - bt_addr_le_copy(&conn->le.resp_addr, &evt->peer_addr); + bt_addr_le_copy(&conn->le.resp_addr, &evt->peer_bda); + + /* init_addr doesn't need updating here since it was + * already set during previous steps. + */ } else { - bt_addr_le_copy(&conn->le.init_addr, &evt->peer_addr); - bt_addr_le_copy(&conn->le.resp_addr, &src); + bt_addr_le_copy(&conn->le.init_addr, &evt->peer_bda); + +#if defined(CONFIG_BLUETOOTH_PRIVACY) + bt_addr_le_copy(&conn->le.resp_addr, &bt_dev.random_addr); +#else + /* id_addr is equal with peer_bda */ + bt_addr_le_copy(&conn->le.resp_addr, &evt->peer_bda); +#endif /* CONFIG_BLUETOOTH_PRIVACY */ } -#endif + bt_conn_set_state(conn, BT_CONN_CONNECTED); /* Note: Connection update removed because Windows interop and BT spec recommendations */ @@ -256,47 +264,6 @@ void on_nble_gap_connect_evt(const struct nble_gap_connect_evt *evt) } -void on_nble_gap_adv_report_evt(const struct nble_gap_adv_report_evt *evt, - const uint8_t *buf, uint8_t len) -{ -#if TODO_IMPLEMENT_CONNECTION - uint8_t num_reports = buf->data[0]; - struct bt_hci_ev_le_advertising_info *info; - - BT_DBG("Adv number of reports %u", num_reports); - - info = net_buf_pull(buf, sizeof(num_reports)); - - while (num_reports--) { - int8_t rssi = info->data[info->length]; - const bt_addr_le_t *addr; - - BT_DBG("%s event %u, len %u, rssi %d dBm", - bt_addr_le_str(&info->addr), - info->evt_type, info->length, rssi); - - addr = find_id_addr(&info->addr); -#endif - - BT_DBG("nble gap: event:%u, len %u", evt->adv_type, len); - - if (scan_dev_found_cb) { - scan_dev_found_cb(&evt->addr, evt->rssi, evt->adv_type, - buf, len); - } -#if TODO_IMPLEMENT_CONNECTION -#if defined(CONFIG_BLUETOOTH_CONN) - check_pending_conn(addr, &info->addr, info->evt_type); -#endif /* CONFIG_BLUETOOTH_CONN */ - /* Get next report iteration by moving pointer to right offset - * in buf according to spec 4.2, Vol 2, Part E, 7.7.65.2. - */ - info = net_buf_pull(buf, sizeof(*info) + info->length + - sizeof(rssi)); - } -#endif -} - void on_nble_gap_conn_update_evt(const struct nble_gap_conn_update_evt *evt) { struct bt_conn *conn; @@ -361,11 +328,12 @@ int bt_conn_update_param_le(struct bt_conn *conn, #endif } -void on_nble_gap_scan_start_stop_rsp(const struct nble_response *rsp) +void on_nble_gap_scan_start_stop_rsp(const struct nble_common_rsp *rsp) { - if (rsp->status) + if (rsp->status) { BT_INFO("scan start/stop failed: %d", rsp->status); - /* TODO: clear scanning bit atomic_clear_bit(bt_dev.flags, BT_DEV_SCANNING) */ + atomic_clear_bit(bt_dev.flags, BT_DEV_SCANNING); + } } static int bt_hci_stop_scanning(void) @@ -405,6 +373,7 @@ static int bt_hci_stop_scanning(void) return err; #endif + atomic_clear_bit(bt_dev.flags, BT_DEV_SCANNING); nble_gap_stop_scan_req(); @@ -412,90 +381,162 @@ static int bt_hci_stop_scanning(void) } #if defined(CONFIG_BLUETOOTH_CENTRAL) -int bt_le_set_auto_conn(bt_addr_le_t *addr, - const struct bt_le_conn_param *param) +static int hci_le_create_conn(struct bt_conn *conn) { - return -EINVAL; -} -#endif /* CONFIG_BLUETOOTH_CENTRAL */ + struct nble_gap_connect_req conn_params; + memset(&conn_params, 0, sizeof(conn_params)); + + conn_params.bda = conn->le.dst; + conn_params.conn_params.interval_min = conn->le.interval_min; + conn_params.conn_params.interval_max = conn->le.interval_max; + conn_params.conn_params.slave_latency = conn->le.latency; + conn_params.conn_params.link_sup_to = conn->le.timeout; -static int start_le_scan(uint8_t scan_type, uint16_t interval, uint16_t window, - uint8_t filter_dup) + conn_params.scan_params.interval = BT_GAP_SCAN_FAST_INTERVAL; + conn_params.scan_params.window = conn_params.scan_params.interval; + + nble_gap_connect_req(&conn_params, conn); + + return 0; +} + +static void check_pending_conn(const bt_addr_le_t *id_addr, + const bt_addr_le_t *addr, uint8_t evtype) { - struct nble_gap_scan_params params = { - .interval = interval, - .window = window, - .scan_type = scan_type, - }; + struct bt_conn *conn; -#ifdef NOT_USED_FOR_NOW - struct net_buf *buf, *rsp; - struct bt_hci_cp_le_set_scan_params *set_param; - struct bt_hci_cp_le_set_scan_enable *scan_enable; - int err; + /* No connections are allowed during explicit scanning */ + if (atomic_test_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) { + return; + } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_SCAN_PARAMS, - sizeof(*set_param)); - if (!buf) { - return -ENOBUFS; + /* Return if event is not connectable */ + if (evtype != BT_LE_ADV_IND && evtype != BT_LE_ADV_DIRECT_IND) { + return; } + conn = bt_conn_lookup_state_le(id_addr, BT_CONN_CONNECT_SCAN); + if (!conn) { + return; + } - set_param = net_buf_add(buf, sizeof(*set_param)); - memset(set_param, 0, sizeof(*set_param)); - set_param->scan_type = scan_type; + if (bt_hci_stop_scanning()) { + goto failed; + } - /* for the rest parameters apply default values according to - * spec 4.2, vol2, part E, 7.8.10 - */ - set_param->interval = sys_cpu_to_le16(interval); - set_param->window = sys_cpu_to_le16(window); - set_param->filter_policy = 0x00; +#if defined(CONFIG_BLUETOOTH_PRIVACY) + if (le_set_rpa()) { + return; + } + conn->le.init_addr.type = BT_ADDR_LE_RANDOM; +#else + bt_addr_le_copy(&conn->le.init_addr, &bt_dev.id_addr); +#endif /* CONFIG_BLUETOOTH_PRIVACY */ - if (scan_type == BT_HCI_LE_SCAN_ACTIVE) { - err = le_set_nrpa(); - if (err) { - net_buf_unref(buf); - return err; - } + bt_addr_le_copy(&conn->le.resp_addr, addr); - set_param->addr_type = BT_ADDR_LE_RANDOM; - } else { - set_param->addr_type = BT_ADDR_LE_PUBLIC; + if (hci_le_create_conn(conn)) { + goto failed; } - bt_hci_cmd_send(BT_HCI_OP_LE_SET_SCAN_PARAMS, buf); - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_SCAN_ENABLE, - sizeof(*scan_enable)); - if (!buf) { - return -ENOBUFS; + bt_conn_set_state(conn, BT_CONN_CONNECT); + bt_conn_unref(conn); + return; + +failed: + conn->err = BT_HCI_ERR_UNSPECIFIED; + bt_conn_set_state(conn, BT_CONN_DISCONNECTED); + bt_conn_unref(conn); + bt_le_scan_update(false); +} +#endif + +void on_nble_gap_adv_report_evt(const struct nble_gap_adv_report_evt *evt, + const uint8_t *buf, uint8_t len) +{ + BT_DBG("nble gap: event:%u, len %u", evt->adv_type, len); + + if (scan_dev_found_cb) { + scan_dev_found_cb(&evt->addr, evt->rssi, evt->adv_type, + buf, len); } +#if defined(CONFIG_BLUETOOTH_CENTRAL) + check_pending_conn(&evt->addr, &evt->addr, evt->adv_type); +#endif /* CONFIG_BLUETOOTH_CENTRAL */ +} +#if 0 +static int set_random_address(const bt_addr_t *addr) +{ + struct nble_set_bda_req req = {0}; - scan_enable = net_buf_add(buf, sizeof(*scan_enable)); - memset(scan_enable, 0, sizeof(*scan_enable)); - scan_enable->filter_dup = filter_dup; - scan_enable->enable = BT_HCI_LE_SCAN_ENABLE; + memcpy(&req.bda.a, addr, sizeof(bt_addr_t)); + req.bda.type = BT_ADDR_LE_RANDOM; + req.cb = NULL; - err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_SCAN_ENABLE, buf, &rsp); + nble_set_bda_req(&req); + return 0; +} + +static int le_set_nrpa(void) +{ + bt_addr_t nrpa = {{0}}; + + nrpa.val[5] &= 0x3f; + + return set_random_address(&nrpa); +} +#endif + +#if defined(CONFIG_BLUETOOTH_PRIVACY) +int le_set_rpa(void) +{ + bt_addr_t rpa = {0}; + + /* Set the two most significant bits to 01 (indicating an RPA) */ + rpa.val[5] &= 0x3f; + rpa.val[5] |= 0x40; + + return set_random_address(&rpa); +} +#endif + +static int start_le_scan(uint8_t scan_type, uint16_t interval, uint16_t window, + uint8_t filter_dup) +{ + struct nble_gap_start_scan_req params; +#if 0 + int err; + +#if defined(CONFIG_BLUETOOTH_PRIVACY) + err = le_set_rpa(); if (err) { return err; } - /* Update scan state in case of success (0) status */ - err = rsp->data[0]; - if (!err) { - atomic_set_bit(bt_dev.flags, BT_DEV_SCANNING); +#else + if (scan_type == BT_HCI_LE_SCAN_ACTIVE) { + /* only set NRPA if there is no advertising ongoing */ + if (!atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { + err = le_set_nrpa(); + if (err) { + return err; + } + } } - - net_buf_unref(rsp); #endif +#endif + params.scan_params.interval = interval; + params.scan_params.window = window; + params.scan_params.scan_type = scan_type; + params.scan_params.use_whitelist = 0; + + atomic_set_bit(bt_dev.flags, BT_DEV_SCANNING); nble_gap_start_scan_req(¶ms); return 0; } -#if NOT_USED_FOR_NOW /* Used to determine whether to start scan and which scan type should be used */ int bt_le_scan_update(bool fast_scan) { @@ -538,7 +579,61 @@ int bt_le_scan_update(bool fast_scan) return 0; #endif /* CONFIG_BLUETOOTH_CENTRAL */ } + +static void update_le_oob_local(const bt_addr_le_t *addr) +{ + if (bt_addr_le_is_identity(addr)) { + bt_addr_le_copy(&bt_dev.id_addr, addr); + } else if (bt_addr_le_is_rpa(addr)) { + bt_addr_le_copy(&bt_dev.random_addr, addr); + } +} + +static void nble_get_bda_cb_init(const bt_addr_le_t *bda, void *user_data) +{ + update_le_oob_local(bda); +} + +static int common_init(void) +{ +#if 0 + struct nble_get_bda_req req; + + req.cb = nble_get_bda_cb_init; + req.user_data =NULL; + + /* read nble identity address */ + nble_get_bda_req(&req); #endif + return 0; +} + +static int hci_init(void) +{ + if (bt_storage) { + int ret; + struct nble_set_bda_req params; + + ret = bt_storage->read(NULL, BT_STORAGE_ID_ADDR, ¶ms.bda, + sizeof(params.bda)); + + if (!ret) { + params.cb = NULL; + params.user_data = NULL; + + nble_set_bda_req(¶ms); + /* nble_get_bda_req() returns the set address but this + * ensures that bt_le_oob_get_local() reads a valid + * address independent of nble async response speed */ + update_le_oob_local(¶ms.bda); + return 0; + } + /* in no provisioned bda available -> use nble one */ + } + BT_DBG("no id addr provisioned"); + + return common_init(); +} static int bt_init(void) { @@ -553,9 +648,9 @@ static int bt_init(void) BT_ERR("HCI driver open failed (%d)", err); return err; } - - err = hci_init(); #endif + err = hci_init(); + if (!err) { err = bt_conn_init(); @@ -572,20 +667,28 @@ static int bt_init(void) return err; } -void on_nble_up(void) +void version_at_init_cb(const struct nble_version *ver) { - BT_DBG("%s", __FUNCTION__); if (bt_ready_cb) bt_ready_cb(bt_init()); } -extern void on_nble_curie_init(void); +void rpc_init_cb(uint32_t version, bool compatible) +{ + /* Retrieve the Nordic version */ + ble_gap_get_version(version_at_init_cb); +} + +__weak +void nble_curie_unreset_hook(void) +{ +} int bt_enable(bt_ready_cb_t cb) { bt_ready_cb = cb; - on_nble_curie_init(); + nble_curie_unreset_hook(); if (!cb) { return bt_init(); @@ -597,35 +700,27 @@ int bt_enable(bt_ready_cb_t cb) static bool valid_adv_param(const struct bt_le_adv_param *param) { - switch (param->type) { - case BT_LE_ADV_IND: - case BT_LE_ADV_SCAN_IND: - case BT_LE_ADV_NONCONN_IND: - break; - default: - return false; - } - -#if 0 - /* checks done in Nordic */ - switch (param->addr_type) { - case BT_LE_ADV_ADDR_IDENTITY: - case BT_LE_ADV_ADDR_NRPA: - break; - default: - return false; + if (!(param->options & BT_LE_ADV_OPT_CONNECTABLE)) { + /* + * BT Core 4.2 [Vol 2, Part E, 7.8.5] + * The Advertising_Interval_Min and Advertising_Interval_Max + * shall not be set to less than 0x00A0 (100 ms) if the + * Advertising_Type is set to ADV_SCAN_IND or ADV_NONCONN_IND. + */ + if (param->interval_min < 0x00a0) { + return false; + } } if (param->interval_min > param->interval_max || param->interval_min < 0x0020 || param->interval_max > 0x4000) { return false; } -#endif return true; } -static int set_ad(struct bt_eir_data *p_ad_data, +static int set_ad(struct nble_eir_data *p_ad_data, const struct bt_data *ad, size_t ad_len) { int i; @@ -652,15 +747,13 @@ int bt_le_adv_start(const struct bt_le_adv_param *param, const struct bt_data *sd, size_t sd_len) { int err; - struct nble_gap_adv_params set_param = {0}; - struct nble_gap_ad_data_params data; + struct nble_gap_set_adv_params_req set_param = {0}; + struct nble_gap_set_adv_data_req data = {{0}, {0}}; if (!valid_adv_param(param)) { return -EINVAL; } - memset(&data, 0, sizeof(data)); - if (atomic_test_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING)) { return -EALREADY; } @@ -675,10 +768,15 @@ int bt_le_adv_start(const struct bt_le_adv_param *param, } /* - * Don't bother with scan response if the advertising type isn't - * a scannable one. + * We need to set SCAN_RSP when enabling advertising type that allows + * for Scan Requests. + * + * If sd was not provided but we enable connectable undirected + * advertising sd needs to be cleared from values set by previous calls. + * Clearing sd is done by calling set_ad() with NULL data and zero len. + * So following condition check is unusual but correct. */ - if (param->type == BT_LE_ADV_IND || param->type == BT_LE_ADV_SCAN_IND) { + if (sd || (param->options & BT_LE_ADV_OPT_CONNECTABLE)) { err = set_ad(&data.sd, sd, sd_len); if (err) { return err; @@ -692,23 +790,29 @@ int bt_le_adv_start(const struct bt_le_adv_param *param, set_param.filter_policy = 0; set_param.interval_max = param->interval_max; set_param.interval_min = param->interval_min; - set_param.type = param->type; + + if (param->options & BT_LE_ADV_OPT_CONNECTABLE) { + set_param.type = BT_LE_ADV_IND; + } else { + if (sd) { + set_param.type = BT_LE_ADV_SCAN_IND; + } else { + set_param.type = BT_LE_ADV_NONCONN_IND; + } + } + nble_gap_set_adv_params_req(&set_param); -#if 0 - if (param->addr_type == BT_LE_ADV_ADDR_NRPA) { - err = le_set_nrpa(); - if (err) { - net_buf_unref(buf); +#if defined(CONFIG_BLUETOOTH_PRIVACY) + if (set_param.type == BT_LE_ADV_IND) { + err = le_set_rpa(); + if (err) return err; - } - - set_param->own_addr_type = BT_ADDR_LE_RANDOM; } else { - set_param->own_addr_type = BT_ADDR_LE_PUBLIC; + err = le_set_nrpa(); + if (err) + return err; } - - bt_hci_cmd_send(BT_HCI_OP_LE_SET_ADV_PARAMETERS, buf); #endif err = set_advertise_enable(); @@ -721,13 +825,16 @@ int bt_le_adv_start(const struct bt_le_adv_param *param, return 0; } -void on_nble_gap_dir_adv_timeout_evt(const struct nble_gap_dir_adv_timeout_evt *p_evt) +void on_nble_gap_dir_adv_timeout_evt(const struct nble_gap_dir_adv_timeout_evt *evt) { struct bt_conn *conn = bt_conn_lookup_state_le(BT_ADDR_LE_ANY, BT_CONN_CONNECT); if (conn) { atomic_clear_bit(bt_dev.flags, BT_DEV_ADVERTISING); - conn->err = p_evt->error; + if (atomic_test_and_clear_bit(conn->flags, BT_CONN_DIR_ADV_CONNECT)) { + atomic_clear_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING); + } + conn->err = evt->error; bt_conn_set_state(conn, BT_CONN_DISCONNECTED); bt_conn_unref(conn); } @@ -787,7 +894,7 @@ int bt_le_scan_start(const struct bt_le_scan_param *param, bt_le_scan_cb_t cb) if (!valid_le_scan_param(param)) { return -EINVAL; } -#if NOT_USED_FOR_NOW + /* Return if active scan is already enabled */ if (atomic_test_and_set_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) { return -EALREADY; @@ -800,16 +907,13 @@ int bt_le_scan_start(const struct bt_le_scan_param *param, bt_le_scan_cb_t cb) return err; } } -#endif err = start_le_scan(param->type, param->interval, param->window, param->filter_dup); if (err) { -#if NOT_USED_FOR_NOW atomic_clear_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN); -#endif return err; } @@ -820,86 +924,246 @@ int bt_le_scan_start(const struct bt_le_scan_param *param, bt_le_scan_cb_t cb) int bt_le_scan_stop(void) { -#if NOT_USED_FOR_NOW /* Return if active scanning is already disabled */ if (!atomic_test_and_clear_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) { return -EALREADY; } -#endif + scan_dev_found_cb = NULL; -#if NOT_USED_FOR_NOW return bt_le_scan_update(false); -#else - return bt_hci_stop_scanning(); -#endif } /* Temporary RSSI patch for UAS: RPC need definition if UAS not compiled */ -__attribute__((weak)) +__weak void on_nble_uas_bucket_change(const struct nble_uas_bucket_change *p_params) { } -void ble_gap_set_rssi_report(struct nble_rssi_report_params *params, +void ble_gap_set_rssi_report(struct ble_rssi_report_params *par, struct bt_conn *conn, rssi_report_resp_t resp_cb, rssi_report_t evt_cb) { + struct nble_gap_set_rssi_report_req req; rssi_report_cb = evt_cb; - params->conn_handle = conn->handle; + req.conn_handle = conn->handle; + req.op = par->op; + req.channel = par->channel; + req.delta_dBm = par->delta_dBm; + req.min_count = par->min_count; - nble_gap_set_rssi_report_req(params, resp_cb); + nble_gap_set_rssi_report_req(&req, resp_cb); } -void on_nble_gap_set_rssi_report_rsp(const struct nble_response *params) +void on_nble_gap_set_rssi_report_rsp(const struct nble_common_rsp *rsp) { - rssi_report_resp_t resp_cb = params->user_data; + rssi_report_resp_t resp_cb = rsp->user_data; if (resp_cb) - resp_cb(params->status); + resp_cb(rsp->status); } -void on_nble_gap_rssi_evt(const struct nble_gap_rssi_evt *event) +void on_nble_gap_rssi_evt(const struct nble_gap_rssi_evt *evt) { if (rssi_report_cb) - rssi_report_cb(event->rssi_data); + rssi_report_cb(evt->rssi_data); } void ble_gap_set_tx_power(int8_t tx_power) { - struct nble_gap_tx_power_params params = { + struct nble_gap_set_tx_power_req params = { .tx_power = tx_power, }; - nble_gap_tx_power_req(¶ms); + nble_gap_set_tx_power_req(¶ms); } -void on_nble_gap_tx_power_rsp(const struct nble_response *params) +void on_nble_gap_tx_power_rsp(const struct nble_common_rsp *rsp) { } void ble_gap_get_version(ble_get_version_cb_t func) { - struct nble_gap_get_version_param params; + nble_get_version_req(func); +} + +void on_nble_get_version_rsp(const struct nble_get_version_rsp *rsp) +{ + ble_get_version_cb_t cb = rsp->cb; - params.cb = func; + if (cb) { + cb(&rsp->ver); + } +} - nble_get_version_req(¶ms); +void on_nble_set_bda_rsp(const struct nble_set_bda_rsp *rsp) +{ + update_le_oob_local(&rsp->bda); + + if (rsp->cb) { + rsp->cb(rsp->status, rsp->user_data, &rsp->bda); + } } -void on_nble_get_version_rsp(const struct nble_version_response *par) +void on_nble_get_bda_rsp(const struct nble_get_bda_rsp *rsp) { - struct nble_gap_get_version_param param = par->params; - ble_get_version_cb_t cb = param.cb; + if (rsp->cb) { + rsp->cb(&rsp->bda, rsp->user_data); + } +} - if (cb) { - cb(&par->ver); +__weak +void on_nble_uart_test_evt(const struct nble_uart_test_evt *evt, + const uint8_t *data, uint8_t len) +{ +} + +int bt_le_oob_get_local(struct bt_le_oob *oob) +{ +#if defined(CONFIG_BLUETOOTH_PRIVACY) + bt_addr_le_copy(&oob->addr, &bt_dev.random_addr); +#else + bt_addr_le_copy(&oob->addr, &bt_dev.id_addr); +#endif /* CONFIG_BLUETOOTH_PRIVACY */ + + return 0; +} + +void on_nble_gap_rpa_update_evt(const struct nble_gap_rpa_update_evt *evt) +{ +#if defined(CONFIG_BLUETOOTH_PRIVACY) + /* Update the RPA address */ + bt_addr_le_copy(&bt_dev.random_addr, &evt->addr); +#endif /* CONFIG_BLUETOOTH_PRIVACY */ +} + +/* storage interface */ +void bt_storage_register(const struct bt_storage *storage) +{ + bt_storage = storage; +} + +void on_nble_storage_read_evt(const struct nble_storage_read_evt *evt) +{ + struct nble_storage_read_rsp_req req; + int len; + + req.status = -ENOTSUP; + req.addr = evt->addr; + req.key = evt->key; + + switch (evt->key) { + case BT_STORAGE_ID_ADDR: + len = sizeof(bt_addr_le_t); + break; + + case BT_STORAGE_ADDRESSES: + len = sizeof(bt_addr_le_t) * evt->max_num_keys; + break; + + case BT_STORAGE_SLAVE_LTK: + case BT_STORAGE_LTK: + len = sizeof(struct bt_storage_ltk); + break; + + case BT_STORAGE_IRK: + len = 16; /* irk[16] */ + break; + + default: + len = 64; /* P256 key */ + break; + } + + BT_DBG("nble_storage_rd_evt(key:0x%x) len:%d", evt->key, len); + + if (bt_storage) { + uint8_t data[len]; + + req.status = bt_storage->read(&evt->addr, evt->key, data, len); + + if (req.status < 0) { + BT_DBG("storage rd failed ret:%d", req.status); + len = 0; + } else { + if (evt->key != BT_STORAGE_ADDRESSES) { + BT_ASSERT(req.status == len); + } + + len = req.status; + req.status = 0; + } + + nble_storage_read_rsp_req(&req, data, len); + } else { + BT_DBG("No storage driver!"); + nble_storage_read_rsp_req(&req, NULL, 0); } } +void on_nble_storage_write_evt(const struct nble_storage_write_evt *evt, + const uint8_t *data, uint16_t len) +{ + int ret; + + if (!bt_storage) { + BT_DBG("No storage driver!"); + return; + } + + ret = bt_storage->write(&evt->addr, evt->key, data, len); + if (0 > ret) { + BT_ERR("storage write failed ret:%d", ret); + } + BT_DBG("storage wr(key:0x%x len:%d)", evt->key, len); +} + +int bt_storage_clear(bt_addr_le_t *addr) +{ +#if defined(CONFIG_BLUETOOTH_SMP) + struct nble_sm_clear_bonds_req params; + + memset(¶ms, 0, sizeof(params)); +#endif + if (addr) { + struct bt_conn *conn; + + conn = bt_conn_lookup_addr_le(addr); + if (conn) { + bt_conn_disconnect(conn, + BT_HCI_ERR_REMOTE_USER_TERM_CONN); + bt_conn_unref(conn); + } + +#if defined(CONFIG_BLUETOOTH_SMP) + bt_addr_le_copy(¶ms.addr, addr); + nble_sm_clear_bonds_req(¶ms); +#endif + + if (bt_storage) { + return bt_storage->clear(addr); + } + + return 0; + } + + bt_conn_disconnect_all(); + +#if defined(CONFIG_BLUETOOTH_SMP) + /* BT_ADDR_LE_ANY clears all */ + nble_sm_clear_bonds_req(¶ms); +#endif + + if (bt_storage) { + return bt_storage->clear(NULL); + } + + return 0; +} + void bt_le_set_device_name(char *device_name, int len) { - struct nble_gap_service_write_params gap_service_params; + struct nble_gap_service_req gap_service_params; if (len > 20) len = 20; memset(&gap_service_params, 0, sizeof(gap_service_params)); @@ -907,17 +1171,34 @@ void bt_le_set_device_name(char *device_name, int len) gap_service_params.name.len = len; gap_service_params.name.sec_mode = 0x11;// GAP_SEC_LEVEL_1 | GAP_SEC_MODE_1; memcpy(gap_service_params.name.name_array, device_name, len); - nble_gap_service_write_req(&gap_service_params); + nble_gap_service_req(&gap_service_params); } void bt_le_set_mac_address(bt_addr_le_t bda) { // Update the MAC addr - struct nble_set_bda_params params; + struct nble_set_bda_req params; params.cb = NULL; params.user_data = NULL; params.bda = bda; nble_set_bda_req(¶ms); + nble_get_bda_cb_init(&bda, NULL); } +void on_nble_common_rsp(const struct nble_common_rsp *rsp) +{ + if (rsp->status) { + BT_ERR("Last request failed, error %d", rsp->status); + return; + } + + BT_DBG("status %d", rsp->status); +} + +void on_nble_gap_set_tx_power_rsp(const struct nble_common_rsp *rsp) +{ + /* stub */ +} + + diff --git a/system/libarc32_arduino101/framework/src/services/ble/gatt.c b/system/libarc32_arduino101/framework/src/services/ble/gatt.c index fe5ce8e0..f831572b 100644 --- a/system/libarc32_arduino101/framework/src/services/ble/gatt.c +++ b/system/libarc32_arduino101/framework/src/services/ble/gatt.c @@ -25,22 +25,23 @@ #include "gatt_internal.h" #include "hci_core.h" #include "conn_internal.h" +#include "gap_internal.h" /* #define BT_GATT_DEBUG 1 */ - -extern void on_nble_curie_log(char *fmt, ...); +#include "os/os.h" extern void __assert_fail(void); +#define TICKS_NONE 0 #ifdef BT_GATT_DEBUG -#define BT_DBG(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_ERR(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_WARN(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_INFO(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_DBG(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_ERR(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_WARN(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_INFO(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) #define BT_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) #else #define BT_DBG(fmt, ...) do {} while (0) -#define BT_ERR(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_WARN(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_INFO(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_ERR(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_WARN(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_INFO(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) #define BT_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) #endif @@ -51,12 +52,16 @@ struct ble_gatt_service { uint16_t attr_count; /* Number of attributes in the array */ }; -struct ble_gatts_flush_all { - struct bt_conn *conn; - int status; - uint8_t flag; +struct prep_data { + void *nano_fifo_data; + const struct bt_gatt_attr *attr; + uint16_t offset; + uint8_t len; + uint8_t *buf; }; +static struct os_fifo prep_queue; + static struct ble_gatt_service db[CONFIG_BT_GATT_BLE_MAX_SERVICES]; static uint8_t db_cnt; @@ -83,9 +88,8 @@ static uint8_t bt_gatt_uuid_memcpy(uint8_t *buf, /* Store the UUID data */ if (uuid->type == BT_UUID_TYPE_16) { uint16_t le16; - - memcpy(&le16, &BT_UUID_16(uuid)->val, sizeof(le16)); - le16 = sys_cpu_to_le16(le16); + + le16 = sys_cpu_to_le16(BT_UUID_16(uuid)->val); memcpy(ptr, &le16, sizeof(le16)); ptr += sizeof(le16); } else { @@ -142,7 +146,7 @@ static int attr_read(struct bt_gatt_attr *attr, uint8_t *data, size_t len) int bt_gatt_register(struct bt_gatt_attr *attrs, size_t count) { size_t attr_table_size, i; - struct nble_gatt_register_req param; + struct nble_gatts_register_req param; /* TODO: Replace the following with net_buf */ uint8_t attr_table[N_BLE_BUF_SIZE]; @@ -161,7 +165,7 @@ int bt_gatt_register(struct bt_gatt_attr *attrs, size_t count) for (i = 0; i < count; i++) { struct bt_gatt_attr *attr = &attrs[i]; - struct ble_gatt_attr *att; + struct nble_gatts_attr *att; int data_size; if (attr_table_size + sizeof(*att) > sizeof(attr_table)) { @@ -169,6 +173,7 @@ int bt_gatt_register(struct bt_gatt_attr *attrs, size_t count) } att = (void *)&attr_table[attr_table_size]; + att->attr = attr; att->perm = attr->perm; /* Read attribute data */ @@ -189,11 +194,11 @@ int bt_gatt_register(struct bt_gatt_attr *attrs, size_t count) attr_table_size += (sizeof(*att) + att->data_size + 3) & ~3; } - nble_gatt_register_req(¶m, attr_table, attr_table_size); + nble_gatts_register_req(¶m, attr_table, attr_table_size); return 0; } -void on_nble_gatt_register_rsp(const struct nble_gatt_register_rsp *rsp, +void on_nble_gatts_register_rsp(const struct nble_gatts_register_rsp *rsp, const struct nble_gatt_attr_handles *handles, uint8_t len) { @@ -209,12 +214,10 @@ void on_nble_gatt_register_rsp(const struct nble_gatt_register_rsp *rsp, for (i = 0; i < rsp->attr_count; i++) { if (handles[i].handle != 0) { - uint16_t le16; - memcpy(&le16, &BT_UUID_16(rsp->attr_base[i].uuid)->val, sizeof(le16)); BT_DBG("gatt: i %d, h %d, type %d, u16 0x%x", i, handles[i].handle, rsp->attr_base[i].uuid->type, - le16); + BT_UUID_16(rsp->attr_base[i].uuid)->val); } } } @@ -248,10 +251,7 @@ ssize_t bt_gatt_attr_read_service(struct bt_conn *conn, struct bt_uuid *uuid = attr->user_data; if (uuid->type == BT_UUID_TYPE_16) { - uint16_t uuid16; - - memcpy(&uuid16, &BT_UUID_16(uuid)->val, sizeof(uuid16)); - uuid16 = sys_cpu_to_le16(uuid16); + uint16_t uuid16 = sys_cpu_to_le16(BT_UUID_16(uuid)->val); return bt_gatt_attr_read(conn, attr, buf, len, offset, &uuid16, 2); @@ -261,36 +261,20 @@ ssize_t bt_gatt_attr_read_service(struct bt_conn *conn, BT_UUID_128(uuid)->val, 16); } -struct gatt_incl { - uint16_t start_handle; - uint16_t end_handle; - uint16_t uuid16; -} __packed; - ssize_t bt_gatt_attr_read_included(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { - struct bt_gatt_include *incl = attr->user_data; - struct gatt_incl pdu; - uint8_t value_len; + struct bt_gatt_attr *incl = attr->user_data; - pdu.start_handle = sys_cpu_to_le16(incl->start_handle); - pdu.end_handle = sys_cpu_to_le16(incl->end_handle); - value_len = sizeof(pdu.start_handle) + sizeof(pdu.end_handle); - - /* - * Core 4.2, Vol 3, Part G, 3.2, - * The Service UUID shall only be present when the UUID is a 16-bit - * Bluetooth UUID. - */ - if (incl->uuid->type == BT_UUID_TYPE_16) { - memcpy(&pdu.uuid16, &BT_UUID_16(incl->uuid)->val, sizeof(pdu.uuid16)); - pdu.uuid16 = sys_cpu_to_le16(pdu.uuid16); - value_len += sizeof(pdu.uuid16); + /* nble gatt register case reading user_data. */ + if (!conn) { + return bt_gatt_attr_read(conn, attr, buf, len, offset, &incl, + sizeof(incl)); } - return bt_gatt_attr_read(conn, attr, buf, len, offset, &pdu, value_len); + /* nble handles gattc reads internally */ + return -EINVAL; } struct gatt_chrc { @@ -332,8 +316,7 @@ ssize_t bt_gatt_attr_read_chrc(struct bt_conn *conn, value_len = sizeof(pdu.properties) + sizeof(pdu.value_handle); if (chrc->uuid->type == BT_UUID_TYPE_16) { - memcpy(&pdu.uuid16, &BT_UUID_16(chrc->uuid)->val, sizeof(pdu.uuid16)); - pdu.uuid16 = sys_cpu_to_le16(pdu.uuid16); + pdu.uuid16 = sys_cpu_to_le16(BT_UUID_16(chrc->uuid)->val); value_len += 2; } else { memcpy(pdu.uuid, BT_UUID_128(chrc->uuid)->val, 16); @@ -434,7 +417,7 @@ static void gatt_ccc_changed(struct _bt_gatt_ccc *ccc) if (value != ccc->value) { ccc->value = value; if (ccc->cfg_changed) - ccc->cfg_changed(value); + ccc->cfg_changed(ccc->user_data, value); } } @@ -464,26 +447,20 @@ static bool is_bonded(const bt_addr_le_t *addr) ssize_t bt_gatt_attr_write_ccc(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, - uint16_t len, uint16_t offset) + uint16_t len, uint16_t offset, uint8_t flags) { struct _bt_gatt_ccc *ccc = attr->user_data; const uint16_t *data = buf; size_t i; - //BT_DBG("%s", __FUNCTION__); - if (offset > sizeof(*data)) { return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET); } - //BT_DBG("%s1", __FUNCTION__); - if (offset + len > sizeof(*data)) { return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN); } - //BT_DBG("%s2", __FUNCTION__); - for (i = 0; i < ccc->cfg_len; i++) { /* Check for existing configuration */ if (!bt_addr_le_cmp(&ccc->cfg[i].peer, &conn->le.dst)) { @@ -491,8 +468,6 @@ ssize_t bt_gatt_attr_write_ccc(struct bt_conn *conn, } } - //BT_DBG("%s3", __FUNCTION__); - if (i == ccc->cfg_len) { for (i = 0; i < ccc->cfg_len; i++) { /* Check for unused configuration */ @@ -512,12 +487,9 @@ ssize_t bt_gatt_attr_write_ccc(struct bt_conn *conn, } } - //BT_DBG("%s len-%p", __FUNCTION__, ccc); - ccc->cfg[i].value = sys_le16_to_cpu(*data); - //BT_DBG("%s 5len-%d", __FUNCTION__, len); - //BT_DBG("handle 0x%04x value %u", attr->handle, *data); + BT_DBG("handle 0x%04x value %u", attr->handle, *data); /* Update cfg if don't match */ if (ccc->value != *data) { @@ -571,33 +543,33 @@ static int att_notify(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *data, size_t len, bt_gatt_notify_sent_func_t cb) { - struct nble_gatt_send_notif_params notif; + struct nble_gatts_notify_req req; - notif.conn_handle = conn->handle; - notif.params.attr = attr; - notif.params.offset = 0; - notif.cback = cb; + req.params.conn_handle = conn->handle; + req.params.attr = attr; + req.params.offset = 0; + req.cback = cb; - nble_gatt_send_notif_req(¬if, data, len); + nble_gatts_notify_req(&req, data, len); return 0; } -void on_nble_gatts_send_notif_rsp(const struct nble_gatt_notif_rsp *rsp) +void on_nble_gatts_notify_tx_evt(const struct nble_gatts_notify_tx_evt *evt) { struct bt_conn *conn; - conn = bt_conn_lookup_handle(rsp->conn_handle); + conn = bt_conn_lookup_handle(evt->conn_handle); if (conn) { - if (rsp->cback) { - rsp->cback(conn, rsp->attr, rsp->status); + if (evt->cback) { + evt->cback(conn, evt->attr, (uint8_t)evt->status); } bt_conn_unref(conn); } } -void on_nble_gatts_send_ind_rsp(const struct nble_gatt_ind_rsp *rsp) +void on_nble_gatts_indicate_rsp(const struct nble_gatts_indicate_rsp *rsp) { struct bt_conn *conn; @@ -614,14 +586,14 @@ void on_nble_gatts_send_ind_rsp(const struct nble_gatt_ind_rsp *rsp) static int att_indicate(struct bt_conn *conn, struct bt_gatt_indicate_params *params) { - struct nble_gatt_send_ind_params ind; + struct nble_gatts_indicate_req req; - ind.conn_handle = conn->handle; - ind.cback = params->func; - ind.params.attr = params->attr; - ind.params.offset = 0; + req.params.conn_handle = conn->handle; + req.params.attr = params->attr; + req.params.offset = 0; + req.cback = params->func; - nble_gatt_send_ind_req(&ind, params->data, params->len); + nble_gatts_indicate_req(&req, params->data, params->len); return 0; } @@ -664,7 +636,12 @@ static uint8_t notify_cb(const struct bt_gatt_attr *attr, void *user_data) } conn = bt_conn_lookup_addr_le(&ccc->cfg[i].peer); - if (!conn || conn->state != BT_CONN_CONNECTED) {//Bug here + if (!conn) { + continue; + } + + if (conn->state != BT_CONN_CONNECTED) { + bt_conn_unref(conn); continue; } @@ -804,6 +781,11 @@ static uint8_t disconnected_cb(const struct bt_gatt_attr *attr, void *user_data) bt_conn_unref(tmp); } + } else { + /* Clear value if not paired */ + if (!ccc->cfg[i].valid) + memset(&ccc->cfg[i].value, 0, + sizeof(ccc->cfg[i].value)); } } @@ -811,7 +793,7 @@ static uint8_t disconnected_cb(const struct bt_gatt_attr *attr, void *user_data) memset(&ccc->value, 0, sizeof(ccc->value)); if (ccc->cfg_changed) { - ccc->cfg_changed(ccc->value); + ccc->cfg_changed(ccc->user_data, ccc->value); } BT_DBG("ccc %p reseted", ccc); @@ -819,98 +801,129 @@ static uint8_t disconnected_cb(const struct bt_gatt_attr *attr, void *user_data) return BT_GATT_ITER_CONTINUE; } -void on_nble_gatts_write_evt(const struct nble_gatt_wr_evt *evt, +static ssize_t on_prep_write(const struct nble_gatts_write_evt *evt, + const uint8_t *buf, uint8_t buflen) +{ + const struct bt_gatt_attr *attr = evt->attr; + struct bt_conn *conn = NULL; + ssize_t status; + + struct prep_data *data; + + // Check permision first + if (!(attr->perm & BT_GATT_PERM_PREPARE_WRITE)) { + return BT_GATT_ERR(BT_ATT_ERR_WRITE_NOT_PERMITTED); + } + + data = nble_curie_alloc_hook(sizeof (struct prep_data)); + + /* Assert if memory allocation failed */ + BT_ASSERT(data); + + data->attr = attr; + data->offset = evt->offset; + data->len = buflen; + + data->buf = nble_curie_alloc_hook(buflen); + + /* Assert if memory allocation failed */ + BT_ASSERT(data->buf); + + memcpy(data->buf, buf, buflen); + conn = bt_conn_lookup_handle(evt->conn_handle); + /* Write attribute value to check if device is authorized */ + status = attr->write(conn, attr, buf, buflen, evt->offset, + BT_GATT_WRITE_FLAG_PREPARE); + + /* Store data in the queue */ + fifo_put(&prep_queue, data); + + if (conn) + bt_conn_unref(conn); + + return status; +} + +void on_nble_gatts_write_evt(const struct nble_gatts_write_evt *evt, const uint8_t *buf, uint8_t buflen) { const struct bt_gatt_attr *attr = evt->attr; struct bt_conn *conn = bt_conn_lookup_handle(evt->conn_handle); - struct nble_gatts_wr_reply_params reply_data; + struct nble_gatts_write_reply_req req; - //BT_DBG("write_evt %p", attr); + BT_DBG("write_evt %p", attr); - /* Check for write support and flush support in case of prepare */ - if (!attr->write || - ((evt->flag & NBLE_GATT_WR_FLAG_PREP) && !attr->flush)) { - reply_data.status = BT_GATT_ERR(BT_ATT_ERR_WRITE_NOT_PERMITTED); + /* Check for write support */ + if (!attr->write) { + req.status = BT_GATT_ERR(BT_ATT_ERR_WRITE_NOT_PERMITTED); goto reply; } - //BT_DBG("%s", __FUNCTION__); - reply_data.status = attr->write(conn, attr, buf, buflen, evt->offset); - if (reply_data.status < 0) { - - //BT_DBG("%s1-1", __FUNCTION__); + /* Check for prepare writes */ + if (evt->flag & NBLE_GATT_WR_FLAG_PREP) { + req.status = on_prep_write(evt, buf, buflen); goto reply; } - //BT_DBG("%s1", __FUNCTION__); + req.status = attr->write(conn, attr, buf, buflen, evt->offset, 0); + if (req.status < 0) { + goto reply; + } /* Return an error if not all data has been written */ - if (reply_data.status != buflen) { - reply_data.status = BT_GATT_ERR(BT_ATT_ERR_UNLIKELY); + if (req.status != buflen) { + req.status = BT_GATT_ERR(BT_ATT_ERR_UNLIKELY); goto reply; } - //BT_DBG("%s2", __FUNCTION__); - - if (attr->flush && !(evt->flag & NBLE_GATT_WR_FLAG_PREP)) - reply_data.status = attr->flush(conn, attr, BT_GATT_FLUSH_SYNC); - - //BT_DBG("%s3", __FUNCTION__); - reply: - //BT_DBG("%s4", __FUNCTION__); if (evt->flag & NBLE_GATT_WR_FLAG_REPLY) { - reply_data.conn_handle = evt->conn_handle; + req.conn_handle = evt->conn_handle; + req.offset = evt->offset; - nble_gatts_wr_reply_req(&reply_data); + nble_gatts_write_reply_req(&req, buf, buflen); } if (conn) bt_conn_unref(conn); } -static uint8_t flush_all(const struct bt_gatt_attr *attr, void *user_data) +void on_nble_gatts_write_exec_evt(const struct nble_gatts_write_exec_evt *evt) { - struct ble_gatts_flush_all *flush_data = user_data; - - if (attr->flush) { - int status = attr->flush(flush_data->conn, attr, flush_data->flag); - - if (status < 0 && flush_data->status == 0) - flush_data->status = status; - } + struct bt_conn *conn = bt_conn_lookup_handle(evt->conn_handle); + const struct bt_gatt_attr *attr; + struct nble_gatts_write_reply_req req; + struct prep_data *data; - return BT_GATT_ITER_CONTINUE; -} + req.conn_handle = evt->conn_handle; + req.status = 0; + req.offset = 0; -void on_nble_gatts_write_exec_evt(const struct nble_gatt_wr_exec_evt *evt) -{ BT_DBG("write_exec_evt"); - struct ble_gatts_flush_all flush_data = { - .conn = bt_conn_lookup_handle(evt->conn_handle), - .flag = evt->flag, - .status = 0, - }; + while ((data = fifo_get(&prep_queue, TICKS_NONE))) { + attr = data->attr; - bt_gatt_foreach_attr(0x0001, 0xFFFF, flush_all, &flush_data); + /* If an error occurred just discard the data */ + if (req.status >= 0) + req.status = attr->write(conn, attr, data->buf, data->len, + data->offset, 0); - struct nble_gatts_wr_reply_params reply_data = { - .conn_handle = evt->conn_handle, - .status = flush_data.status, - }; - nble_gatts_wr_reply_req(&reply_data); + nble_curie_free_hook(data->buf); + nble_curie_free_hook(data); + } + + nble_gatts_write_reply_req(&req, NULL, 0); - bt_conn_unref(flush_data.conn); + bt_conn_unref(conn); } -void on_nble_gatts_read_evt(const struct nble_gatt_rd_evt *evt) +void on_nble_gatts_read_evt(const struct nble_gatts_read_evt *evt) { - struct nble_gatts_rd_reply_params reply_data; + struct nble_gatts_read_reply_req req; const struct bt_gatt_attr *attr; /* The length of the value sent back in the response is unknown because * of NRF API limitation, so we use the max possible one: ATT_MTU-1 */ @@ -921,7 +934,7 @@ void on_nble_gatts_read_evt(const struct nble_gatt_rd_evt *evt) BT_DBG("read_evt %p", attr); - memset(&reply_data, 0, sizeof(reply_data)); + memset(&req, 0, sizeof(req)); if (attr->read) { struct bt_conn *conn = bt_conn_lookup_handle(evt->conn_handle); @@ -936,38 +949,36 @@ void on_nble_gatts_read_evt(const struct nble_gatt_rd_evt *evt) } /* status >= 0 is considered as success by nble */ - reply_data.status = len; + req.status = len; if (len < 0) { len = 0; } - reply_data.conn_handle = evt->conn_handle; + req.conn_handle = evt->conn_handle; /* offset is needed by nble even in error case */ - reply_data.offset = evt->offset; + req.offset = evt->offset; - nble_gatts_rd_reply_req(&reply_data, data, len); + nble_gatts_read_reply_req(&req, data, len); } #if defined(CONFIG_BLUETOOTH_GATT_CLIENT) -void on_nble_gattc_value_evt(const struct ble_gattc_value_evt *evt, - uint8_t *data, uint8_t length) +void on_nble_gattc_value_evt(const struct nble_gattc_value_evt *evt, + uint8_t *data, uint8_t len) { struct bt_gatt_subscribe_params *params; struct bt_conn *conn; conn = bt_conn_lookup_handle(evt->conn_handle); - //BT_DBG("FUNC %s", __FUNCTION__); - if (conn) { for (params = subscriptions; params; params = params->_next) { if (evt->handle != params->value_handle) { continue; } - if (params->notify(conn, params, data, length) == + if (params->notify(conn, params, data, len) == BT_GATT_ITER_STOP) { bt_gatt_unsubscribe(conn, params); } @@ -1048,7 +1059,6 @@ void on_nble_gattc_discover_rsp(const struct nble_gattc_discover_rsp *rsp, struct bt_gatt_attr *attr = NULL; if (rsp->type == BT_GATT_DISCOVER_PRIMARY) { - //BT_DBG("%s-%d", __FUNCTION__, __LINE__); const struct nble_gattc_primary *gattr = (void *)&data[i * sizeof(*gattr)]; if ((gattr->range.start_handle < params->start_handle) && @@ -1083,8 +1093,9 @@ void on_nble_gattc_discover_rsp(const struct nble_gattc_discover_rsp *rsp, /* Data is not available at this point */ break; } - attr = (&(struct bt_gatt_attr) - BT_GATT_INCLUDE_SERVICE(&inc_value)); + attr = (&(struct bt_gatt_attr) { + .uuid = BT_UUID_GATT_INCLUDE, + .user_data = &inc_value, }); attr->handle = gattr->handle; last_handle = gattr->handle; } else if (rsp->type == BT_GATT_DISCOVER_CHARACTERISTIC) { @@ -1095,10 +1106,6 @@ void on_nble_gattc_discover_rsp(const struct nble_gattc_discover_rsp *rsp, gattr->prop)); attr->handle = gattr->handle; last_handle = gattr->handle; - /* Skip if UUID is set but doesn't match */ - if (params->uuid && bt_uuid_cmp(&gattr->uuid.uuid, params->uuid)) { - continue; - } } else if (rsp->type == BT_GATT_DISCOVER_DESCRIPTOR) { const struct nble_gattc_descriptor *gattr = (void *)&data[i * sizeof(*gattr)]; @@ -1141,7 +1148,7 @@ void on_nble_gattc_discover_rsp(const struct nble_gattc_discover_rsp *rsp, int bt_gatt_discover(struct bt_conn *conn, struct bt_gatt_discover_params *params) { - struct nble_discover_params discover_params; + struct nble_gattc_discover_req req; if (!conn || !params || !params->func || !params->start_handle || !params->end_handle || params->start_handle > params->end_handle) { @@ -1154,15 +1161,15 @@ int bt_gatt_discover(struct bt_conn *conn, BT_DBG("disc: %d", params->start_handle); - memset(&discover_params, 0, sizeof(discover_params)); + memset(&req, 0, sizeof(req)); switch (params->type) { case BT_GATT_DISCOVER_PRIMARY: case BT_GATT_DISCOVER_CHARACTERISTIC: if (params->uuid) { /* Always copy a full 128 bit UUID */ - discover_params.uuid = *BT_UUID_128(params->uuid); - discover_params.flags = DISCOVER_FLAGS_UUID_PRESENT; + req.uuid = *BT_UUID_128(params->uuid); + req.flags = DISCOVER_FLAGS_UUID_PRESENT; } break; @@ -1173,20 +1180,20 @@ int bt_gatt_discover(struct bt_conn *conn, return -EINVAL; } - discover_params.conn_handle = conn->handle; - discover_params.type = params->type; - discover_params.handle_range.start_handle = params->start_handle; - discover_params.handle_range.end_handle = params->end_handle; + req.conn_handle = conn->handle; + req.type = params->type; + req.handle_range.start_handle = params->start_handle; + req.handle_range.end_handle = params->end_handle; - discover_params.user_data = params; + req.user_data = params; - nble_gattc_discover_req(&discover_params); + nble_gattc_discover_req(&req); return 0; } -void on_nble_gattc_read_multiple_rsp(const struct ble_gattc_read_rsp *rsp, - uint8_t *pdu, uint8_t length) +void on_nble_gattc_read_multi_rsp(const struct nble_gattc_read_rsp *rsp, + uint8_t *data, uint8_t len) { struct bt_gatt_read_params *params; struct bt_conn *conn = bt_conn_lookup_handle(rsp->conn_handle); @@ -1203,7 +1210,7 @@ void on_nble_gattc_read_multiple_rsp(const struct ble_gattc_read_rsp *rsp, return; } - params->func(conn, 0, params, pdu, length); + params->func(conn, 0, params, data, len); /* mark read as complete since read multiple is single response */ params->func(conn, 0, params, NULL, 0); @@ -1211,8 +1218,8 @@ void on_nble_gattc_read_multiple_rsp(const struct ble_gattc_read_rsp *rsp, bt_conn_unref(conn); } -void on_nble_gattc_read_rsp(const struct ble_gattc_read_rsp *rsp, - uint8_t *pdu, uint8_t length) +void on_nble_gattc_read_rsp(const struct nble_gattc_read_rsp *rsp, + uint8_t *data, uint8_t len) { struct bt_gatt_read_params *params; struct bt_conn *conn = bt_conn_lookup_handle(rsp->conn_handle); @@ -1227,7 +1234,7 @@ void on_nble_gattc_read_rsp(const struct ble_gattc_read_rsp *rsp, return; } - if (params->func(conn, 0, params, pdu, length) == BT_GATT_ITER_STOP) { + if (params->func(conn, 0, params, data, len) == BT_GATT_ITER_STOP) { bt_conn_unref(conn); return; } @@ -1238,13 +1245,13 @@ void on_nble_gattc_read_rsp(const struct ble_gattc_read_rsp *rsp, * in length, the Read Long Characteristic Value procedure may be used * if the rest of the Characteristic Value is required. */ - if (length < BLE_GATT_MTU_SIZE - 1) { + if (len < BLE_GATT_MTU_SIZE - 1) { params->func(conn, 0, params, NULL, 0); bt_conn_unref(conn); return; } - params->single.offset += length; + params->single.offset += len; /* Continue reading the attribute */ if (bt_gatt_read(conn, params)) { @@ -1256,27 +1263,28 @@ void on_nble_gattc_read_rsp(const struct ble_gattc_read_rsp *rsp, int bt_gatt_read(struct bt_conn *conn, struct bt_gatt_read_params *params) { - struct ble_gattc_read_params single_req; - struct ble_gattc_read_multiple_params mutiple_req; + struct nble_gattc_read_req sreq; + struct nble_gattc_read_multi_req mreq; if (!conn || conn->state != BT_CONN_CONNECTED || !params || params->handle_count == 0 || !params->func) { return -EINVAL; } - single_req.conn_handle = conn->handle; + sreq.conn_handle = conn->handle; if (1 == params->handle_count) { - single_req.handle = params->single.handle; - single_req.offset = params->single.offset; - single_req.user_data = params; + sreq.handle = params->single.handle; + sreq.offset = params->single.offset; + sreq.user_data = params; - nble_gattc_read_req(&single_req); + nble_gattc_read_req(&sreq); } else { - mutiple_req.conn_handle = conn->handle; - mutiple_req.user_data = params; + mreq.conn_handle = conn->handle; + mreq.user_data = params; - nble_gattc_read_multiple_req(&mutiple_req, params->handles, 2 * params->handle_count); + nble_gattc_read_multi_req(&mreq, params->handles, + 2 * params->handle_count); } return 0; } @@ -1287,9 +1295,9 @@ static void on_write_no_rsp_complete(struct bt_conn *conn, uint8_t err, } static void on_write_complete(struct bt_conn *conn, uint8_t err, - const struct bt_gatt_write_params *wr_params) + const struct nble_gattc_write_param *wr_params) { - bt_gatt_write_rsp_func_t func = wr_params->user_data[0]; + bt_gatt_rsp_func_t func = wr_params->user_data[0]; const void *data = wr_params->user_data[1]; BT_ASSERT(func); @@ -1298,9 +1306,9 @@ static void on_write_complete(struct bt_conn *conn, uint8_t err, static int _bt_gatt_write(struct bt_conn *conn, uint16_t handle, bool with_resp, uint16_t offset, const void *data, uint16_t length, - struct bt_gatt_write_params *wr_params) + struct nble_gattc_write_param *wr_params) { - struct ble_gattc_write_params req; + struct nble_gattc_write_req req; req.conn_handle = conn->handle; req.handle = handle; @@ -1313,7 +1321,7 @@ static int _bt_gatt_write(struct bt_conn *conn, uint16_t handle, bool with_resp, return 0; } -void on_nble_gattc_write_rsp(const struct ble_gattc_write_rsp *rsp) +void on_nble_gattc_write_rsp(const struct nble_gattc_write_rsp *rsp) { struct bt_conn *conn = bt_conn_lookup_handle(rsp->conn_handle); @@ -1327,32 +1335,35 @@ void on_nble_gattc_write_rsp(const struct ble_gattc_write_rsp *rsp) bt_conn_unref(conn); } - int bt_gatt_write_without_response(struct bt_conn *conn, uint16_t handle, const void *data, uint16_t length, bool sign) { - return bt_gatt_write(conn, handle, 0, data, length, - on_write_no_rsp_complete); + struct bt_gatt_write_params p; + p.func = on_write_no_rsp_complete; + p.handle = handle; + p.offset = 0; + p.data = data; + p.length = length; + return bt_gatt_write(conn, &p); } -int bt_gatt_write(struct bt_conn *conn, uint16_t handle, uint16_t offset, - const void *data, uint16_t length, - bt_gatt_write_rsp_func_t func) +int bt_gatt_write(struct bt_conn *conn, struct bt_gatt_write_params *params) { - struct bt_gatt_write_params wr_params; + struct nble_gattc_write_param wr_params; - if (!conn || conn->state != BT_CONN_CONNECTED || !handle || !func) { + if (!conn || conn->state != BT_CONN_CONNECTED || !params->handle || + !params->func) { return -EINVAL; } wr_params.func = on_write_complete; - wr_params.user_data[0] = func; - wr_params.user_data[1] = (void *)data; + wr_params.user_data[0] = params->func; + wr_params.user_data[1] = (void *)params->data; - return _bt_gatt_write(conn, handle, - (func == on_write_no_rsp_complete) + return _bt_gatt_write(conn, params->handle, + (params->func == on_write_no_rsp_complete) ? false : true, - offset, data, length, &wr_params); + params->offset, params->data, params->length, &wr_params); } static void gatt_subscription_add(struct bt_conn *conn, @@ -1366,7 +1377,7 @@ static void gatt_subscription_add(struct bt_conn *conn, } static void att_write_ccc_rsp(struct bt_conn *conn, uint8_t err, - const struct bt_gatt_write_params *wr_params) + const struct nble_gattc_write_param *wr_params) { struct bt_gatt_subscribe_params *params = wr_params->user_data[0]; @@ -1389,7 +1400,7 @@ static int gatt_write_ccc(struct bt_conn *conn, uint16_t handle, uint16_t value, bt_att_func_t func, struct bt_gatt_subscribe_params *params) { - struct bt_gatt_write_params wr_params; + struct nble_gattc_write_param wr_params; wr_params.func = func; wr_params.user_data[0] = params; @@ -1520,26 +1531,26 @@ static void add_subscriptions(struct bt_conn *conn) #else void on_nble_gattc_discover_rsp(const struct nble_gattc_discover_rsp *rsp, - const uint8_t *data, uint8_t data_len) + const uint8_t *data, uint8_t data_len) { } -void on_nble_gattc_write_rsp(const struct ble_gattc_write_rsp *rsp) +void on_nble_gattc_write_rsp(const struct nble_gattc_write_rsp *rsp) { } -void on_nble_gattc_value_evt(const struct ble_gattc_value_evt *evt, - uint8_t *buf, uint8_t buflen) +void on_nble_gattc_value_evt(const struct nble_gattc_value_evt *evt, + uint8_t *buf, uint8_t buflen) { } -void on_nble_gattc_read_rsp(const struct ble_gattc_read_rsp *rsp, - uint8_t *data, uint8_t data_len) +void on_nble_gattc_read_rsp(const struct nble_gattc_read_rsp *rsp, + uint8_t *data, uint8_t data_len) { } -void on_nble_gattc_read_multiple_rsp(const struct ble_gattc_read_rsp *rsp, - uint8_t *data, uint8_t data_len) +void on_nble_gattc_read_multi_rsp(const struct nble_gattc_read_rsp *rsp, + uint8_t *data, uint8_t data_len) { } @@ -1549,6 +1560,8 @@ void bt_gatt_connected(struct bt_conn *conn) { BT_DBG("conn %p", conn); bt_gatt_foreach_attr(0x0001, 0xffff, connected_cb, conn); + fifo_init(&prep_queue); + #if defined(CONFIG_BLUETOOTH_GATT_CLIENT) add_subscriptions(conn); #endif /* CONFIG_BLUETOOTH_GATT_CLIENT */ @@ -1556,9 +1569,17 @@ void bt_gatt_connected(struct bt_conn *conn) void bt_gatt_disconnected(struct bt_conn *conn) { + struct prep_data *data; + BT_DBG("conn %p", conn); - bt_gatt_foreach_attr(0x0001, 0xffff, disconnected_cb, conn); + /* Discard queued buffers */ + while ((data = fifo_get(&prep_queue, TICKS_NONE))) { + nble_curie_free_hook(data->buf); + nble_curie_free_hook(data); + } + + bt_gatt_foreach_attr(0x0001, 0xffff, disconnected_cb, conn); #if defined(CONFIG_BLUETOOTH_GATT_CLIENT) /* If bonded don't remove subscriptions */ if (is_bonded(&conn->le.dst)) { diff --git a/system/libarc32_arduino101/framework/src/services/ble/hci_core.h b/system/libarc32_arduino101/framework/src/services/ble/hci_core.h index dc7374b0..5bb0a58d 100644 --- a/system/libarc32_arduino101/framework/src/services/ble/hci_core.h +++ b/system/libarc32_arduino101/framework/src/services/ble/hci_core.h @@ -16,6 +16,9 @@ /* State tracking for the local Bluetooth controller */ struct bt_dev { + /* Local Identity Address */ + bt_addr_le_t id_addr; + bt_addr_le_t random_addr; atomic_t flags[1]; }; extern struct bt_dev bt_dev; @@ -29,7 +32,7 @@ static inline bool bt_addr_le_is_rpa(const bt_addr_le_t *addr) if (addr->type != BT_ADDR_LE_RANDOM) return false; - if ((addr->val[5] & 0xc0) == 0x40) + if ((addr->a.val[5] & 0xc0) == 0x40) return true; return false; @@ -41,7 +44,7 @@ static inline bool bt_addr_le_is_identity(const bt_addr_le_t *addr) return true; /* Check for Random Static address type */ - if ((addr->val[5] & 0xc0) == 0xc0) + if ((addr->a.val[5] & 0xc0) == 0xc0) return true; return false; diff --git a/system/libarc32_arduino101/framework/src/services/ble/l2cap.c b/system/libarc32_arduino101/framework/src/services/ble/l2cap.c index 488cfd0e..a4c87394 100644 --- a/system/libarc32_arduino101/framework/src/services/ble/l2cap.c +++ b/system/libarc32_arduino101/framework/src/services/ble/l2cap.c @@ -25,19 +25,18 @@ /* #define BT_GATT_DEBUG 1 */ -extern void on_nble_curie_log(char *fmt, ...); extern void __assert_fail(void); #ifdef BT_GATT_DEBUG -#define BT_DBG(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_ERR(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_WARN(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_INFO(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_DBG(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_ERR(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_WARN(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_INFO(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) #define BT_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) #else #define BT_DBG(fmt, ...) do {} while (0) -#define BT_ERR(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_WARN(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_INFO(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_ERR(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_WARN(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_INFO(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) #define BT_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) #endif diff --git a/system/libarc32_arduino101/framework/src/services/ble/smp.h b/system/libarc32_arduino101/framework/src/services/ble/smp.h index 4f52c002..7ad3f0b9 100644 --- a/system/libarc32_arduino101/framework/src/services/ble/smp.h +++ b/system/libarc32_arduino101/framework/src/services/ble/smp.h @@ -69,11 +69,10 @@ void bt_smp_pkey_ready(void); int bt_smp_init(void); int bt_smp_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey); -int bt_smp_auth_passkey_confirm(struct bt_conn *conn, bool match); +int bt_smp_auth_passkey_confirm(struct bt_conn *conn); +int bt_smp_auth_pairing_confirm(struct bt_conn *conn); int bt_smp_auth_cancel(struct bt_conn *conn); -int bt_smp_remove_info(const bt_addr_le_t *addr); - #ifdef CONFIG_BLUETOOTH_SMP void bt_smp_connected(struct bt_conn *conn); void bt_smp_disconnected(struct bt_conn *conn); diff --git a/system/libarc32_arduino101/framework/src/services/ble/smp_null.c b/system/libarc32_arduino101/framework/src/services/ble/smp_null.c index cdc3a4d5..025ef33d 100644 --- a/system/libarc32_arduino101/framework/src/services/ble/smp_null.c +++ b/system/libarc32_arduino101/framework/src/services/ble/smp_null.c @@ -27,19 +27,18 @@ /* #define BT_GATT_DEBUG 1 */ -extern void on_nble_curie_log(char *fmt, ...); extern void __assert_fail(void); #ifdef BT_GATT_DEBUG -#define BT_DBG(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_ERR(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_WARN(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_INFO(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_DBG(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_ERR(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_WARN(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_INFO(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) #define BT_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) #else #define BT_DBG(fmt, ...) do {} while (0) -#define BT_ERR(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_WARN(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) -#define BT_INFO(fmt, ...) on_nble_curie_log(fmt, ##__VA_ARGS__) +#define BT_ERR(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_WARN(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) +#define BT_INFO(fmt, ...) nble_curie_log_hook(fmt, ##__VA_ARGS__) #define BT_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) #endif @@ -53,66 +52,56 @@ extern void __assert_fail(void); #define NBLE_SMP_AUTH_OPTIONS 0 #define NBLE_SMP_OBB_PRESENT BT_SMP_OOB_NOT_PRESENT -#if NOT_USED_FOR_NOW -int bt_smp_sign_verify(struct bt_conn *conn, struct net_buf *buf) -{ - return -ENOTSUP; -} -int bt_smp_sign(struct bt_conn *conn, struct net_buf *buf) +int bt_smp_init(void) { - return -ENOTSUP; + return 0; } -#endif -void on_nble_gap_sm_bond_info_rsp(const struct nble_gap_sm_bond_info_rsp *rsp, - const bt_addr_le_t *peer_addr, uint16_t len) +void on_nble_sm_bond_info_rsp(const struct nble_sm_bond_info_rsp *par, + const bt_addr_le_t *peer_addr, uint16_t len) { /* stub */ } -void on_nble_gap_sm_passkey_req_evt(const struct nble_gap_sm_passkey_req_evt * p_evt) +void on_nble_sm_passkey_req_evt(const struct nble_sm_passkey_req_evt *evt) { /* stub */ } -void on_nble_gap_sm_passkey_display_evt( - const struct nble_gap_sm_passkey_disp_evt *p_evt) +void on_nble_sm_passkey_disp_evt(const struct nble_sm_passkey_disp_evt *evt) { /* stub */ } -void on_nble_gap_sm_status_evt(const struct nble_gap_sm_status_evt *evt) +void on_nble_sm_status_evt(const struct nble_sm_status_evt *evt) { /* stub */ - BT_INFO("nble_gap_sm_status_evt: %d, gap_status: %d", - evt->evt_type, evt->status); } -int bt_smp_init(void) +void on_nble_sm_common_rsp(const struct nble_sm_common_rsp *rsp) { - struct nble_gap_sm_config_params params = { - .options = NBLE_SMP_AUTH_OPTIONS, - .io_caps = NBLE_SMP_IO_CAPS, - .key_size = BT_SMP_MAX_ENC_KEY_SIZE, - .oob_present = NBLE_SMP_OBB_PRESENT, - }; - - nble_gap_sm_config_req(¶ms); - - return 0; + if (rsp->status) { + BT_WARN("gap sm request failed: %d", rsp->status); + } } -void on_nble_gap_sm_config_rsp(struct nble_gap_sm_config_rsp *p_params) +void on_nble_sm_config_rsp(struct nble_sm_config_rsp *rsp) { - if (p_params->status) { - BT_ERR("sm_config failed: %d", p_params->status); + if (rsp->status) { + BT_ERR("sm_config failed: %d", rsp->status); } } -void on_nble_gap_sm_common_rsp(const struct nble_gap_sm_response *rsp) +void on_nble_sm_pairing_request_evt(const struct nble_sm_pairing_request_evt *evt) { - if (rsp->status) { - BT_WARN("gap sm request failed: %d", rsp->status); - } + /* stub */ + (void)evt; } + +void on_nble_sm_security_request_evt(const struct nble_sm_security_request_evt *evt) +{ + /* stub */ + (void)evt; +} + diff --git a/system/libarc32_arduino101/framework/src/services/ble_service/ble_service.c b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service.c index 07231cb1..a166bed5 100644 --- a/system/libarc32_arduino101/framework/src/services/ble_service/ble_service.c +++ b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service.c @@ -51,6 +51,10 @@ #include "rpc.h" #include "util/misc.h" +#include "infra/time.h" + +extern void __assert_fail(void); +#define BT_SERVICE_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) struct _ble_service_cb _ble_cb = { 0 }; volatile uint8_t ble_inited = false; @@ -64,191 +68,175 @@ static const struct bt_conn_auth_cb auth_callbacks; #endif static service_t ble_service = { - .service_id = BLE_SERVICE_ID, - .client_connected = ble_client_connected, - .client_disconnected = ble_client_disconnected, + .service_id = BLE_SERVICE_ID, + .client_connected = ble_client_connected, + .client_disconnected = ble_client_disconnected, }; static void ble_is_not_enabled_rsp(struct cfw_message *msg, int status) { - struct ble_enable_rsp *resp = - (struct ble_enable_rsp *)cfw_alloc_rsp_msg(msg, - /* translate msg from req to rsp */ - (CFW_MESSAGE_ID(msg) ^ MSG_ID_BLE_SERVICE_BASE) - | MSG_ID_BLE_SERVICE_RSP, - sizeof(*resp)); - resp->status = status; - cfw_send_message(resp); + struct ble_enable_rsp *resp = + (struct ble_enable_rsp *)cfw_alloc_rsp_msg(msg, + /* translate msg from req to rsp */ + (CFW_MESSAGE_ID(msg) ^ MSG_ID_BLE_SERVICE_BASE) + | MSG_ID_BLE_SERVICE_RSP, + sizeof(*resp)); + resp->status = status; + cfw_send_message(resp); } #ifdef CONFIG_TCMD_BLE_DEBUG static void handle_msg_id_ble_dbg(struct cfw_message *msg) { - struct nble_debug_params params; - struct ble_dbg_req_rsp *resp = (void *) - cfw_alloc_rsp_msg(msg, MSG_ID_BLE_DBG_RSP, sizeof(*resp)); - struct ble_dbg_req_rsp *req = (struct ble_dbg_req_rsp *) msg; - - params.u0 = req->u0; - params.u1 = req->u1; - - nble_gap_dbg_req(¶ms, resp); + struct nble_dbg_req params; + struct ble_dbg_req_rsp *resp = (void *) + cfw_alloc_rsp_msg(msg, MSG_ID_BLE_DBG_RSP, sizeof(*resp)); + struct ble_dbg_req_rsp *req = (struct ble_dbg_req_rsp *) msg; + + params.u0 = req->u0; + params.u1 = req->u1; + params.user_data = (void *)resp; + nble_dbg_req(¶ms); } #endif /* CONFIG_TCMD_BLE_DEBUG */ -void on_nble_gap_dbg_rsp(const struct nble_debug_resp *params) +void on_nble_dbg_rsp(const struct nble_dbg_rsp *params) { #ifdef CONFIG_TCMD_BLE_DEBUG - struct ble_dbg_req_rsp *resp = params->user_data; - if (!resp) - return; - resp->u0 = params->u0; - resp->u1 = params->u1; - cfw_send_message(resp); + struct ble_dbg_req_rsp *resp = params->user_data; + if (!resp) + return; + resp->u0 = params->u0; + resp->u1 = params->u1; + cfw_send_message(resp); #endif /* CONFIG_TCMD_BLE_DEBUG */ } static void handle_msg_id_ble_rpc_callin(struct message *msg, void *priv) { - struct ble_rpc_callin *rpc = container_of(msg, struct ble_rpc_callin, msg); - /* handle incoming message */ + struct ble_rpc_callin *rpc = container_of(msg, struct ble_rpc_callin, msg); + /* handle incoming message */ //pr_debug(LOG_MODULE_BLE, "%s-%d", __FUNCTION__, __LINE__); - rpc_deserialize(rpc->p_data, rpc->len); - bfree(rpc->p_data); - message_free(msg); + rpc_deserialize(rpc->p_data, rpc->len); + bfree(rpc->p_data); + message_free(msg); //pr_debug(LOG_MODULE_BLE, "%s-%d", __FUNCTION__, __LINE__); } -static void ble_set_bda_cb(int status, void *user_data) +static void ble_set_bda_cb(int status, + void *user_data, + const bt_addr_le_t *bda) { - struct ble_enable_req *req = user_data; - - if (!req) - return; - - struct ble_enable_rsp *resp = (void *)cfw_alloc_rsp_msg(&req->header, - MSG_ID_BLE_ENABLE_RSP, sizeof(*resp)); - resp->status = status; - - if (status == 0) { - resp->enable = 1; - - nble_gap_read_bda_req(resp); - } else { - /* error case */ - resp->enable = 0; - cfw_send_message(resp); - } - bfree(req); -} - - -void on_nble_gap_read_bda_rsp(const struct nble_service_read_bda_response *params) -{ - struct cfw_message *rsp = params->user_data; - - if (rsp) { - struct ble_enable_rsp *r = container_of(rsp, struct ble_enable_rsp, header); - r->bd_addr = params->bd; - cfw_send_message(rsp); - } + struct ble_enable_req *req = user_data; + + if (!req) + return; + + struct ble_enable_rsp *resp = (void *)cfw_alloc_rsp_msg(&req->header, + MSG_ID_BLE_ENABLE_RSP, + sizeof(*resp)); + resp->status = status; + + if (status == 0) { + resp->enable = 1; + + //nble_read_bda_req(resp); + } else { + /* error case */ + resp->enable = 0; + cfw_send_message(resp); + } + bfree(req); } static void handle_ble_enable(struct ble_enable_req *req, - struct _ble_service_cb *p_cb) + struct _ble_service_cb *p_cb) { - pr_info(LOG_MODULE_BLE, "ble_enable: state %d", p_cb->ble_state); + pr_info(LOG_MODULE_BLE, "ble_enable: state %d", p_cb->ble_state); - p_cb->ble_state = BLE_ST_ENABLED; + p_cb->ble_state = BLE_ST_ENABLED; - if (req->bda_present) { - struct nble_set_bda_params params; + if (req->bda_present) { + struct nble_set_bda_req params; - params.cb = ble_set_bda_cb; - params.user_data = req; - params.bda = req->bda; + params.cb = ble_set_bda_cb; + params.user_data = req; + params.bda = req->bda; - nble_set_bda_req(¶ms); - } else { - ble_set_bda_cb(0, req); - } -} - -void on_nble_set_bda_rsp(const struct nble_set_bda_rsp *params) -{ - if (params->cb) { - params->cb(params->status, params->user_data); - } + nble_set_bda_req(¶ms); + } else { + ble_set_bda_cb(0, req, NULL); + } } static void handle_ble_disable(struct ble_enable_req *req, struct _ble_service_cb *p_cb) { - struct ble_enable_rsp *resp; + struct ble_enable_rsp *resp; - pr_debug(LOG_MODULE_BLE, "ble_disable"); - p_cb->ble_state = BLE_ST_DISABLED; + pr_debug(LOG_MODULE_BLE, "ble_disable"); + p_cb->ble_state = BLE_ST_DISABLED; - bt_le_adv_stop(); + bt_le_adv_stop(); - resp = (void *)cfw_alloc_rsp_msg(&req->header, - MSG_ID_BLE_ENABLE_RSP, - sizeof(*resp)); - cfw_send_message(resp); // Sid. KW warning ack. + resp = (void *)cfw_alloc_rsp_msg(&req->header, + MSG_ID_BLE_ENABLE_RSP, + sizeof(*resp)); + cfw_send_message(resp); // Sid. KW warning ack. } static void ble_service_message_handler(struct cfw_message *msg, void *param) { - bool free_msg = true; - struct _ble_service_cb *p_cb = param; - uint16_t msg_id = CFW_MESSAGE_ID(msg); - - if (p_cb->ble_state < BLE_ST_ENABLED && - msg_id != MSG_ID_BLE_ENABLE_REQ) { - ble_is_not_enabled_rsp(msg, -ENODEV); - goto out; - } - - switch (msg_id) { - case MSG_ID_BLE_ENABLE_REQ: { - struct ble_enable_req *req = - container_of(msg, struct ble_enable_req, header); - if (p_cb->ble_state) { - if (req->enable) { - handle_ble_enable(req, p_cb); - free_msg = false; - } else - handle_ble_disable(req, p_cb); - } else { - pr_debug(LOG_MODULE_BLE, "ble_hdl_msg: core service not opened!"); - /* core service is not yet up */ - struct ble_enable_rsp *resp = (void *)cfw_alloc_rsp_msg(msg, - MSG_ID_BLE_ENABLE_RSP, sizeof(*resp)); - resp->status = -EINPROGRESS; - resp->enable = 0; - cfw_send_message(resp); // Sid. KW warning ack. - } - } - break; + bool free_msg = true; + struct _ble_service_cb *p_cb = param; + uint16_t msg_id = CFW_MESSAGE_ID(msg); + + if (p_cb->ble_state < BLE_ST_ENABLED && + msg_id != MSG_ID_BLE_ENABLE_REQ) { + ble_is_not_enabled_rsp(msg, -ENODEV); + goto out; + } + + switch (msg_id) { + case MSG_ID_BLE_ENABLE_REQ: { + struct ble_enable_req *req = + container_of(msg, struct ble_enable_req, header); + if (p_cb->ble_state) { + if (req->enable) { + handle_ble_enable(req, p_cb); + free_msg = false; + } else + handle_ble_disable(req, p_cb); + } else { + pr_debug(LOG_MODULE_BLE, "ble_hdl_msg: core service not opened!"); + /* core service is not yet up */ + struct ble_enable_rsp *resp = (void *)cfw_alloc_rsp_msg(msg, + MSG_ID_BLE_ENABLE_RSP, sizeof(*resp)); + resp->status = -EINPROGRESS; + resp->enable = 0; + cfw_send_message(resp); // Sid. KW warning ack. + } + } + break; #ifdef CONFIG_TCMD_BLE_DEBUG - case MSG_ID_BLE_DBG_REQ: - handle_msg_id_ble_dbg(msg); - break; + case MSG_ID_BLE_DBG_REQ: + handle_msg_id_ble_dbg(msg); + break; #endif - default: - pr_warning(LOG_MODULE_BLE, "unsupported %d", msg_id); - break; - } + default: + pr_warning(LOG_MODULE_BLE, "unsupported %d", msg_id); + break; + } out: - if (free_msg) - cfw_msg_free(msg); + if (free_msg) + cfw_msg_free(msg); } static void ble_client_connected(conn_handle_t *instance) { - if (_ble_cb.ble_state == BLE_ST_NOT_READY) - pr_warning(LOG_MODULE_BLE, "BLE_CORE service is not registered"); + if (_ble_cb.ble_state == BLE_ST_NOT_READY) + pr_warning(LOG_MODULE_BLE, "BLE_CORE service is not registered"); } static void ble_client_disconnected(conn_handle_t *instance) @@ -257,43 +245,57 @@ static void ble_client_disconnected(conn_handle_t *instance) void ble_bt_rdy(int err) { - _ble_cb.ble_state = BLE_ST_DISABLED; + BT_SERVICE_ASSERT(err == 0); + _ble_cb.ble_state = BLE_ST_DISABLED; ble_inited = true; - /* register BLE service */ - if (cfw_register_service(_ble_cb.queue, &ble_service, - ble_service_message_handler, &_ble_cb) == -1) { - panic(0xb1eb1e); - } + /* register BLE service */ + if (cfw_register_service(_ble_cb.queue, + &ble_service, + ble_service_message_handler, + &_ble_cb) == -1) { + panic(0xb1eb1e); + } } void ble_cfw_service_init(int service_id, T_QUEUE queue) { - _ble_cb.queue = queue; - _ble_cb.ble_state = BLE_ST_NOT_READY; + _ble_cb.queue = queue; + _ble_cb.ble_state = BLE_ST_NOT_READY; +} +void ble_enable() +{ + uint32_t time_stamp_last = 0; + #ifdef CONFIG_IPC_UART_NS16550 - nble_driver_configure(queue, handle_msg_id_ble_rpc_callin); + nble_driver_configure(_ble_cb.queue, handle_msg_id_ble_rpc_callin); #endif ble_inited = false; - + time_stamp_last = get_uptime_ms(); + bt_enable(ble_bt_rdy); - do{} + do{ + + uint32_t time_stamp_current = get_uptime_ms(); + if (time_stamp_current - time_stamp_last > 3000) + { + nble_driver_hw_reset(); + //pr_warning(LOG_MODULE_BLE, "time_stamp_current %d", time_stamp_current); + + time_stamp_last = time_stamp_current; + } + } while (ble_inited == false); } void nble_log(const struct nble_log_s *param, char *buf, uint8_t buflen) { - pr_info(LOG_MODULE_BLE, buf, param->param0, param->param1, param->param2, param->param3); + pr_info(LOG_MODULE_BLE, + buf, + param->param0, + param->param1, + param->param2); } -void on_nble_common_rsp(const struct nble_response *params) -{ - struct ble_rsp *resp = params->user_data; - - if (!resp) - return; - resp->status = params->status; - cfw_send_message(resp); -} diff --git a/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_api.c b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_api.c deleted file mode 100644 index e70b15c8..00000000 --- a/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_api.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2015, Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ble_service.h" - -#include -#include -//#include -//#include "util/assert.h" - -#include "ble_service_int.h" -#include "ble_service_internal.h" -#include "cfw/cfw_service.h" -#include "cfw/cfw_client.h" - -#include -#include - -#include "ble_protocol.h" -#include "ble_service_utils.h" - -int ble_service_enable(cfw_service_conn_t * p_service_conn, uint8_t enable, - const struct ble_enable_config * p_config, - void *p_priv) -{ - struct ble_enable_req * msg = - (void *) cfw_alloc_message_for_service(p_service_conn, - MSG_ID_BLE_ENABLE_REQ, - sizeof(*msg), p_priv); - msg->central_conn_params = p_config->central_conn_params; - msg->enable = enable; - - if (p_config->p_bda) { - msg->bda_present = 1; - msg->bda = *p_config->p_bda; - } - - return cfw_send_message(msg); -} diff --git a/system/libarc32_arduino101/framework/src/services/ble_service/dtm_internal.h b/system/libarc32_arduino101/framework/src/services/ble_service/dtm_internal.h new file mode 100644 index 00000000..1d55a564 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble_service/dtm_internal.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DTM_INTERNAL_H_ +#define DTM_INTERNAL_H_ + +#include + +struct nble_dtm_cmd_req { + uint8_t cmd_type; + uint8_t tx_rx_freq; + uint8_t tx_len; + uint8_t tx_pattern; + int8_t pwr_dbm; + dtm_rsp_func_t func; + void *user_data; +}; + +void nble_dtm_cmd_req(const struct nble_dtm_cmd_req *req); + +struct nble_dtm_rsp { + int status; + uint16_t nb; + dtm_rsp_func_t func; + void *user_data; +}; + +void on_nble_dtm_rsp(const struct nble_dtm_rsp *rsp); +#endif //DTM_INTERNAL_H_ diff --git a/system/libarc32_arduino101/framework/src/services/ble_service/gap_internal.h b/system/libarc32_arduino101/framework/src/services/ble_service/gap_internal.h index 333ad36e..1add789f 100644 --- a/system/libarc32_arduino101/framework/src/services/ble_service/gap_internal.h +++ b/system/libarc32_arduino101/framework/src/services/ble_service/gap_internal.h @@ -26,24 +26,6 @@ /* Directed advertisement timeout error after 1.28s */ #define ERR_DIRECTED_ADVERTISING_TIMEOUT 0x3C -enum NBLE_GAP_SM_PASSKEY_TYPE { - NBLE_GAP_SM_REJECT = 0, - NBLE_GAP_SM_PK_PASSKEY, - NBLE_GAP_SM_PK_OOB, -}; - -enum NBLE_GAP_SM_EVT { - NBLE_GAP_SM_EVT_START_PAIRING, - NBLE_GAP_SM_EVT_BONDING_COMPLETE, - NBLE_GAP_SM_EVT_LINK_ENCRYPTED, - NBLE_GAP_SM_EVT_LINK_SECURITY_CHANGE, -}; - -enum NBLE_GAP_RSSI_OPS { - NBLE_GAP_RSSI_DISABLE_REPORT = 0, - NBLE_GAP_RSSI_ENABLE_REPORT -}; - enum NBLE_TEST_OPCODES { NBLE_TEST_INIT_DTM = 0x01, NBLE_TEST_START_DTM_RX = 0x1d, @@ -63,30 +45,66 @@ enum NBLE_TEST_OPCODES { #define DTM_HCI_LE_END_IDX (DTM_HCI_STATUS_IDX + 1) -struct nble_response { + +/* bt_dev flags: the flags defined here represent BT controller state */ +enum { + BT_DEV_READY, + + BT_DEV_ADVERTISING, + BT_DEV_KEEP_ADVERTISING, + BT_DEV_SCANNING, + BT_DEV_EXPLICIT_SCAN, + +#if defined(CONFIG_BLUETOOTH_BREDR) + BT_DEV_ISCAN, + BT_DEV_PSCAN, +#endif /* CONFIG_BLUETOOTH_BREDR */ +}; + +struct nble_log_s { + uint32_t param0; + uint32_t param1; + uint32_t param2; +}; + +void nble_log(const struct nble_log_s *par, char *data, uint8_t len); + +struct nble_common_rsp { int status; void *user_data; }; -struct nble_gap_device_name { - /* Security mode for writing device name, @ref BLE_GAP_SEC_MODES */ - uint8_t sec_mode; - /* 0: no authorization, 1: authorization required */ - uint8_t authorization; - /* Device name length (0-248) */ - uint8_t len; - uint8_t name_array[20]; +struct bt_local_addr { + bt_addr_le_t id_addr; +#if defined(CONFIG_BLUETOOTH_PRIVACY) + bt_addr_le_t rpa; +#endif }; -struct nble_gap_connection_values { - /* Connection interval (unit 1.25 ms) */ - uint16_t interval; - /* Connection latency (unit interval) */ - uint16_t latency; - /* Connection supervision timeout (unit 10ms)*/ - uint16_t supervision_to; +void on_nble_common_rsp(const struct nble_common_rsp *rsp); + +void nble_panic_req(void *user_data); + +struct nble_version { + uint8_t version; + uint8_t major; + uint8_t minor; + uint8_t patch; + char version_string[20]; + uint8_t build_hash[4]; + uint8_t hash[4]; +}; + +typedef void (*ble_get_version_cb_t)(const struct nble_version *ver); + +void nble_get_version_req(ble_get_version_cb_t cb); + +struct nble_get_version_rsp { + ble_get_version_cb_t cb; + struct nble_version ver; }; +void on_nble_get_version_rsp(const struct nble_get_version_rsp *rsp); enum NBLE_GAP_SVC_ATTR_TYPE { /* Device Name, UUID 0x2a00 */ @@ -99,7 +117,17 @@ enum NBLE_GAP_SVC_ATTR_TYPE { NBLE_GAP_SVC_ATTR_CAR = 0xa6, }; -struct nble_gap_connection_params { +struct nble_gap_device_name { + /* Security mode for writing device name, see BLE_GAP_SEC_MODES */ + uint8_t sec_mode; + /* 0: no authorization, 1: authorization required */ + uint8_t authorization; + /* Device name length (0-248) */ + uint8_t len; + uint8_t name_array[20]; +}; + +struct nble_conn_param { /* minimal connection interval: range 0x0006 to 0x0c80 (unit 1.25ms) */ uint16_t interval_min; /* maximum connection interval: range 0x0006 to 0x0c80 must be bigger then min! */ @@ -110,90 +138,96 @@ struct nble_gap_connection_params { uint16_t link_sup_to; }; -struct nble_gap_scan_parameters { - /* If 1, perform active scanning (scan requests). */ - uint8_t active; - /* If 1, ignore unknown devices (non whitelisted). */ - uint8_t selective; - /* Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ - uint16_t interval; - /* Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ - uint16_t window; - /* Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ - uint16_t timeout; -}; - -struct nble_gap_service_write_params { - /* GAP Characteristics attribute type @ref BLE_GAP_SVC_ATTR_TYPE */ +struct nble_gap_service_req { + /* GAP Characteristics attribute type see NBLE_GAP_SVC_ATTR_TYPE */ uint16_t attr_type; union { struct nble_gap_device_name name; /* Appearance UUID */ uint16_t appearance; /* Preferred Peripheral Connection Parameters */ - struct nble_gap_connection_params conn_params; + struct nble_conn_param ppcp; /* Central Address Resolution support 0: no, 1: yes */ uint8_t car; }; }; -struct nble_service_read_bda_response { - int status; - /* If @ref status ok */ - bt_addr_le_t bd; - void *user_data; -}; - -struct nble_service_write_response { - int status; - /* GAP Characteristics attribute type @ref BLE_GAP_SVC_ATTR_TYPE */ - uint16_t attr_type; - void *user_data; -}; - -struct nble_gap_service_read_params { - /* Type of GAP data characteristic to read @ref BLE_GAP_SVC_ATTR_TYPE */ - uint16_t attr_type; -}; +void nble_gap_service_req(const struct nble_gap_service_req *req); -struct nble_debug_params { +struct nble_dbg_req { uint32_t u0; uint32_t u1; + void *user_data; }; -struct nble_debug_resp { +void nble_dbg_req(const struct nble_dbg_req *req); + +struct nble_dbg_rsp { int status; uint32_t u0; uint32_t u1; void *user_data; }; -typedef void (*nble_set_bda_cb_t)(int status, void *user_data); +void on_nble_dbg_rsp(const struct nble_dbg_rsp *rsp); -struct nble_set_bda_params { - bt_addr_le_t bda; +typedef void (*nble_set_bda_cb_t)(int status, void *user_data, const bt_addr_le_t *bda); + +struct nble_set_bda_req { nble_set_bda_cb_t cb; void *user_data; + bt_addr_le_t bda; }; +void nble_set_bda_req(const struct nble_set_bda_req *req); + struct nble_set_bda_rsp { nble_set_bda_cb_t cb; void *user_data; int status; + bt_addr_le_t bda; +}; + +void on_nble_set_bda_rsp(const struct nble_set_bda_rsp *rsp); + +typedef void (*nble_get_bda_cb_t)(const bt_addr_le_t *bda, void *user_data); + +struct nble_get_bda_req { + nble_get_bda_cb_t cb; + void *user_data; +}; + +void nble_get_bda_req(const struct nble_get_bda_req *req); + +struct nble_get_bda_rsp { + nble_get_bda_cb_t cb; + void *user_data; + bt_addr_le_t bda; }; -struct bt_eir_data { +void on_nble_get_bda_rsp(const struct nble_get_bda_rsp *rsp); + +struct nble_eir_data { uint8_t len; uint8_t data[31]; }; -struct nble_gap_adv_params { +struct nble_gap_set_adv_data_req { + /* Advertisement data, maybe 0 (length) */ + struct nble_eir_data ad; + /* Scan response data, maybe 0 (length) */ + struct nble_eir_data sd; +}; + +void nble_gap_set_adv_data_req(struct nble_gap_set_adv_data_req *req); + +struct nble_gap_set_adv_params_req { uint16_t timeout; /* min interval 0xffff: use default 0x0800 */ uint16_t interval_min; /* max interval 0xffff: use default 0x0800 */ uint16_t interval_max; - /* advertisement types @ref GAP_ADV_TYPES */ + /* advertisement types see GAP_ADV_TYPES */ uint8_t type; /* filter policy to apply with white list */ uint8_t filter_policy; @@ -201,130 +235,63 @@ struct nble_gap_adv_params { bt_addr_le_t peer_bda; }; -struct nble_gap_ad_data_params { - /* Advertisement data, maybe 0 (length) */ - struct bt_eir_data ad; - /* Scan response data, maybe 0 (length) */ - struct bt_eir_data sd; -}; - -struct nble_log_s { - uint8_t param0; - uint8_t param1; - uint8_t param2; - uint8_t param3; -}; - -/* bt_dev flags: the flags defined here represent BT controller state */ -enum { - BT_DEV_READY, - - BT_DEV_ADVERTISING, - BT_DEV_KEEP_ADVERTISING, - BT_DEV_SCANNING, - BT_DEV_EXPLICIT_SCAN, - -#if defined(CONFIG_BLUETOOTH_BREDR) - BT_DEV_ISCAN, - BT_DEV_PSCAN, -#endif /* CONFIG_BLUETOOTH_BREDR */ -}; - -void nble_log(const struct nble_log_s *param, char *buf, uint8_t buflen); - -void on_nble_up(void); - -void nble_gap_service_write_req(const struct nble_gap_service_write_params *params); - -void on_nble_gap_read_bda_rsp(const struct nble_service_read_bda_response *params); - -void nble_gap_dbg_req(const struct nble_debug_params *params, void *user_data); - -void on_nble_gap_dbg_rsp(const struct nble_debug_resp *params); - -void on_nble_set_bda_rsp(const struct nble_set_bda_rsp *params); - -void nble_set_bda_req(const struct nble_set_bda_params *params); - -void nble_gap_set_adv_data_req(struct nble_gap_ad_data_params *ad_data_params); - -void nble_gap_set_adv_params_req(struct nble_gap_adv_params *adv_params); +void nble_gap_set_adv_params_req(struct nble_gap_set_adv_params_req *req); void nble_gap_start_adv_req(void); -void on_nble_gap_start_advertise_rsp(const struct nble_response *params); +void on_nble_gap_start_adv_rsp(const struct nble_common_rsp *rsp); void nble_gap_stop_adv_req(void *user_data); -void nble_gap_read_bda_req(void *priv); - -struct nble_gap_irk_info { - /* Identity Resolving Key (IRK) */ - uint8_t irk[16]; -}; - -void on_nble_common_rsp(const struct nble_response *params); - -struct nble_gap_connect_update_params { +struct nble_gap_conn_update_req { uint16_t conn_handle; - struct nble_gap_connection_params params; + struct nble_conn_param params; }; -void nble_gap_conn_update_req(const struct nble_gap_connect_update_params *params); +void nble_gap_conn_update_req(const struct nble_gap_conn_update_req *req); -void on_nble_gap_conn_update_rsp(const struct nble_response *params); - -struct nble_gap_connect_req_params { - bt_addr_le_t bda; - struct nble_gap_connection_params conn_params; - struct nble_gap_scan_parameters scan_params; -}; +void on_nble_gap_conn_update_rsp(const struct nble_common_rsp *rsp); -struct nble_gap_disconnect_req_params { +struct nble_gap_disconnect_req { uint16_t conn_handle; uint8_t reason; }; -void nble_gap_disconnect_req(const struct nble_gap_disconnect_req_params *params); - -struct nble_gap_sm_config_params { - /* Security options (@ref BLE_GAP_SM_OPTIONS) */ - uint8_t options; - /* I/O Capabilities to allow passkey exchange (@ref BLE_GAP_IO_CAPABILITIES) */ - uint8_t io_caps; - /* Maximum encryption key size (7-16) */ - uint8_t key_size; - uint8_t oob_present; -}; - -void nble_gap_sm_config_req(const struct nble_gap_sm_config_params *params); +void nble_gap_disconnect_req(const struct nble_gap_disconnect_req *req); -struct nble_gap_sm_config_rsp { +struct nble_sm_config_rsp { void *user_data; int status; bool sm_bond_dev_avail; }; -void on_nble_gap_sm_config_rsp(struct nble_gap_sm_config_rsp *params); +void on_nble_sm_config_rsp(struct nble_sm_config_rsp *rsp); - -struct nble_gap_sm_pairing_params { - /* authentication level see @ref BLE_GAP_SM_OPTIONS */ - uint8_t auth_level; +struct nble_sm_pairing_param { + /* authentication level see BLE_GAP_SM_OPTIONS */ + uint8_t auth; + uint8_t io_capabilities; + uint8_t max_key_size; + uint8_t min_key_size; + uint8_t oob_flag; }; -struct nble_gap_sm_security_params { +struct nble_sm_security_req { struct bt_conn *conn; uint16_t conn_handle; /* Local authentication/bonding parameters */ - struct nble_gap_sm_pairing_params params; + struct nble_sm_pairing_param params; }; -void nble_gap_sm_security_req(const struct nble_gap_sm_security_params * - params); +void nble_sm_security_req(const struct nble_sm_security_req *req); -struct nble_gap_sm_passkey { - uint8_t type; +enum NBLE_SM_PASSKEY_TYPE { + NBLE_SM_PK_PASSKEY, + NBLE_SM_PK_OOB, +}; + +struct nble_sm_passkey { + uint8_t type; /* see NBLE_SM_PASSKEY_TYPE */ union { uint32_t passkey; uint8_t oob[16]; @@ -332,42 +299,46 @@ struct nble_gap_sm_passkey { }; }; -struct nble_gap_sm_key_reply_req_params { +struct nble_sm_passkey_reply_req { struct bt_conn *conn; uint16_t conn_handle; - struct nble_gap_sm_passkey params; + struct nble_sm_passkey params; }; -void nble_gap_sm_passkey_reply_req(const struct nble_gap_sm_key_reply_req_params - *params); +void nble_sm_passkey_reply_req(const struct nble_sm_passkey_reply_req *req); -struct nble_gap_sm_clear_bond_req_params { +struct nble_sm_clear_bonds_req { bt_addr_le_t addr; }; -void nble_gap_sm_clear_bonds_req(const struct nble_gap_sm_clear_bond_req_params - *params); +void nble_sm_clear_bonds_req(const struct nble_sm_clear_bonds_req *req); -struct nble_gap_sm_response { +struct nble_sm_common_rsp { int status; struct bt_conn *conn; }; -void on_nble_gap_sm_common_rsp(const struct nble_gap_sm_response *rsp); +void on_nble_sm_common_rsp(const struct nble_sm_common_rsp *rsp); -/** - * Callback for rssi event. - */ -typedef void (*rssi_report_t)(const int8_t *rssi_data); +struct nble_sm_pairing_response_req { + struct bt_conn *conn; + uint16_t conn_handle; + struct nble_sm_pairing_param params; +}; -/** - * Callback for rssi report response. - */ -typedef void (*rssi_report_resp_t)(int status); +void nble_sm_pairing_response_req(const struct nble_sm_pairing_response_req *req); + +struct nble_sm_error_req { + struct bt_conn *conn; + uint16_t conn_handle; + uint8_t reason; +}; -struct nble_rssi_report_params { +void nble_sm_error_req(const struct nble_sm_error_req *req); + +struct nble_gap_set_rssi_report_req { uint16_t conn_handle; - /* RSSI operation @ref NBLE_GAP_RSSI_OPS */ + /* RSSI operation see NBLE_GAP_RSSI_OPS */ uint8_t op; /* Channel for RSSI enabling */ uint8_t channel; @@ -377,122 +348,78 @@ struct nble_rssi_report_params { uint8_t min_count; }; -void ble_gap_set_rssi_report(struct nble_rssi_report_params *params, - struct bt_conn *conn, - rssi_report_resp_t resp_cb, rssi_report_t evt_cb); - -void nble_gap_set_rssi_report_req(const struct nble_rssi_report_params *params, - void *user_data); +void nble_gap_set_rssi_report_req(const struct nble_gap_set_rssi_report_req *req, + void *user_data); -void on_nble_gap_set_rssi_report_rsp(const struct nble_response *params); +void on_nble_gap_set_rssi_report_rsp(const struct nble_common_rsp *rsp); -struct nble_gap_scan_params { +struct nble_scan_param { uint16_t interval; uint16_t window; + /* Unused for the connection request */ uint8_t scan_type; + /* Unused for the connection request */ uint8_t use_whitelist; }; -void nble_gap_start_scan_req(const struct nble_gap_scan_params *params); - -void nble_gap_stop_scan_req(void); - -void on_nble_gap_scan_start_stop_rsp(const struct nble_response *rsp); - -void nble_gap_connect_req(const struct nble_gap_connect_req_params *params, - void *user_data); - -void on_nble_gap_connect_rsp(const struct nble_response *params); +struct nble_gap_start_scan_req { + struct nble_scan_param scan_params; +}; -void nble_gap_cancel_connect_req(void *priv); +void nble_gap_start_scan_req(const struct nble_gap_start_scan_req *req); -void on_nble_gap_cancel_connect_rsp(const struct nble_response *params); +void nble_gap_stop_scan_req(void); -enum BLE_GAP_SET_OPTIONS { - BLE_GAP_SET_CH_MAP = 0, -}; +void on_nble_gap_scan_start_stop_rsp(const struct nble_common_rsp *rsp); -struct nble_gap_channel_map { - /* connection on which to change channel map */ - uint16_t conn_handle; - /* 37 bits are used of the 40 bits (LSB) */ - uint8_t map[5]; +struct nble_gap_connect_req { + bt_addr_le_t bda; + struct nble_conn_param conn_params; + struct nble_scan_param scan_params; }; +void nble_gap_connect_req(const struct nble_gap_connect_req *req, + void *user_data); -struct nble_gap_set_option_params { - /* Option to set @ref BLE_GAP_SET_OPTIONS */ - uint8_t op; - union { - struct nble_gap_channel_map ch_map; - }; -}; +void on_nble_gap_connect_rsp(const struct nble_common_rsp *rsp); -/* - * Generic request op codes. - * This allows to access some non connection related commands like DTM. - */ -enum BLE_GAP_GEN_OPS { - /* Not used now. */ - DUMMY_VALUE = 0, -}; +void nble_gap_cancel_connect_req(void *user_data); -struct nble_gap_gen_cmd_params { - /* @ref BLE_GAP_GEN_OPS */ - uint8_t op_code; -}; +void on_nble_gap_cancel_connect_rsp(const struct nble_common_rsp *rsp); /* Temporary patch: RSSI processing for UAS */ -struct nble_uas_rssi_calibrate { +struct nble_uas_rssi_calibrate_req { float distance; }; -void nble_uas_rssi_calibrate_req(const struct nble_uas_rssi_calibrate *p_struct); +void nble_uas_rssi_calibrate_req(const struct nble_uas_rssi_calibrate_req *req); /* Temporary patch: RSSI processing for UAS */ struct nble_uas_bucket_change { uint8_t distance; }; -void on_nble_uas_bucket_change(const struct nble_uas_bucket_change *p_params); - -struct nble_version { - uint8_t version; - uint8_t major; - uint8_t minor; - uint8_t patch; - char version_string[20]; - uint8_t hash[4]; -}; -typedef void (*ble_get_version_cb_t)(const struct nble_version *ver); +void on_nble_uas_bucket_change(const struct nble_uas_bucket_change *par); -struct nble_gap_get_version_param { - ble_get_version_cb_t cb; -}; - -struct nble_version_response { - struct nble_gap_get_version_param params; - struct nble_version ver; +struct nble_gap_set_tx_power_req { + int8_t tx_power; }; -void nble_get_version_req(const struct nble_gap_get_version_param *params); - -void on_nble_get_version_rsp(const struct nble_version_response *params); +void nble_gap_set_tx_power_req(const struct nble_gap_set_tx_power_req *req); -void nble_gap_dtm_init_req(void *user_data); +void on_nble_gap_set_tx_power_rsp(const struct nble_common_rsp *rsp); -void on_nble_gap_dtm_init_rsp(void *user_data); - -struct nble_gap_tx_power_params { - int8_t tx_power; +struct nble_conn_values { + /* Connection interval (unit 1.25 ms) */ + uint16_t interval; + /* Connection latency (unit interval) */ + uint16_t latency; + /* Connection supervision timeout (unit 10ms)*/ + uint16_t supervision_to; }; -void nble_gap_tx_power_req(const struct nble_gap_tx_power_params *params); - -void on_nble_gap_tx_power_rsp(const struct nble_response *params); - struct nble_gap_connect_evt { uint16_t conn_handle; - struct nble_gap_connection_values conn_values; + struct nble_conn_values conn_values; /* 0 if connected as master, otherwise as slave */ uint8_t role_slave; /* Address of peer device */ @@ -510,7 +437,7 @@ void on_nble_gap_disconnect_evt(const struct nble_gap_disconnect_evt *evt); struct nble_gap_conn_update_evt { uint16_t conn_handle; - struct nble_gap_connection_values conn_values; + struct nble_conn_values conn_values; }; void on_nble_gap_conn_update_evt(const struct nble_gap_conn_update_evt *evt); @@ -522,16 +449,17 @@ struct nble_gap_adv_report_evt { }; void on_nble_gap_adv_report_evt(const struct nble_gap_adv_report_evt *evt, - const uint8_t *buf, uint8_t len); + const uint8_t *data, uint8_t len); struct nble_gap_dir_adv_timeout_evt { uint16_t conn_handle; uint16_t error; }; -void on_nble_gap_dir_adv_timeout_evt(const struct nble_gap_dir_adv_timeout_evt *p_evt); +void on_nble_gap_dir_adv_timeout_evt(const struct nble_gap_dir_adv_timeout_evt *evt); + +#define BLE_GAP_RSSI_EVT_SIZE 32 -#define BLE_GAP_RSSI_EVT_SIZE 32 struct nble_gap_rssi_evt { uint16_t conn_handle; int8_t rssi_data[BLE_GAP_RSSI_EVT_SIZE]; @@ -539,91 +467,164 @@ struct nble_gap_rssi_evt { void on_nble_gap_rssi_evt(const struct nble_gap_rssi_evt *evt); -struct nble_gap_timout_evt { - uint16_t conn_handle; - /* reason for timeout @ref BLE_SVC_GAP_TIMEOUT_REASON */ - int reason; -}; - -struct nble_gap_sm_passkey_req_evt { +struct nble_sm_passkey_req_evt { uint16_t conn_handle; uint8_t key_type; }; -void on_nble_gap_sm_passkey_req_evt(const struct nble_gap_sm_passkey_req_evt *evt); +void on_nble_sm_passkey_req_evt(const struct nble_sm_passkey_req_evt *evt); -struct nble_gap_sm_passkey_disp_evt { +struct nble_sm_passkey_disp_evt { uint16_t conn_handle; uint32_t passkey; + uint8_t passkey_confirm; }; -void on_nble_gap_sm_passkey_display_evt(const struct nble_gap_sm_passkey_disp_evt *evt); +void on_nble_sm_passkey_disp_evt(const struct nble_sm_passkey_disp_evt *evt); + +enum NBLE_SM_STATUS_EVT { + NBLE_SM_STATUS_START_PAIRING, + NBLE_SM_STATUS_BONDING_COMPLETE, + NBLE_SM_STATUS_LINK_ENCRYPTED, + NBLE_SM_STATUS_LINK_SECURITY_CHANGE, +}; struct nble_link_sec { bt_security_t sec_level; uint8_t enc_size; }; -struct nble_gap_sm_status_evt { +struct nble_sm_status_evt { uint16_t conn_handle; - uint8_t evt_type; + uint8_t evt_type; /* see NBLE_SM_STATUS_EVT */ int status; - struct nble_link_sec enc_link_sec; + union { + struct nble_link_sec enc_link_sec; + bt_addr_le_t addr; + }; }; -void on_nble_gap_sm_status_evt(const struct nble_gap_sm_status_evt *evt); +void on_nble_sm_status_evt(const struct nble_sm_status_evt *evt); -void on_nble_set_bda_rsp(const struct nble_set_bda_rsp *params); - -enum BLE_INFO_REQ_TYPES { - BLE_INFO_BONDING = 1, /* Get bonding database related information */ - BLE_INFO_LAST /* Keep last */ +struct nble_sec_param { + uint8_t auth; + uint8_t io_capabilities; + uint8_t min_key_size; + uint8_t max_key_size; }; -struct ble_gap_bonded_dev_info -{ - uint8_t addr_count; /* Count of le_addr in array. */ - uint8_t irk_count; /* IRK count */ - bt_addr_le_t le_addr[]; /* Bonded device address */ +struct nble_sm_pairing_request_evt { + uint16_t conn_handle; + struct nble_sec_param sec_param; }; -struct ble_get_info_rsp { - int status; /* Response status */ - uint8_t info_type; /* Requested information type */ - struct ble_gap_bonded_dev_info info_params; +void on_nble_sm_pairing_request_evt(const struct nble_sm_pairing_request_evt *evt); + +struct nble_sm_security_request_evt { + uint16_t conn_handle; + struct nble_sec_param sec_param; }; -struct nble_gap_sm_bond_info; -typedef void (*ble_bond_info_cb_t)(const struct nble_gap_sm_bond_info *info, - const bt_addr_le_t *addr, uint16_t len, - void *user_data); +void on_nble_sm_security_request_evt(const struct nble_sm_security_request_evt *evt); -struct nble_gap_sm_bond_info_param { +struct nble_sm_bond_info; +typedef void (*ble_bond_info_cb_t)(const struct nble_sm_bond_info *info, + const bt_addr_le_t *addr, uint16_t len, + void *user_data); + +struct nble_sm_bond_info_req { ble_bond_info_cb_t cb; void *user_data; bool include_bonded_addrs; }; -void nble_gap_sm_bond_info_req(const struct nble_gap_sm_bond_info_param *params); +void nble_sm_bond_info_req(const struct nble_sm_bond_info_req *req); -struct nble_gap_sm_bond_info { +struct nble_sm_bond_info { int err; uint8_t addr_count; uint8_t irk_count; }; -struct nble_gap_sm_bond_info_rsp { +struct nble_sm_bond_info_rsp { ble_bond_info_cb_t cb; void *user_data; - struct nble_gap_sm_bond_info info; + struct nble_sm_bond_info info; +}; + +void on_nble_sm_bond_info_rsp(const struct nble_sm_bond_info_rsp *rsp, + const bt_addr_le_t *peer_addr, uint16_t len); + +struct nble_uart_test_req { + /* Test type */ + uint16_t test_type; + /* Number of loops */ + uint16_t nb_loops; + /* The maximum delay */ + uint16_t max_delay; + /* The maximum length */ + uint16_t max_len; }; -void on_nble_gap_sm_bond_info_rsp(const struct nble_gap_sm_bond_info_rsp *rsp, - const bt_addr_le_t *peer_addr, uint16_t len); +void nble_uart_test_req(const struct nble_uart_test_req *req, + const uint8_t *data, uint8_t len); + +struct nble_uart_test_evt { + /* Number of loops executed */ + uint16_t nb_loops; +}; -void ble_gap_get_bonding_info(ble_bond_info_cb_t func, void *user_data, - bool include_bonded_addrs); +void on_nble_uart_test_evt(const struct nble_uart_test_evt *evt, + const uint8_t *data, uint8_t len); + +struct nble_gap_rpa_update_evt { + bt_addr_le_t addr; +}; + +void on_nble_gap_rpa_update_evt(const struct nble_gap_rpa_update_evt *evt); + +/* + * The following functions are NOT RPC functions + */ void ble_gap_get_version(ble_get_version_cb_t func); +void ble_gap_get_bda_info(struct bt_local_addr *addr); + +enum NBLE_GAP_RSSI_OPS { + NBLE_GAP_RSSI_DISABLE_REPORT = 0, + NBLE_GAP_RSSI_ENABLE_REPORT +}; + +typedef void (*rssi_report_t)(const int8_t *rssi_data); + +typedef void (*rssi_report_resp_t)(int status); + +struct ble_rssi_report_params { + /* RSSI operation see NBLE_GAP_RSSI_OPS */ + uint8_t op; + /* Channel for RSSI enabling */ + uint8_t channel; + /* minimum RSSI dBm change to report a new RSSI value */ + uint8_t delta_dBm; + /* number of delta_dBm changes before sending a new RSSI report */ + uint8_t min_count; +}; + +void ble_gap_set_rssi_report(struct ble_rssi_report_params *par, + struct bt_conn *conn, + rssi_report_resp_t resp_cb, rssi_report_t evt_cb); + +/* Hook function to release to BT controller reset */ +void nble_curie_unreset_hook(void); + +/* Hook function to display log from the BT controller */ +void nble_curie_log_hook(char *fmt, ...); + +/* Function to set the RPA address */ +int le_set_rpa(void); + +int bt_le_scan_update(bool fast_scan); + +int set_advertise_enable(void); #endif /* GAP_INTERNAL_H_ */ diff --git a/system/libarc32_arduino101/framework/src/services/ble_service/gatt_internal.h b/system/libarc32_arduino101/framework/src/services/ble_service/gatt_internal.h index 25ac4da8..6185dbf9 100644 --- a/system/libarc32_arduino101/framework/src/services/ble_service/gatt_internal.h +++ b/system/libarc32_arduino101/framework/src/services/ble_service/gatt_internal.h @@ -20,8 +20,6 @@ #include #include -/* Forward declarations */ -struct nble_response; #define BLE_GATT_MTU_SIZE 23 @@ -30,98 +28,154 @@ struct nble_response; * Typically they are required if gatt.h APIs can not be mapped 1:1 onto controller API */ -enum NBLE_GATT_IND_TYPES { - NBLE_GATT_IND_TYPE_NONE = 0, - NBLE_GATT_IND_TYPE_NOTIFICATION, - NBLE_GATT_IND_TYPE_INDICATION, +/* + * GATT Attribute stream structure. + */ +struct nble_gatts_attr { + /* Attribute pointer */ + struct bt_gatt_attr *attr; + /* Attribute permissions */ + uint16_t perm; + /* Attribute variable data size */ + uint16_t data_size; + /* Attribute variable data: always starts with the UUID and data follows */ + uint8_t data[]; }; -struct nble_gatt_register_req { +struct nble_gatts_register_req { /* Base address of the attribute table in the Quark mem space */ struct bt_gatt_attr *attr_base; /* Number of of attributes in this service */ uint8_t attr_count; }; -struct nble_gatt_register_rsp { +void nble_gatts_register_req(const struct nble_gatts_register_req *req, + uint8_t *data, uint16_t len); + +struct nble_gatts_register_rsp { int status; struct bt_gatt_attr *attr_base; /* Number of attributes successfully added */ uint8_t attr_count; }; +struct nble_gatt_attr_handles { + uint16_t handle; +}; + +void on_nble_gatts_register_rsp(const struct nble_gatts_register_rsp *rsp, + const struct nble_gatt_attr_handles *attrs, + uint8_t len); + enum nble_gatt_wr_flag { NBLE_GATT_WR_FLAG_REPLY = 1, NBLE_GATT_WR_FLAG_PREP = 2, }; -struct nble_gatt_wr_evt { +struct nble_gatts_write_evt { struct bt_gatt_attr *attr; uint16_t conn_handle; uint16_t offset; - uint8_t flag; /* Cf. enum nble_gatt_wr_flag */ + /* see nble_gatt_wr_flag */ + uint8_t flag; +}; + +void on_nble_gatts_write_evt(const struct nble_gatts_write_evt *evt, + const uint8_t *data, uint8_t len); + +struct nble_gatts_write_reply_req { + uint16_t conn_handle; + uint16_t offset; + int32_t status; }; -struct nble_gatt_wr_exec_evt { +void nble_gatts_write_reply_req(const struct nble_gatts_write_reply_req *req, + const uint8_t *data, uint8_t len); + +struct nble_gatts_write_exec_evt { uint16_t conn_handle; uint8_t flag; }; -struct nble_gatt_rd_evt { +void on_nble_gatts_write_exec_evt(const struct nble_gatts_write_exec_evt *evt); + +struct nble_gatts_read_evt { struct bt_gatt_attr *attr; uint16_t conn_handle; uint16_t offset; }; -struct nble_gatts_rd_reply_params { +void on_nble_gatts_read_evt(const struct nble_gatts_read_evt *evt); + +struct nble_gatts_read_reply_req { uint16_t conn_handle; uint16_t offset; int32_t status; }; -struct nble_gatts_wr_reply_params { - uint16_t conn_handle; - int32_t status; -}; +void nble_gatts_read_reply_req(const struct nble_gatts_read_reply_req *req, + uint8_t *data, uint16_t len); -struct nble_gatt_notif_ind_params { +struct nble_gatts_value_change_param { const struct bt_gatt_attr *attr; + uint16_t conn_handle; uint16_t offset; }; -struct nble_gatt_send_notif_params { +struct nble_gatts_notify_req { /* Function to be invoked when buffer is freed */ bt_gatt_notify_sent_func_t cback; - uint16_t conn_handle; - struct nble_gatt_notif_ind_params params; + struct nble_gatts_value_change_param params; }; -struct nble_gatt_notif_rsp { +void nble_gatts_notify_req(const struct nble_gatts_notify_req *req, + const uint8_t *data, uint16_t len); + +struct nble_gatts_notify_tx_evt { bt_gatt_notify_sent_func_t cback; - int status; - uint16_t conn_handle; + uint8_t status __attribute__ ((aligned (4))); + uint16_t conn_handle __attribute__ ((aligned (4))); struct bt_gatt_attr *attr; }; -struct nble_gatt_send_ind_params { +void on_nble_gatts_notify_tx_evt(const struct nble_gatts_notify_tx_evt *evt); + +struct nble_gatts_indicate_req { /* Function to be invoked when buffer is freed */ bt_gatt_indicate_func_t cback; - uint16_t conn_handle; - struct nble_gatt_notif_ind_params params; + struct nble_gatts_value_change_param params; }; -struct nble_gatt_ind_rsp { +void nble_gatts_indicate_req(const struct nble_gatts_indicate_req *req, + const uint8_t *data, uint8_t len); + +struct nble_gatts_indicate_rsp { bt_gatt_indicate_func_t cback; - int status; - uint16_t conn_handle; struct bt_gatt_attr *attr; + uint8_t status; + uint16_t conn_handle; }; +void on_nble_gatts_indicate_rsp(const struct nble_gatts_indicate_rsp *rsp); + +#define DISCOVER_FLAGS_UUID_PRESENT 1 + struct nble_gatt_handle_range { uint16_t start_handle; uint16_t end_handle; }; +struct nble_gattc_discover_req { + void *user_data; + struct bt_uuid_128 uuid; + struct nble_gatt_handle_range handle_range; + uint16_t conn_handle; + uint8_t type; + uint8_t flags; +}; + +void nble_gattc_discover_req(const struct nble_gattc_discover_req *req); + struct nble_gattc_primary { uint16_t handle; struct nble_gatt_handle_range range; @@ -147,162 +201,98 @@ struct nble_gattc_descriptor { }; struct nble_gattc_discover_rsp { - int32_t status; + uint8_t status; void *user_data; uint16_t conn_handle; uint8_t type; }; -struct nble_gatts_attribute_rsp { - int32_t status; - struct bt_gatt_attr *attr; - void *user_data; -}; - -void nble_gatts_rd_reply_req(const struct nble_gatts_rd_reply_params *, uint8_t *, uint16_t); - -void nble_gatts_wr_reply_req(const struct nble_gatts_wr_reply_params *p_params); - -void nble_gatt_register_req(const struct nble_gatt_register_req *p_param, - uint8_t *p_buf, - uint16_t len); - -struct nble_gatt_attr_handles { - uint16_t handle; -}; - -void on_nble_gatt_register_rsp(const struct nble_gatt_register_rsp *p_param, - const struct nble_gatt_attr_handles *p_attrs, uint8_t len); - -void on_nble_gatts_write_evt(const struct nble_gatt_wr_evt *p_evt, - const uint8_t *p_buf, uint8_t buflen); - -void on_nble_gatts_write_exec_evt(const struct nble_gatt_wr_exec_evt *evt); - -void on_nble_gatts_read_evt(const struct nble_gatt_rd_evt *p_evt); - -void nble_gatt_send_notif_req(const struct nble_gatt_send_notif_params *p_params, - const uint8_t *p_value, uint16_t length); - -void nble_gatt_send_ind_req(const struct nble_gatt_send_ind_params *p_params, - const uint8_t *p_value, uint8_t length); - -void on_nble_gatts_send_notif_rsp(const struct nble_gatt_notif_rsp *rsp); - -void on_nble_gatts_send_ind_rsp(const struct nble_gatt_ind_rsp *rsp); - -#define DISCOVER_FLAGS_UUID_PRESENT 1 +void on_nble_gattc_discover_rsp(const struct nble_gattc_discover_rsp *rsp, + const uint8_t *data, uint8_t len); -struct nble_discover_params { +struct nble_gattc_read_req { void *user_data; - struct bt_uuid_128 uuid; - struct nble_gatt_handle_range handle_range; uint16_t conn_handle; - uint8_t type; - uint8_t flags; + uint16_t handle; + uint16_t offset; }; -void nble_gattc_discover_req(const struct nble_discover_params *req); - -void on_nble_gattc_discover_rsp(const struct nble_gattc_discover_rsp *rsp, - const uint8_t *data, uint8_t data_len); - -/* - * GATT Attribute stream structure. - * - * This structure is a "compressed" copy of @ref bt_gatt_attr. - * UUID pointer and user_data pointer are used as offset into buffer itself. - * The offset is from the beginning of the buffer. therefore a value of 0 - * means that UUID or user_data is not present. - */ -struct ble_gatt_attr { - /* Attribute permissions */ - uint16_t perm; - /* Attribute variable data size */ - uint16_t data_size; - /* Attribute variable data: always starts with the UUID and data follows */ - uint8_t data[]; -}; +void nble_gattc_read_req(const struct nble_gattc_read_req *req); -struct ble_gattc_read_params { +struct nble_gattc_read_rsp { + uint8_t status; void *user_data; uint16_t conn_handle; uint16_t handle; uint16_t offset; }; -struct ble_gattc_read_multiple_params { - void *user_data; - uint16_t conn_handle; -}; +void on_nble_gattc_read_rsp(const struct nble_gattc_read_rsp *rsp, + uint8_t *data, uint8_t len); -struct ble_gattc_read_rsp { - int status; +struct nble_gattc_read_multi_req { void *user_data; uint16_t conn_handle; - uint16_t handle; - uint16_t offset; }; -/* forward declaration */ -struct bt_gatt_write_params; +void nble_gattc_read_multi_req(const struct nble_gattc_read_multi_req *req, + const uint16_t *handles, uint16_t len); + +void on_nble_gattc_read_multi_rsp(const struct nble_gattc_read_rsp *rsp, + uint8_t *data, uint8_t len); + +struct nble_gattc_write_param; typedef void (*bt_att_func_t)(struct bt_conn *conn, uint8_t err, - const struct bt_gatt_write_params *wr_params); + const struct nble_gattc_write_param *par); -struct bt_gatt_write_params { +struct nble_gattc_write_param { /* Function invoked upon write response */ bt_att_func_t func; /* User specific data */ void *user_data[2]; }; -struct ble_gattc_write_params { +struct nble_gattc_write_req { uint16_t conn_handle; uint16_t handle; uint16_t offset; /* different than 0 if response required */ uint8_t with_resp; - struct bt_gatt_write_params wr_params; + struct nble_gattc_write_param wr_params; }; -struct ble_gattc_write_rsp { +void nble_gattc_write_req(const struct nble_gattc_write_req *req, + const uint8_t *data, uint16_t len); + +struct nble_gattc_write_rsp { + uint8_t status; uint16_t conn_handle; - int status; uint16_t handle; - uint16_t len; - struct bt_gatt_write_params wr_params; + struct nble_gattc_write_param wr_params; }; -void nble_gattc_read_req(const struct ble_gattc_read_params *params); - -void on_nble_gattc_read_rsp(const struct ble_gattc_read_rsp *rsp, - uint8_t *data, uint8_t data_len); - -void nble_gattc_read_multiple_req( - const struct ble_gattc_read_multiple_params *params, - const uint16_t *data, uint16_t data_len); - -void on_nble_gattc_read_multiple_rsp(const struct ble_gattc_read_rsp *rsp, - uint8_t *data, uint8_t data_len); - -void nble_gattc_write_req(const struct ble_gattc_write_params *params, - const uint8_t *buf, uint8_t buflen); - -void on_nble_gattc_write_rsp(const struct ble_gattc_write_rsp *rsp); +void on_nble_gattc_write_rsp(const struct nble_gattc_write_rsp *rsp); void bt_gatt_connected(struct bt_conn *conn); void bt_gatt_disconnected(struct bt_conn *conn); +enum NBLE_GATTC_EVT { + NBLE_GATTC_EVT_NOTIFICATION, + NBLE_GATTC_EVT_INDICATION, +}; -struct ble_gattc_value_evt { - uint16_t conn_handle; +struct nble_gattc_value_evt { int status; + uint16_t conn_handle; uint16_t handle; + /* see NBLE_GATTC_VALUE_EVT */ uint8_t type; }; -void on_nble_gattc_value_evt(const struct ble_gattc_value_evt *evt, - uint8_t *buf, uint8_t buflen); +void on_nble_gattc_value_evt(const struct nble_gattc_value_evt *evt, + uint8_t *data, uint8_t len); +void *nble_curie_alloc_hook(uint32_t size); +void nble_curie_free_hook(void *buffer); #endif /* GATT_INTERNAL_H_ */ diff --git a/system/libarc32_arduino101/framework/src/services/ble_service/nble_driver.c b/system/libarc32_arduino101/framework/src/services/ble_service/nble_driver.c index 4a128f13..544f733c 100644 --- a/system/libarc32_arduino101/framework/src/services/ble_service/nble_driver.c +++ b/system/libarc32_arduino101/framework/src/services/ble_service/nble_driver.c @@ -66,7 +66,7 @@ static uint16_t rpc_port_id; static list_head_t m_rpc_tx_q; -extern void on_nble_curie_log(char *fmt, ...) +void nble_curie_log_hook(char *fmt, ...) { va_list args; @@ -75,6 +75,16 @@ extern void on_nble_curie_log(char *fmt, ...) va_end(args); } +void *nble_curie_alloc_hook(uint32_t size) +{ + return balloc(size, NULL); +} + +void nble_curie_free_hook(void *buffer) +{ + bfree(buffer); +} + /* * When we set val to 1 it will wake up the remote (BLE Core), setting it to 0 * will allow remote to sleep. @@ -225,10 +235,11 @@ static int uart_ipc_rpc_cback(int channel, int request, int len, void *p_data) /* if BLE service is available, handle it in BLE service context */ struct ble_rpc_callin *rpc = (void *) message_alloc( sizeof(*rpc), NULL); -if (NULL == rpc) -{ - panic(-1); -} + if (NULL == rpc) + { + panic(-1); + } + MESSAGE_ID(&rpc->msg) = 0; MESSAGE_LEN(&rpc->msg) = sizeof(*rpc); MESSAGE_SRC(&rpc->msg) = rpc_port_id; @@ -280,8 +291,13 @@ uint8_t *rpc_alloc_cb(uint16_t length) return p_elt->data; } +void rpc_free_cb(const uint8_t *buf) +{ + // Stub +} + /* called under NON-interrupt context */ -void rpc_transmit_cb(uint8_t *p_buf, uint16_t length) +void rpc_transmit_cb(uint8_t *p_buf) { struct rpc_tx_elt *p_elt; @@ -297,32 +313,27 @@ void rpc_transmit_cb(uint8_t *p_buf, uint16_t length) * other constraints: therefore, this reset might not work everytime, especially after * flashing or debugging. */ -void nble_driver_init(void) +void nble_driver_hw_reset(void) { uint32_t delay_until; - - nble_interface_init(); - /* Setup UART0 for BLE communication, HW flow control required */ - SET_PIN_MODE(18, QRK_PMUX_SEL_MODEA); /* UART0_RXD */ - SET_PIN_MODE(19, QRK_PMUX_SEL_MODEA); /* UART0_TXD */ - SET_PIN_MODE(40, QRK_PMUX_SEL_MODEB); /* UART0_CTS_B */ - SET_PIN_MODE(41, QRK_PMUX_SEL_MODEB); /* UART0_RTS_B */ - - ipc_uart_init(0); - - //while (1) - //{} + /* RESET_PIN depends on the board and the local configuration: check top of file */ gpio_cfg_data_t pin_cfg = { .gpio_type = GPIO_OUTPUT }; + delay_until = get_uptime_32k() + 32768 * 2; // 2ms wait for Nordic chip boot + while (get_uptime_32k() < delay_until); + + ipc_uart_init(0); + soc_gpio_set_config(SOC_GPIO_32, RESET_PIN, &pin_cfg); //soc_gpio_set_config(SOC_GPIO_32_ID, BLE_SW_CLK_PIN, &pin_cfg); /* Reset hold time is 0.2us (normal) or 100us (SWD debug) */ soc_gpio_write(SOC_GPIO_32, RESET_PIN, 0); /* Wait for ~1ms */ - delay_until = get_uptime_32k() + 32768; + delay_until = get_uptime_32k() + 327;//68; /* Open the UART channel for RPC while Nordic is in reset */ + //if (NULL == m_rpc_channel) m_rpc_channel = ipc_uart_channel_open(RPC_CHANNEL, uart_ipc_rpc_cback); while (get_uptime_32k() < delay_until); @@ -336,6 +347,19 @@ void nble_driver_init(void) soc_gpio_set_config(SOC_GPIO_32, RESET_PIN, &pin_cfg); } +void nble_driver_init(void) +{ + + nble_interface_init(); + /* Setup UART0 for BLE communication, HW flow control required */ + SET_PIN_MODE(18, QRK_PMUX_SEL_MODEA); /* UART0_RXD */ + SET_PIN_MODE(19, QRK_PMUX_SEL_MODEA); /* UART0_TXD */ + SET_PIN_MODE(40, QRK_PMUX_SEL_MODEB); /* UART0_CTS_B */ + SET_PIN_MODE(41, QRK_PMUX_SEL_MODEB); /* UART0_RTS_B */ + + nble_driver_hw_reset(); +} + void nble_driver_configure(T_QUEUE queue, void (*handler)(struct message*, void*)) { @@ -346,7 +370,7 @@ void nble_driver_configure(T_QUEUE queue, void (*handler)(struct message*, void* } -void on_nble_curie_init(void) +void nble_curie_unreset_hook(void) { nble_driver_init(); } diff --git a/system/libarc32_arduino101/framework/src/services/ble_service/nble_driver.h b/system/libarc32_arduino101/framework/src/services/ble_service/nble_driver.h index 7ea15b44..b4e8cb74 100644 --- a/system/libarc32_arduino101/framework/src/services/ble_service/nble_driver.h +++ b/system/libarc32_arduino101/framework/src/services/ble_service/nble_driver.h @@ -47,6 +47,7 @@ struct ble_rpc_callin { * mechanism is up and running. */ void nble_driver_init(void); +void nble_driver_hw_reset(void); void nble_driver_configure(T_QUEUE queue, void (*handler)(struct message*, void*)); diff --git a/system/libarc32_arduino101/framework/src/services/ble_service/storage_internal.h b/system/libarc32_arduino101/framework/src/services/ble_service/storage_internal.h new file mode 100644 index 00000000..2fab1b73 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble_service/storage_internal.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STORAGE_INTERNAL_H_ +#define STORAGE_INTERNAL_H_ + +struct nble_storage_read_evt { + bt_addr_le_t addr; + /* valid only for BT_STORAGE_ADDRESSES */ + uint8_t max_num_keys; + uint16_t key; +}; + +enum { + NBLE_STORAGE_UPDATE = BIT(0), /* key update */ +}; + +struct nble_storage_write_evt { + uint8_t flags; + bt_addr_le_t addr; + uint16_t key; +}; + +struct nble_storage_read_rsp_req { + int status; /* posix status code */ + bt_addr_le_t addr; + uint16_t key; +}; + +void on_nble_storage_read_evt(const struct nble_storage_read_evt *evt); + +void on_nble_storage_write_evt(const struct nble_storage_write_evt *evt, + const uint8_t *data, uint16_t len); + +void nble_storage_read_rsp_req(const struct nble_storage_read_rsp_req *req, + const uint8_t *data, uint16_t len); + +#endif //STORAGE_INTERNAL_H_ diff --git a/variants/arduino_101/libarc32drv_arduino101.a b/variants/arduino_101/libarc32drv_arduino101.a index db6e5b45..6c78d7ef 100644 Binary files a/variants/arduino_101/libarc32drv_arduino101.a and b/variants/arduino_101/libarc32drv_arduino101.a differ diff --git a/variants/arduino_101/linker_scripts/flash.ld b/variants/arduino_101/linker_scripts/flash.ld index 7ba34942..58127bd0 100644 --- a/variants/arduino_101/linker_scripts/flash.ld +++ b/variants/arduino_101/linker_scripts/flash.ld @@ -52,7 +52,7 @@ __firq_stack_size = 1024; /* Minimum heap size to allocate * Actual heap size might be bigger due to page size alignment */ -__HEAP_SIZE_MIN = 16384; +__HEAP_SIZE_MIN = 20480; /* This should be set to the page size used by the malloc implementation */ __PAGE_SIZE = 4096;