Skip to content

New BLE API preview #337

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 19, 2016
Merged

New BLE API preview #337

merged 2 commits into from
Dec 19, 2016

Conversation

sgbihu
Copy link
Contributor

@sgbihu sgbihu commented Oct 27, 2016

A preview version for Arduino BLE API.
Just for test, please don't merge now.

@noelpaz
Copy link
Contributor

noelpaz commented Oct 27, 2016

On 1.0.7 with older BLE FW , the advertised address is the same as the one on the sticker
ex: 98:4F:EE:0C:FC:D7
On 2.0.0 with V3 FW, the advertised address is not the same and completely different
ex: D2:18:86:B3:59:25
but if it does a self inquiry using the API call BLE.address
it gets the same address as in the sticker.

@sandeepmistry
Copy link
Contributor

I have made the same observation as @noelpaz, on the sticker 98:4F:EE:0C:07:A5 is displayed and BLE.address() returns the same value. The OS X Packet Logger app (from Xcode Hardware IO tools) is displaying an address of CB:0A:84:1D:F7:A7 and random device address. Previously a public device address was used that matched the sticker.

screen shot 2016-10-27 at 5 24 37 pm

cc/ @agdl

@SidLeung
Copy link
Contributor

SidLeung commented Oct 27, 2016

Jira ticket, 738, created for this issue. The issue did not indicate a manufacturing problem as initially suspected. Thus, OTP area memory content were initialized correctly and was intag.

Copy link
Contributor

@sandeepmistry sandeepmistry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @sgbihu,

I've done a first pass review of the public facing API and made my comments.

We need to discuss the details of how to filter scanning by local name and service UUID, it was not in the original spec. Also, when scanning I cannot seem to access the peripheral local name, an empty string is always returned.

#include "BLEAttribute.h"
#include "BLECharacteristicImp.h"
#include "BLEProfileManager.h"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we replace all of these includes with just #include <CurieBLE.h>?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

#define LED_PIN 13

void setup() {
Serial.begin(115200);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All examples should use a baud rate of 9600 for Serial, as it's the default baud rate of the IDE's Serial Monitor.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Serial.println("test---");

// set LED pin to output mode
pinMode(LED_PIN, OUTPUT);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example does not need to control the on board LED, we can remove this.

BLE.begin();
Serial.println(BLE.address());

BLE.startScanning("LED");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filtering scanning by name (or service UUID) is not something we discussed, we need to have a broader discussion on this.

Also, you should be allowed to scan without any filters.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the environment is noisy, the available api is slow, need more buffer in the stack. I think we need consider those questions

  1. The RAM
  2. Does device need buffer the ADV's data?
  3. How to let user process the RAW ADV data?
  4. Filter ADV

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've started another discussion on this outside this PR.

We can drop discovered peripherals if the user does not call available() fast enough.

We should not expose the raw advertisement and scan response to the user. There are some existing API's in BLE devices for them to access the parsed data.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

BLE.startScanning("LED");
}

void controlLed(BLEDevice &peripheral)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should aim to remove all passing by reference from the examples.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

void setAcceptAdvertiseLocalName(String name);
void setAcceptAdvertiseLocalName(BLEService& service);
void setAcceptAdvertiseCallback(String name);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The setAcceptAdvertise* API's should not be public.

bool operator!=(const BLEDevice& device) const;
//BLEDevice& operator=(const BLEDevice& device);
// central mode
void startScanning(String name); // start scanning for peripherals
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to support scanning without filters and have a broader discussion for how to do filtering for both local name and service uuid's.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had the same question -- or maybe support "*" wildcard

/*
BLE Device API
Copyright (c) 2016 Arduino LLC. All right reserved.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this an internal class? If so, can we move it to src/internal/BLEDeviceManager.h?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will move implementation related class definitions/files to the internal subdirectory.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -0,0 +1,894 @@
/*
* Copyright (c) 2016 Intel Corporation. All rights reserved.
*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to above, is this an internal class?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

*
* @note none
*/
bool setValue(T value);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We discussed a new writeValue operations, I don't see them here. setValue will be deprecated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. This PRU already include deprecated code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well you have setValue but I doubt see the new writeValue in here though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed for baseline.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor

@eriknyquist eriknyquist left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to be more careful when using the heap. Remember that using new also allocates on the heap, and pointers to objects allocated with new also need to be checked for NULL-ness.

Additionally, I noticed that you are using balloc() instead of malloc(). This function calls cfw_alloc() which simply calls malloc() but disables interrupts first.
(See here https://github.com/01org/corelibs-arduino101/blob/master/system/libarc32_arduino101/framework/src/os/os.c#L43)
Is this really necessary? Is there some reason you cannot use malloc()?

if (NULL == _attr_base)
{
_attr_base = (bt_gatt_attr_t *)balloc(attr_counter * sizeof(bt_gatt_attr_t), NULL);
memset(_attr_base, 0x00, (attr_counter * sizeof(bt_gatt_attr_t)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check for NULL-ness before memset

BLEDevice bleDevice(bt_conn_get_dst(conn));

// Get characteristic by handle params->single.handle
chrc = BLEProfileManager::instance()->characteristic(bleDevice, params->single.handle);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remember, every time you call BLEProfileManager::instance(), it creates a new BLEProfileManager on the (very small) heap. Running out of heap space is very possible with < 8k available. Always check for NULL-ness.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Used Singleton pattern, it only be created 1 time. Will add assert to avoid NULL check in instance method. If the device can't allocate the memory, the APP can't execute correct.

_value = (unsigned char*)balloc(_value_size, NULL);
if (_value_size > BLE_MAX_ATTR_DATA_LEN)
{
_value_buffer = (unsigned char*)balloc(_value_size, NULL);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check _value and _value_buffer for NULL-ness. Heap is very small, it might well be NULL.

Copy link
Contributor

@eriknyquist eriknyquist left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still a lot of unchecked heap allocations happening.


if (NULL != characteristic._value)
{
memcpy(_value, characteristic._value, _value_size);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_value is a pointer returned from malloc. You need to check for NULL-ness before using it.

return;
}

memcpy(_value_buffer + offset, value, length);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check _value_buffer for NULL-ness before using.


_value_size = descriptorImp->valueSize();
_value = (unsigned char*)balloc(_value_size, NULL);
memcpy(_value, descriptorImp->value(), _value_size);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can't assume balloc/malloc will return a valid pointer. ALways check it for NULL-ness.

_bledev.setAddress(*BLEUtils::bleGetLoalAddress());

_value_size = valueLength > BLE_MAX_ATTR_LONGDATA_LEN ? BLE_MAX_ATTR_LONGDATA_LEN : valueLength;
_value = (unsigned char*)balloc(_value_size, NULL);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing as line 44. Have to check _value for NULL-ness

_value_length = descriptor.valueLength();
_value = (unsigned char*)balloc(_value_length, NULL);

memcpy(_value, descriptor.value(), _value_length);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You must check _value for NULL-ness before you try to copy something to it.

_value_length = BLE_MAX_ATTR_DATA_LEN;
_value = (unsigned char*)balloc(_value_length, NULL);

memset(_value, 0, _value_length);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pointer _value was returned by balloc. Check for NULL-ness first.

@@ -14,12 +14,12 @@ compiler.prefix=arc-elf32

compiler.path={runtime.tools.arc-elf32.path}/bin/
compiler.c.cmd=arc-elf32-gcc
compiler.c.flags=-c -std=gnu11 -mcpu=quarkse_em -mlittle-endian -g -Os -Wall -fno-reorder-functions -fno-asynchronous-unwind-tables -fno-omit-frame-pointer -fno-defer-pop -Wno-unused-but-set-variable -Wno-main -ffreestanding -fno-stack-protector -mno-sdata -ffunction-sections -fdata-sections -fsigned-char -MMD -D__ARDUINO_ARC__ -DCONFIG_BLUETOOTH_PERIPHERAL -DCONFIG_BLUETOOTH_CENTRAL -DCONFIG_BLUETOOTH_GATT_CLIENT
compiler.c.flags=-c -std=gnu11 -mcpu=quarkse_em -mlittle-endian -g -O0 -Wall -fno-reorder-functions -fno-asynchronous-unwind-tables -fno-omit-frame-pointer -fno-defer-pop -Wno-unused-but-set-variable -Wno-main -ffreestanding -fno-stack-protector -mno-sdata -ffunction-sections -fdata-sections -fsigned-char -MMD -D__ARDUINO_ARC__ -DCONFIG_BLUETOOTH_PERIPHERAL -DCONFIG_BLUETOOTH_CENTRAL -DCONFIG_BLUETOOTH_GATT_CLIENT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a fix, a temporary patch.

1. Add new library

2. Add BLEPeripheral library back compatible features

3. Fix IMU build issue

4. Fix the memset crash issue
  i.  The FIRQ doesn't save the LP_COUNTER register.
  ii. Update the code to save LP related register

5. Fix the central crash issue when peripheral disconnect

6. Revert the UART changes
   -This change will break the BLE's communication

7. Implement the balloc to replace old one
   -Create memory pool
   -Port V3's balloc
   -Fix the local name display unexpected chars

8. Fix ScanCallback, LED related issue
   -The Serial.print called in interrupt and interrupt block the Serial interrupt.
   -The resource not released when call disconnect API.

9. Fix the discover blocked when connect/disconnect the link successively

Block the disconnect if not receive the disconnect event

10. Return error when discover attributes if error happened

11. Update the back compatible comments

12. Fix the discover attribute failed issue
    -Add the -fcheck-new build option
    -Increase the IRQ stack size

13. Add discoverAttributesByService API
    - The sensorTag has many services and RAM is not enough for discover all services
    -This crash caused by bt_uuid_16 and bt_uuid_128 has different space and makes an address exception

14. Add keywords and fix read issue

15. Update the CurieBLE and delete BLE
@calvinatintel calvinatintel merged commit 4c89a18 into arduino:master Dec 19, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants