diff --git a/README.md b/README.md index a710c0f3..b437314b 100644 --- a/README.md +++ b/README.md @@ -53,3 +53,21 @@ them to the [support forum](https://forum.arduino.cc/index.php?board=103). > "How do I use this library?" > "I can't get this example sketch to work. What am I doing wrong?" + +# Enable debug interface on Serail1 + +* Default disable the debug interface. + +If you want to enable debug trace on Serial1 to debug corelib, follow these instructions. + +1. Shut down the IDE +2. Go to Arduino15 directory + * Windows: `C:\Users\\AppData\Roaming\Arduino15` + * OS X: `~/Library/Arduino15` + * Linux: `~/.arduino15` +3. Modify the platform.txt + * Find `compiler.c.flags` and add `-DCONFIGURE_DEBUG_CORELIB_ENABLED` at the end of this line + * Find `compiler.cpp.flags` and add `-DCONFIGURE_DEBUG_CORELIB_ENABLED` at the end of this line +4. Initial Serial1 in your sketch + * Add `Serial1.begin(115200);` in your `setup()` +5. Adjust the output level at log_init function in log.c diff --git a/system/libarc32_arduino101/framework/src/nordic_interface.h b/cores/arduino/printk.cpp similarity index 79% rename from system/libarc32_arduino101/framework/src/nordic_interface.h rename to cores/arduino/printk.cpp index 1b187b16..babfc0ed 100644 --- a/system/libarc32_arduino101/framework/src/nordic_interface.h +++ b/cores/arduino/printk.cpp @@ -28,13 +28,25 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef NORDIC_INTERFACE_H -#define NORDIC_INTERFACE_H -#include "infra/ipc_uart.h" +#include +#include +#include "UARTClass.h" -void uart_ipc_message_cback(uint8_t cpu_id, int channel, int len, void * p_data); -int send_message_ipc_uart(struct message * message); -void free_message_ipc_uart(struct message * message); -int nordic_interface_init(T_QUEUE queue); +extern "C" void printk(const char *fmt, va_list args); +extern UARTClass Serial1; +#define PRINTK_BUFSIZ 256 + +void printk(const char *fmt, va_list args) +{ +#ifdef CONFIGURE_DEBUG_CORELIB_ENABLED + int len = 0; + + char tmp[PRINTK_BUFSIZ]; + + len = vsnprintf(tmp, PRINTK_BUFSIZ, fmt, args); + + tmp[len] = '\0'; + Serial1.println(tmp); +#endif +} -#endif // NORDIC_INTERFACE_H diff --git a/libraries/CurieBLE/examples/BatteryAdvChange/BatteryAdvChange.ino b/libraries/CurieBLE/examples/BatteryAdvChange/BatteryAdvChange.ino new file mode 100644 index 00000000..fee71356 --- /dev/null +++ b/libraries/CurieBLE/examples/BatteryAdvChange/BatteryAdvChange.ino @@ -0,0 +1,108 @@ +/* Please see code cpyright at the bottom of this example code */ +/* + This sketch illustrates how to change the advertising data so that it is visible but not + connectable. Then after 10 seconds it changes to being connectable + This sketch example partially implements the standard Bluetooth Low-Energy Battery service. +*/ + +#include + +BLEPeripheral blePeripheral; // BLE Peripheral Device (the board you're programming) +BLEService batteryService("180F"); // BLE Battery Service +int count = 0; +// BLE Battery Level Characteristic" +BLEUnsignedCharCharacteristic batteryLevelChar("2A19", // standard 16-bit characteristic UUID + BLERead | BLENotify); // remote clients will be able to +// get notifications if this characteristic changes + +void setup() { + Serial.begin(9600); // initialize serial communication + pinMode(13, OUTPUT); // initialize the LED on pin 13 to indicate when a central is connected + while (!Serial) { + //wait for Serial to connect + } + /* Set a local name for the BLE device + This name will appear in advertising packets + and can be used by remote devices to identify this BLE device + The name can be changed but maybe be truncated based on space left in advertisement packet */ + blePeripheral.setLocalName("BatteryAdvChangeSketch"); + blePeripheral.setAdvertisedServiceUuid(batteryService.uuid()); // add the service UUID + blePeripheral.addAttribute(batteryService); // Add the BLE Battery service + blePeripheral.addAttribute(batteryLevelChar); // add the battery level characteristic + + /* Now activate the BLE device. It will start continuously transmitting BLE + advertising packets and will be visible to remote BLE central devices + until it receives a new connection */ + + blePeripheral.begin(); + Serial.println("Bluetooth device active, waiting for connections..."); + Serial.println("Starts in Connectable mode"); +} + +void loop() { + // listen for BLE peripherals to connect: + BLECentralHelper central = blePeripheral.central(); + // wait + Serial.print(". "); + if (count == 10) { + Serial.print("\nReached count "); + Serial.println(count); + + } + delay (1000); + count++; + // Switch from Connectable to Non Connectable and vice versa + if (count > 10 ) { + static bool change_discover = false; + Serial.println("Stop Adv and pausing for 10 seconds. Device should be invisible"); + // Some central devices (phones included) may cache previous scan inofrmation + // restart your central and it should not see this peripheral once stopAdvertising() is called + blePeripheral.stopAdvertising(); + delay(10000); + + if (change_discover) + { + + // Using the function setAdvertisingParam we specify that it now NOT connectable + // The loop is for 10 seconds. Your central device may timeout later than that + // and may eventually connect when we set it back to connectable mode below + blePeripheral.setConnectable(false); + Serial.println("In Non Connectable mode"); + + } + else + { + + //using the function setAdvertisingParam we specify that it now connectable + blePeripheral.setConnectable(true); + Serial.println("In Connectable mode"); + } + Serial.println("Start Adv"); + blePeripheral.startAdvertising(); + if (change_discover) { + Serial.println("Adding 5 second delay in Non Connect Mode"); + delay(5000); + } + change_discover = !change_discover; + count = 0; + } +} + +/* + Copyright (c) 2016 Intel Corporation. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + diff --git a/libraries/CurieBLE/examples/BatteryMonitor/BatteryMonitor.ino b/libraries/CurieBLE/examples/BatteryMonitor/BatteryMonitor.ino index 688b147f..0bf09ecf 100644 --- a/libraries/CurieBLE/examples/BatteryMonitor/BatteryMonitor.ino +++ b/libraries/CurieBLE/examples/BatteryMonitor/BatteryMonitor.ino @@ -45,7 +45,7 @@ void setup() { void loop() { // listen for BLE peripherals to connect: - BLECentral central = blePeripheral.central(); + BLECentralHelper central = blePeripheral.central(); // if a central is connected to peripheral: if (central) { @@ -63,6 +63,14 @@ void loop() { if (currentMillis - previousMillis >= 200) { previousMillis = currentMillis; updateBatteryLevel(); + + static unsigned short count = 0; + count++; + // update the connection interval + if(count%5 == 0){ + delay(1000); + updateIntervalParams(central); + } } } // when the central disconnects, turn off the LED: @@ -87,6 +95,31 @@ void updateBatteryLevel() { } } +void updateIntervalParams(BLECentralHelper ¢ral) { + // read and update the connection interval that peer central device + static unsigned short interval = 0x60; + ble_conn_param_t m_conn_param; + // Get connection interval that peer central device wanted + central.getConnParams(m_conn_param); + Serial.print("min interval = " ); + Serial.println(m_conn_param.interval_min ); + Serial.print("max interval = " ); + Serial.println(m_conn_param.interval_max ); + Serial.print("latency = " ); + Serial.println(m_conn_param.latency ); + Serial.print("timeout = " ); + Serial.println(m_conn_param.timeout ); + + //Update connection interval + Serial.println("set Connection Interval"); + central.setConnectionInterval(interval,interval); + + interval++; + if(interval<0x06) + interval = 0x06; + if(interval>0x100) + interval = 0x06; +} /* Copyright (c) 2016 Intel Corporation. All rights reserved. diff --git a/libraries/CurieBLE/examples/CallbackLED/CallbackLED.ino b/libraries/CurieBLE/examples/CallbackLED/CallbackLED.ino index f8788731..26946cbf 100644 --- a/libraries/CurieBLE/examples/CallbackLED/CallbackLED.ino +++ b/libraries/CurieBLE/examples/CallbackLED/CallbackLED.ino @@ -45,19 +45,19 @@ void loop() { blePeripheral.poll(); } -void blePeripheralConnectHandler(BLECentral& central) { +void blePeripheralConnectHandler(BLEHelper& central) { // central connected event handler Serial.print("Connected event, central: "); Serial.println(central.address()); } -void blePeripheralDisconnectHandler(BLECentral& central) { +void blePeripheralDisconnectHandler(BLEHelper& central) { // central disconnected event handler Serial.print("Disconnected event, central: "); Serial.println(central.address()); } -void switchCharacteristicWritten(BLECentral& central, BLECharacteristic& characteristic) { +void switchCharacteristicWritten(BLEHelper& central, BLECharacteristic& characteristic) { // central wrote new value to characteristic, update LED Serial.print("Characteristic event, written: "); diff --git a/libraries/CurieBLE/examples/IMUBleCentral/IMUBleCentral.ino b/libraries/CurieBLE/examples/IMUBleCentral/IMUBleCentral.ino new file mode 100644 index 00000000..0523ed55 --- /dev/null +++ b/libraries/CurieBLE/examples/IMUBleCentral/IMUBleCentral.ino @@ -0,0 +1,143 @@ +/* + Copyright (c) 2016 Intel Corporation. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +/* + This sketch example partially implements the standard Bluetooth Low-Energy Battery service. + For more information: https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx +*/ + +#define MAX_IMU_RECORD 1 + +struct bt_le_conn_param conn_param = {0x18, 0x28, 0, 400}; +typedef struct { + int index; + unsigned int slot[3]; +} imuFrameType; + +imuFrameType imuBuf[MAX_IMU_RECORD]; +BLECentral bleCentral; // BLE Central Device (the board you're programming) + +BLEService bleImuService("F7580001-153E-D4F6-F26D-43D8D98EEB13"); +BLECharacteristic bleImuChar("F7580003-153E-D4F6-F26D-43D8D98EEB13", // standard 128-bit characteristic UUID + BLERead | BLENotify, sizeof(imuBuf)); // remote clients will be able to + // get notifications if this characteristic changes + +void ble_connected(BLEHelper &role) +{ + BLEPeripheralHelper&peripheral = *(BLEPeripheralHelper*)(&role); + Serial.println("Connected"); + + // Start discovery the profiles in peripheral device + peripheral.discover(); +} + +void bleImuCharacteristicWritten(BLEHelper& central, BLECharacteristic& characteristic) +{ + // Peripheral wrote new value to characteristic by Notification/Indication + const unsigned char *cvalue = characteristic.value(); + const imuFrameType *value = (const imuFrameType *)cvalue; + Serial.print("\r\nCharacteristic event, written: "); + Serial.print(value->index); + Serial.print("\t"); + Serial.print(value->slot[0]); + Serial.print("\t"); + Serial.print(value->slot[1]); + Serial.print("\t"); + Serial.println(value->slot[2]); +} + +bool adv_found(uint8_t type, + const uint8_t *data, + uint8_t data_len, + void *user_data) +{ + bt_addr_le_t *addr = (bt_addr_le_t *)user_data; + int i; + + Serial.print("[AD]:"); + Serial.print(type); + Serial.print(" data_len "); + Serial.println(data_len); + + switch (type) + { + case BT_DATA_UUID128_SOME: + case BT_DATA_UUID128_ALL: + { + if (data_len % MAX_UUID_SIZE != 0) + { + Serial.println("AD malformed"); + return true; + } + struct bt_uuid * serviceuuid = bleImuService.uuid(); + for (i = 0; i < data_len; i += MAX_UUID_SIZE) + { + if (memcmp (((struct bt_uuid_128*)serviceuuid)->val, &data[i], MAX_UUID_SIZE) != 0) + { + continue; + } + + // Accept the advertisement + if (!bleCentral.stopScan()) + { + Serial.println("Stop LE scan failed"); + continue; + } + Serial.println("Connecting"); + // Connect to peripheral + bleCentral.connect(addr, &conn_param); + return false; + } + } + } + + return true; +} + +void setup() { + Serial.begin(115200); // initialize serial communication + pinMode(13, OUTPUT); // initialize the LED on pin 13 to indicate when a central is connected + + bleImuChar.setEventHandler(BLEWritten, bleImuCharacteristicWritten); + + /* Set a local name for the BLE device + This name will appear in advertising packets + and can be used by remote devices to identify this BLE device + The name can be changed but maybe be truncated based on space + left in advertisement packet */ + bleCentral.addAttribute(bleImuService); // Add the BLE IMU service + bleCentral.addAttribute(bleImuChar); // Add the BLE IMU characteristic + + /* Setup callback */ + bleCentral.setAdvertiseHandler(adv_found); + bleCentral.setEventHandler(BLEConnected, ble_connected); + + /* Now activate the BLE device. It will start continuously transmitting BLE + advertising packets and will be visible to remote BLE central devices + until it receives a new connection */ + bleCentral.begin(); +} + + +void loop() +{ + delay(2000); +} + diff --git a/libraries/CurieBLE/examples/IMUBleNotification/IMUBleNotification.ino b/libraries/CurieBLE/examples/IMUBleNotification/IMUBleNotification.ino new file mode 100644 index 00000000..4a179e2a --- /dev/null +++ b/libraries/CurieBLE/examples/IMUBleNotification/IMUBleNotification.ino @@ -0,0 +1,120 @@ +/* + Copyright (c) 2016 Intel Corporation. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include + +/* + This sketch example partially implements the standard Bluetooth Low-Energy Battery service. + For more information: https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx +*/ + +#define MAX_IMU_RECORD 1 + +typedef struct { + int index; + unsigned int slot[3]; +} imuFrameType; + +imuFrameType imuBuf[MAX_IMU_RECORD]; + +unsigned seqNum = 0; + +BLEPeripheral blePeripheral; // BLE Peripheral Device (the board you're programming) +BLEService bleImuService("F7580001-153E-D4F6-F26D-43D8D98EEB13"); // Tx IMU data Characteristic +BLECharacteristic bleImuChar("F7580003-153E-D4F6-F26D-43D8D98EEB13", // standard 128-bit characteristic UUID + BLERead | BLENotify, sizeof(imuBuf)); // remote clients will be able to + // get notifications if this characteristic changes +void setup() { + + Serial.begin(9600); // initialize serial communication + pinMode(13, OUTPUT); // initialize the LED on pin 13 to indicate when a central is connected + + + /* Set a local name for the BLE device + This name will appear in advertising packets + and can be used by remote devices to identify this BLE device + The name can be changed but maybe be truncated based on space left in advertisement packet */ + blePeripheral.setLocalName("Imu"); + blePeripheral.setAdvertisedServiceUuid(bleImuService.uuid()); // add the service UUID + blePeripheral.addAttribute(bleImuService); // Add the BLE Battery service + blePeripheral.addAttribute(bleImuChar); // add the battery level characteristic + + /* Now activate the BLE device. It will start continuously transmitting BLE + advertising packets and will be visible to remote BLE central devices + until it receives a new connection */ + blePeripheral.begin(); + + CurieIMU.begin(); +} + +void recordImuData(int index) { + /* Read IMU data. + */ + int ax, ay, az; + int gx, gy, gz; + + imuBuf[index].index = seqNum++; + CurieIMU.readMotionSensor(ax, ay, az, gx, gy, gz); + + imuBuf[index].slot[0] = (unsigned int)((ax << 16) | (ay & 0x0FFFF)); + imuBuf[index].slot[1] = (unsigned int)((az << 16) | (gx & 0x0FFFF)); + imuBuf[index].slot[2] = (unsigned int)((gy << 16) | (gz & 0x0FFFF)); + +} + + +void loop() { + // listen for BLE peripherals to connect: + BLECentralHelper central = blePeripheral.central(); + + // if a central is connected to peripheral: + if (central) + { + Serial.print("Connected to central: "); + // print the central's MAC address: + Serial.println(central.address()); + + Serial.print("IMU buffer size: "); + Serial.println(sizeof(imuBuf)); + + // turn on the LED to indicate the connection: + digitalWrite(13, HIGH); + + long currentMillis, sentTime; + + // Send IMU data as long as the central is still connected + currentMillis = sentTime = millis(); + while (central.connected()) + { + // Take IMU data every 100 msec + if ((millis() - sentTime) >= 100) + { + recordImuData(0); + sentTime = millis(); + bleImuChar.setValue((unsigned char *)&(imuBuf[0]), sizeof(imuBuf)); + } + } // while + + // when the central disconnects, turn off the LED: + digitalWrite(13, LOW); + Serial.print("Disconnected from central: "); + Serial.println(central.address()); + } +} + diff --git a/libraries/CurieBLE/examples/LED/LED.ino b/libraries/CurieBLE/examples/LED/LED.ino index a55501dc..263c7d5b 100644 --- a/libraries/CurieBLE/examples/LED/LED.ino +++ b/libraries/CurieBLE/examples/LED/LED.ino @@ -38,7 +38,7 @@ void setup() { void loop() { // listen for BLE peripherals to connect: - BLECentral central = blePeripheral.central(); + BLECentralHelper central = blePeripheral.central(); // if a central is connected to peripheral: if (central) { diff --git a/libraries/CurieBLE/examples/LEDCentral/LEDCentral.ino b/libraries/CurieBLE/examples/LEDCentral/LEDCentral.ino new file mode 100644 index 00000000..04cd0971 --- /dev/null +++ b/libraries/CurieBLE/examples/LEDCentral/LEDCentral.ino @@ -0,0 +1,157 @@ +/* + Copyright (c) 2016 Intel Corporation. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110- + 1301 USA +*/ + +// This example can work with CallbackLED to show the profile read/write operation in central +#include + +struct bt_le_conn_param conn_param = {0x18, 0x28, 0, 400}; + +const int ledPin = 13; // set ledPin to use on-board LED +BLECentral bleCentral; // create central instance +BLEPeripheralHelper *blePeripheral1 = NULL; + +BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // create service +BLECharCharacteristic switchChar("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);// create switch characteristic and allow remote device to read and write + +void bleCentralConnectHandler(BLEHelper& peripheral) +{ + // peripheral connected event handler + blePeripheral1 = (BLEPeripheralHelper *)(&peripheral); + Serial.print("Connected event, peripheral: "); + Serial.println(peripheral.address()); + // Start discovery the profiles in peripheral device + blePeripheral1->discover(); +} + +void bleCentralDisconnectHandler(BLEHelper& peripheral) +{ + // peripheral disconnected event handler + blePeripheral1 = NULL; + Serial.print("Disconnected event, peripheral: "); + Serial.println(peripheral.address()); + bleCentral.startScan(); +} + +void switchCharacteristicWritten(BLEHelper& peripheral, BLECharacteristic& characteristic) +{ + // Read response/Notification wrote new value to characteristic, update LED + Serial.print("Characteristic event, written: "); + + if (switchChar.value()) + { + Serial.println("LED on"); + digitalWrite(ledPin, HIGH); + } + else + { + Serial.println("LED off"); + digitalWrite(ledPin, LOW); + } +} + +bool adv_found(uint8_t type, + const uint8_t *data, + uint8_t data_len, + void *user_data) +{ + bt_addr_le_t *addr = (bt_addr_le_t *)user_data; + int i; + + Serial.print("[AD]:"); + Serial.print(type); + Serial.print(" data_len "); + Serial.println(data_len); + + switch (type) + { + case BT_DATA_UUID128_SOME: + case BT_DATA_UUID128_ALL: + { + if (data_len % MAX_UUID_SIZE != 0) + { + Serial.println("AD malformed"); + return true; + } + struct bt_uuid * serviceuuid = ledService.uuid(); + for (i = 0; i < data_len; i += MAX_UUID_SIZE) + { + if (memcmp (((struct bt_uuid_128*)serviceuuid)->val, &data[i], MAX_UUID_SIZE) != 0) + { + continue; + } + + // Accept the advertisement + if (!bleCentral.stopScan()) + { + Serial.println("Stop LE scan failed"); + continue; + } + Serial.println("Connecting"); + // Connect to peripheral + bleCentral.connect(addr, &conn_param); + return false; + } + } + } + + return true; +} + +void setup() { + Serial.begin(9600); + pinMode(ledPin, OUTPUT); // use the LED on pin 13 as an output + + // add service and characteristic + bleCentral.addAttribute(ledService); + bleCentral.addAttribute(switchChar); + + // assign event handlers for connected, disconnected to central + bleCentral.setEventHandler(BLEConnected, bleCentralConnectHandler); + bleCentral.setEventHandler(BLEDisconnected, bleCentralDisconnectHandler); + + // advertise the service + bleCentral.setAdvertiseHandler(adv_found); + + // assign event handlers for characteristic + switchChar.setEventHandler(BLEWritten, switchCharacteristicWritten); + + bleCentral.begin(); + Serial.println(("Bluetooth device active, waiting for connections...")); +} + +void loop() +{ + static unsigned int counter = 0; + static char ledstate = 0; + delay(2000); + if (blePeripheral1) + { + counter++; + + if (counter % 3) + { + switchChar.read(*blePeripheral1); + } + else + { + ledstate = !ledstate; + switchChar.write(*blePeripheral1, (unsigned char *)(&ledstate), sizeof (ledstate)); + } + } +} diff --git a/libraries/CurieBLE/examples/MIDIBLE/MIDIBLE.ino b/libraries/CurieBLE/examples/MIDIBLE/MIDIBLE.ino index 2dbe9833..4892f017 100644 --- a/libraries/CurieBLE/examples/MIDIBLE/MIDIBLE.ino +++ b/libraries/CurieBLE/examples/MIDIBLE/MIDIBLE.ino @@ -140,19 +140,19 @@ void loop() { } -void midiDeviceConnectHandler(BLECentral& central) { +void midiDeviceConnectHandler(BLEHelper& central) { // central connected event handler Serial.print("Connected event, central: "); Serial.println(central.address()); } -void midiDeviceDisconnectHandler(BLECentral& central) { +void midiDeviceDisconnectHandler(BLEHelper& central) { // central disconnected event handler Serial.print("Disconnected event, central: "); Serial.println(central.address()); } -void midiCharacteristicWritten(BLECentral& central, BLECharacteristic& characteristic) { +void midiCharacteristicWritten(BLEHelper& central, BLECharacteristic& characteristic) { // central wrote new value to characteristic, update LED Serial.print("Characteristic event, written: "); } diff --git a/libraries/CurieBLE/examples/Scanning/Scanning.ino b/libraries/CurieBLE/examples/Scanning/Scanning.ino new file mode 100644 index 00000000..d2d7d0e2 --- /dev/null +++ b/libraries/CurieBLE/examples/Scanning/Scanning.ino @@ -0,0 +1,129 @@ +/* + Copyright (c) 2016 Intel Corporation. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include + +#define BLE_SCANING_DEVICE_MAX_CNT 5 + +typedef struct{ + char macaddr[32]; // BLE MAC address. + char loacalname[22]; // Device's name +}ble_device_info_t; + +ble_device_info_t device_list[BLE_SCANING_DEVICE_MAX_CNT]; +uint8_t list_index = 0; + +BLECentral bleCentral; // BLE Central Device (the board you're programming) + +bool adv_list_add(ble_device_info_t &device) +{ + if (list_index >= BLE_SCANING_DEVICE_MAX_CNT) + { + return false; + } + for (int i = 0; i < list_index; i++) + { + if (0 == memcmp(device.macaddr, device_list[i].macaddr, sizeof (device.macaddr))) + { + // Found and update the item + return false; + } + } + // Add the device + memcpy(&device_list[list_index], &device, sizeof (ble_device_info_t)); + list_index++; + return true; +} + + +bool adv_list_update(ble_device_info_t &device) +{ + for (int i = 0; i < list_index; i++) + { + if (0 == memcmp(device.macaddr, device_list[i].macaddr, sizeof (device.macaddr))) + { + // Found and update the item + memcpy(device_list[i].loacalname, device.loacalname, sizeof(device.loacalname)); + return true; + } + } + return false; +} + +void adv_list_clear() +{ + list_index = 0; + memset(device_list, 0x00, sizeof(device_list)); +} + +// Process the Advertisement data +bool adv_found(uint8_t type, + const uint8_t *data, + uint8_t data_len, + void *user_data) +{ + bt_addr_le_t *addr = (bt_addr_le_t *)user_data; + ble_device_info_t device; + bt_addr_le_to_str (addr, device.macaddr, sizeof (device.macaddr)); + memcpy(device.loacalname, " -NA-", sizeof(" -NA-")); + + switch (type) { + case BT_DATA_NAME_SHORTENED: + case BT_DATA_NAME_COMPLETE: + memcpy(device.loacalname, data, data_len); + device.loacalname[data_len] = '\0'; + adv_list_update(device); + break; + } + adv_list_add(device); + return true; +} + +void setup() { + Serial.begin(115200); // initialize serial communication + + /* Setup callback */ + bleCentral.setAdvertiseHandler(adv_found); + + /* Now activate the BLE device. + It will start continuously scanning BLE advertising + */ + bleCentral.begin(); + Serial.println("Bluetooth device active, start scanning..."); +} + +void loop() { + // Output the scanned device per 3s + delay(3000); + Serial.print("\r\n\r\n\t\t\tScaning result\r\n \tMAC\t\t\t\tLocal Name\r\n"); + Serial.print("-------------------------------------------------------------\r\n"); + + for (int i = 0; i < list_index; i++) + { + + Serial.print(device_list[i].macaddr); + Serial.print(" | "); + Serial.println(device_list[i].loacalname); + } + if (list_index == 0) + { + Serial.print("No device found\r\n"); + } + Serial.print("-------------------------------------------------------------\r\n"); + adv_list_clear(); +} + diff --git a/libraries/CurieBLE/examples/UpdateConnectionInterval/UpdateConnectionInterval.ino b/libraries/CurieBLE/examples/UpdateConnectionInterval/UpdateConnectionInterval.ino new file mode 100644 index 00000000..9347914e --- /dev/null +++ b/libraries/CurieBLE/examples/UpdateConnectionInterval/UpdateConnectionInterval.ino @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * See the bottom of this file for the license terms. + */ + +#include + +/* + This example can work with BatteryMonitor + to show how to control and response the connection intelval request. +*/ + +// set up connection params + +ble_conn_param_t conn_param = {30.0, // minimum interval in ms 7.5 - 4000 + 50.0, // maximum interval in ms 7.5 - + 0, // latency + 4000 // timeout in ms 100 - 32000ms + }; + +const int ledPin = 13; // set ledPin to use on-board LED +BLECentral bleCentral; // create central instance +BLEPeripheralHelper *blePeripheral1 = NULL; + +BLEService batteryService("180F"); // create service with a 16-bit UUID +BLECharCharacteristic batteryLevelChar("2A19", BLERead | BLENotify);// create switch characteristic +//and allow remote device to read and notify + +bool adv_found(uint8_t type, + const uint8_t *data, + uint8_t data_len, + void *user_data); + +void setup() +{ + Serial.begin(9600); + + // add service and characteristic + bleCentral.addAttribute(batteryService); + bleCentral.addAttribute(batteryLevelChar); + + // assign event handlers for connected, disconnected to central + bleCentral.setEventHandler(BLEConnected, bleCentralConnectHandler); + bleCentral.setEventHandler(BLEDisconnected, bleCentralDisconnectHandler); + bleCentral.setEventHandler(BLEUpdateParam, bleCentralUpdateParam); + + // advertise the service + bleCentral.setAdvertiseHandler(adv_found); + + // assign event handlers for characteristic + batteryLevelChar.setEventHandler(BLEWritten, switchCharacteristicWritten); + + bleCentral.begin(); + Serial.println(("Bluetooth device active, waiting for connections...")); +} + +void loop() +{ + static unsigned int counter = 0; + static char ledstate = 0; + delay(2000); + if (blePeripheral1) + { + counter++; + + if (counter % 3) + { + batteryLevelChar.read(*blePeripheral1); + } + else + { + ledstate = !ledstate; + batteryLevelChar.write(*blePeripheral1, (unsigned char *)(&ledstate), sizeof (ledstate)); + } + } + +} + +void bleCentralConnectHandler(BLEHelper& peripheral) +{ + // peripheral connected event handler + blePeripheral1 = (BLEPeripheralHelper *)(&peripheral); + Serial.print("Connected event, peripheral: "); + Serial.println(peripheral.address()); + // Start discovery the profiles in peripheral device + blePeripheral1->discover(); +} + +void bleCentralDisconnectHandler(BLEHelper& peripheral) +{ + // peripheral disconnected event handler + blePeripheral1 = NULL; + Serial.print("Disconnected event, peripheral: "); + Serial.println(peripheral.address()); + bleCentral.startScan(); +} + +void bleCentralUpdateParam(BLEHelper& peripheral) +{ + // peripheral update the connection interval event handler + Serial.print("UpdateParam event, peripheral: "); + blePeripheral1 = (BLEPeripheralHelper *)(&peripheral); + Serial.println(peripheral.address()); + + // Get connection interval that peer peripheral device wanted + ble_conn_param_t m_conn_param; + blePeripheral1->getConnParams(m_conn_param); + Serial.print("min interval = " ); + Serial.println(m_conn_param.interval_min ); + Serial.print("max interval = " ); + Serial.println(m_conn_param.interval_max ); + Serial.print("latency = " ); + Serial.println(m_conn_param.latency ); + Serial.print("timeout = " ); + Serial.println(m_conn_param.timeout ); + + //Update the connection interval + blePeripheral1->setConnectionInterval(m_conn_param.interval_min,m_conn_param.interval_max); +} + +void switchCharacteristicWritten(BLEHelper& peripheral, BLECharacteristic& characteristic) +{ + // Read response/Notification wrote new value to characteristic, update LED + Serial.print("Characteristic event, notify: "); + + int battery = batteryLevelChar.value(); + if (battery) + { + Serial.print("Battery Level % is now: "); // print it + Serial.println(battery); + delay(100); + + Serial.println("LED on"); + digitalWrite(ledPin, HIGH); + } + else + { + Serial.println("LED off"); + digitalWrite(ledPin, LOW); + } +} + +bool adv_found(uint8_t type, + const uint8_t *data, + uint8_t data_len, + void *user_data) +{ + bt_addr_le_t *addr = (bt_addr_le_t *)user_data; + int i; + + Serial.print("[AD]:"); + Serial.print(type); + Serial.print(" data_len "); + Serial.println(data_len); + + switch (type) + { + case BT_DATA_UUID16_SOME: + case BT_DATA_UUID16_ALL: + { + if (data_len % MAX_UUID_SIZE_16 != 0) + { + Serial.println("AD malformed"); + return true; + } + struct bt_uuid * serviceuuid = batteryService.uuid(); + for (i = 0; i < data_len; i += MAX_UUID_SIZE_16) + { + if (memcmp (&((bt_uuid_16_t*)serviceuuid)->val, &data[i], MAX_UUID_SIZE_16) != 0) + { + continue; + } + + // Accept the advertisement + if (!bleCentral.stopScan()) + { + Serial.println("Stop LE scan failed"); + continue; + } + Serial.println("Connecting"); + // Connect to peripheral + bleCentral.connect(addr, &conn_param); + return false; + } + } + } + + return true; +} + +/* + Copyright (c) 2016 Intel Corporation. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ diff --git a/libraries/CurieBLE/src/BLEAttribute.cpp b/libraries/CurieBLE/src/BLEAttribute.cpp index d6f46591..478c2e00 100644 --- a/libraries/CurieBLE/src/BLEAttribute.cpp +++ b/libraries/CurieBLE/src/BLEAttribute.cpp @@ -19,23 +19,60 @@ #include "BLEAttribute.h" -#include "BLEUuid.h" - unsigned char BLEAttribute::_numAttributes = 0; BLEAttribute::BLEAttribute(const char* uuid, enum BLEAttributeType type) : - _uuid(uuid), + _uuid_cstr(uuid), _type(type), _handle(0) { + char temp[] = {0, 0, 0}; + int strLength = strlen(uuid); + int length = 0; + _numAttributes++; + + memset (&_uuid, 0x00, sizeof(_uuid)); + + for (int i = strLength - 1; i >= 0 && length < MAX_UUID_SIZE; i -= 2) + { + if (uuid[i] == '-') + { + i++; + continue; + } + + temp[0] = uuid[i - 1]; + temp[1] = uuid[i]; + + _uuid.val[length] = strtoul(temp, NULL, 16); + + length++; + } + + if (length == 2) + { + uint16_t temp = (_uuid.val[1] << 8)| _uuid.val[0]; + _uuid.uuid.type = BT_UUID_TYPE_16; + ((struct bt_uuid_16*)(&_uuid.uuid))->val = temp; + } + else + { + _uuid.uuid.type = BT_UUID_TYPE_128; + } } const char* BLEAttribute::uuid() const { - return _uuid; + return _uuid_cstr; +} + +struct bt_uuid *BLEAttribute::uuid(void) +{ + return (struct bt_uuid *)&_uuid; } + enum BLEAttributeType BLEAttribute::type() const { return this->_type; @@ -52,14 +89,14 @@ BLEAttribute::setHandle(uint16_t handle) { } -bt_uuid -BLEAttribute::btUuid() const { - BLEUuid bleUuid = BLEUuid(uuid()); - - return bleUuid.uuid(); -} - unsigned char BLEAttribute::numAttributes() { return _numAttributes; } + +bool BLEAttribute::discovering() +{ + return _discoverying; +} + + diff --git a/libraries/CurieBLE/src/BLEAttribute.h b/libraries/CurieBLE/src/BLEAttribute.h index 8aaca067..71a19fca 100644 --- a/libraries/CurieBLE/src/BLEAttribute.h +++ b/libraries/CurieBLE/src/BLEAttribute.h @@ -28,7 +28,10 @@ enum BLEAttributeType { BLETypeDescriptor = 0x2900 }; +// Class declare +class BLEProfile; class BLEPeripheral; +class BLEPeripheralHelper; class BLEAttribute { public: @@ -39,9 +42,20 @@ class BLEAttribute { * @return const char* string representation of the Attribute */ const char* uuid(void) const; + struct bt_uuid *uuid(void); protected: - friend BLEPeripheral; + //friend BLEPeripheral; + friend BLEProfile; + + friend ssize_t profile_write_process(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + const void *buf, uint16_t len, + uint16_t offset); + friend ssize_t profile_read_process(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + void *buf, uint16_t len, + uint16_t offset); BLEAttribute(const char* uuid, enum BLEAttributeType type); @@ -51,13 +65,32 @@ class BLEAttribute { void setHandle(uint16_t handle); static unsigned char numAttributes(void); - + // The below APIs are for central device to discover the + virtual void discover(struct bt_gatt_discover_params *params) = 0; + virtual void discover(const struct bt_gatt_attr *attr, + struct bt_gatt_discover_params *params) = 0; + /** + * @brief Get attribute's discover state + * + * @param none + * + * @return bool true - In discovering state + * false- Not discovering + * + * @note none + */ + bool discovering(); + + bool _discoverying; private: static unsigned char _numAttributes; - const char* _uuid; + const char* _uuid_cstr; + struct bt_uuid_128 _uuid; + enum BLEAttributeType _type; uint16_t _handle; + }; #endif // _BLE_ATTRIBUTE_H_INCLUDED diff --git a/libraries/CurieBLE/src/BLECentral.cpp b/libraries/CurieBLE/src/BLECentral.cpp index 73d0326d..6b4afcf5 100644 --- a/libraries/CurieBLE/src/BLECentral.cpp +++ b/libraries/CurieBLE/src/BLECentral.cpp @@ -17,87 +17,84 @@ * */ -#include "BLECentral.h" - -#include "BLEPeripheral.h" +#include "BLECentralRole.h" +#include "BLECentral.h" -BLECentral::BLECentral(BLEPeripheral* peripheral) : - _peripheral(peripheral) +bool BLECentral::startScan() { - clearAddress(); + return BLECentralRole::instance()->startScan(); } -BLECentral::operator bool() const { - ble_addr_t zero; - - memset(&zero, 0, sizeof(zero)); - - return (memcmp(&_address, &zero, sizeof(_address)) != 0); +bool BLECentral::startScan(const struct bt_le_scan_param &scan_param) +{ + return BLECentralRole::instance()->startScan(scan_param); } -bool -BLECentral::operator==(const BLECentral& rhs) const { - return (memcmp(&_address, &rhs._address, sizeof(_address)) == 0); +bool BLECentral::stopScan() +{ + return BLECentralRole::instance()->stopScan(); } -bool -BLECentral::operator!=(const BLECentral& rhs) const { - return !(*this == rhs); +bool BLECentral::connect(const bt_addr_le_t *addr, const struct bt_le_conn_param *param) +{ + return BLECentralRole::instance()->connect(addr, param); } -bool -BLECentral::connected() { - poll(); - - return (*this && *this == _peripheral->central()); +void BLECentral::discover(BLEPeripheralHelper &peripheral) +{ + peripheral.discover(); } -const char* -BLECentral::address() const { - static char address[18]; - - String addressStr = ""; - - for (int i = 5; i >= 0; i--) { - unsigned char a = _address.addr[i]; - - if (a < 0x10) { - addressStr += "0"; - } - - addressStr += String(a, 16); - - if (i > 0) { - addressStr += ":"; - } - } +void BLECentral::setEventHandler(BLERoleEvent event, BLERoleEventHandler callback) +{ + BLECentralRole::instance()->setEventHandler(event, callback); +} - strcpy(address, addressStr.c_str()); +void BLECentral::setAdvertiseHandler(ble_advertise_handle_cb_t advcb) +{ + BLECentralRole::instance()->setAdvertiseHandler(advcb); +} - return address; +void BLECentral::setScanParam(const struct bt_le_scan_param &scan_param) +{ + BLECentralRole::instance()->setScanParam(scan_param); } -void -BLECentral::poll() { - _peripheral->poll(); +void BLECentral::addAttribute(BLEAttribute& attribute) +{ + BLECentralRole::instance()->addAttribute(attribute); } -bool -BLECentral::disconnect() { - if (connected()) { - return _peripheral->disconnect(); +bool BLECentral::begin(void) +{ + bool retval = BLECentralRole::instance()->begin(); + if (!retval) + { + pr_error(LOG_MODULE_BLE,"%s: Intit failed", __FUNCTION__); + return false; } - - return false; + + // Start scan + const struct bt_le_scan_param *scan_param = BLECentralRole::instance()->getScanParam(); + struct bt_le_scan_param zero_param; + memset(&zero_param, 0x00, sizeof (zero_param)); + if (0 == memcmp(&zero_param, scan_param, sizeof (zero_param))) + { + // Not set the scan parameter. + // Use the default scan parameter to scan + zero_param.type = BT_HCI_LE_SCAN_ACTIVE; + zero_param.filter_dup = BT_HCI_LE_SCAN_FILTER_DUP_ENABLE; + zero_param.interval = BT_GAP_SCAN_FAST_INTERVAL;//BT_GAP_SCAN_SLOW_INTERVAL_1;// + zero_param.window = BT_GAP_SCAN_FAST_WINDOW; //BT_GAP_SCAN_SLOW_WINDOW_1;// + retval = BLECentralRole::instance()->startScan(zero_param); + } + else + { + retval = BLECentralRole::instance()->startScan(); + } + return retval; } -void -BLECentral::setAddress(ble_addr_t address) { - _address = address; -} -void -BLECentral::clearAddress() { - memset(&_address, 0x00, sizeof(_address)); -} + diff --git a/libraries/CurieBLE/src/BLECentral.h b/libraries/CurieBLE/src/BLECentral.h index c51250d9..8327f5d6 100644 --- a/libraries/CurieBLE/src/BLECentral.h +++ b/libraries/CurieBLE/src/BLECentral.h @@ -21,50 +21,119 @@ #define _BLE_CENTRAL_H_INCLUDED #include "BLECommon.h" +#include "BLERoleBase.h" -class BLEPeripheral; +class BLEAttribute; -class BLECentral { - friend class BLEPeripheral; - - public: - /** - * Is the Central connected - * - * @return boolean_t true if the central is connected, otherwise false - */ - bool connected(void); - - /** - * Get the address of the Central in string form - * - * @return const char* address of the Central in string form - */ - const char* address(void) const; - - /** - * Disconnect the central if it is connected - * - */ - bool disconnect(void); - - /** - * Poll the central for events - */ - void poll(void); - - operator bool(void) const; - bool operator==(const BLECentral& rhs) const; - bool operator!=(const BLECentral& rhs) const; - - protected: - BLECentral(BLEPeripheral* peripheral); - void setAddress(ble_addr_t address); - void clearAddress(); - - private: - BLEPeripheral* _peripheral; - ble_addr_t _address; +class BLECentral{ +public: + /** + * @brief Start scan + * + * @param none + * + * @return bool Indicate the success or error + * + * @note none + */ + bool startScan(); + + /** + * @brief Start scan with scan parameter + * + * @param none + * + * @return bool Indicate the success or error + * + * @note none + */ + bool startScan(const struct bt_le_scan_param &scan_param); + + /** + * @brief Stop scan + * + * @param none + * + * @return bool Indicate the success or error + * + * @note none + */ + bool stopScan(); + + /** + * @brief Schedule a connect request to peripheral to establish a connection + * + * @param addr The MAC address of peripheral device that want to establish connection + * + * @param param The connetion parameters + * + * @return bool Indicate the success or error + * + * @note none + */ + bool connect(const bt_addr_le_t *addr, const struct bt_le_conn_param *param); + + /** + * @brief Discover the peripheral device profile + * + * @param peripheral The Peripheral that need to discover the profile + * + * @return none + * + * @note none + */ + void discover(BLEPeripheralHelper &peripheral); + + /** + * @brief Set the scan parameter + * + * @param scan_param The scan parameter want to be set + * + * @return none + * + * @note none + */ + void setScanParam(const struct bt_le_scan_param &scan_param); + + /** + * @brief Add an attribute to the BLE Central Device + * + * @param attribute Attribute to add to Central + * + * @return none + * + * @note The attribute will used for discover the peripheral handler + */ + void addAttribute(BLEAttribute& attribute); + + /** + * Provide a function to be called when events related to this Device are raised + * + * @param event Event type for callback + * @param callback Pointer to callback function to invoke when an event occurs. + */ + void setEventHandler(BLERoleEvent event, BLERoleEventHandler callback); + + /** + * @brief Provide a function to be called when scanned the advertisement + * + * @param advcb Pointer to callback function to invoke when advertisement received + * + * @return none + * + * @note none + */ + void setAdvertiseHandler(ble_advertise_handle_cb_t advcb); + + /** + * Setup attributes and start scan + * + * @return bool indicating success or error + */ + bool begin(void); +protected: +private: + }; #endif diff --git a/libraries/CurieBLE/src/BLECentralHelper.cpp b/libraries/CurieBLE/src/BLECentralHelper.cpp new file mode 100644 index 00000000..99e92de9 --- /dev/null +++ b/libraries/CurieBLE/src/BLECentralHelper.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "BLECentralHelper.h" + +#include "BLEPeripheralRole.h" + + +BLECentralHelper::BLECentralHelper(BLEPeripheralRole* peripheral) : + _peripheral(peripheral) +{ + clearAddress(); +} + +BLECentralHelper::operator bool() const { + bt_addr_le_t zero; + + memset(&zero, 0, sizeof(zero)); + + return (memcmp(&_address, &zero, sizeof(_address)) != 0); +} + +bool +BLECentralHelper::operator==(const BLECentralHelper& rhs) const { + return (memcmp(&_address, &rhs._address, sizeof(_address)) == 0); +} + +bool +BLECentralHelper::operator!=(const BLECentralHelper& rhs) const { + return !(*this == rhs); +} + +bool +BLECentralHelper::connected() { + poll(); + + return (*this && *this == _peripheral->central()); +} + +const char* +BLECentralHelper::address() const { + static char address[18]; + + String addressStr = ""; + + for (int i = 5; i >= 0; i--) { + unsigned char a = _address.val[i]; + + if (a < 0x10) { + addressStr += "0"; + } + + addressStr += String(a, 16); + + if (i > 0) { + addressStr += ":"; + } + } + + strcpy(address, addressStr.c_str()); + + return address; +} + +void +BLECentralHelper::poll() { + _peripheral->poll(); +} + +bool +BLECentralHelper::disconnect() { + if (connected()) { + return _peripheral->disconnect(); + } + + return false; +} + +void +BLECentralHelper::setAddress(bt_addr_le_t address) { + _address = address; +} + +void +BLECentralHelper::clearAddress() { + memset(&_address, 0x00, sizeof(_address)); +} diff --git a/libraries/CurieBLE/src/BLECentralHelper.h b/libraries/CurieBLE/src/BLECentralHelper.h new file mode 100644 index 00000000..465d9cab --- /dev/null +++ b/libraries/CurieBLE/src/BLECentralHelper.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef _BLE_CENTRAL_HELPER_H_INCLUDED +#define _BLE_CENTRAL_HELPER_H_INCLUDED + +#include "BLECommon.h" +#include "BLEHelper.h" + +class BLEPeripheralRole; + +class BLECentralHelper: public BLEHelper{ + friend class BLEPeripheralRole; + friend class BLECentralRole; + + public: + /** + * Is the Central connected + * + * @return boolean_t true if the central is connected, otherwise false + */ + bool connected(void); + + /** + * Get the address of the Central in string form + * + * @return const char* address of the Central in string form + */ + const char* address(void) const; + + /** + * Disconnect the central if it is connected + * + */ + bool disconnect(void); + + /** + * Poll the central for events + */ + void poll(void); + + operator bool(void) const; + bool operator==(const BLECentralHelper& rhs) const; + bool operator!=(const BLECentralHelper& rhs) const; + + protected: + BLECentralHelper(BLEPeripheralRole* peripheral); + void setAddress(bt_addr_le_t address); + void clearAddress(); + + private: + BLEPeripheralRole* _peripheral; + bt_addr_le_t _address; +}; + +#endif diff --git a/libraries/CurieBLE/src/BLECentralRole.cpp b/libraries/CurieBLE/src/BLECentralRole.cpp new file mode 100644 index 00000000..1595e24d --- /dev/null +++ b/libraries/CurieBLE/src/BLECentralRole.cpp @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "BLECentralRole.h" + + +void ble_central_device_found(const bt_addr_le_t *addr, + int8_t rssi, + uint8_t type, + const uint8_t *ad, + 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); + + BLECentralRole::instance()->handleDeviceFound(addr, rssi, type, + ad, len); +} + + +BLECentralRole* BLECentralRole::_ble_central_ins = NULL; + +BLECentralRole *BLECentralRole::instance() +{ + if (NULL == _ble_central_ins) + { + _ble_central_ins = new BLECentralRole(); + } + return _ble_central_ins; +} + +BLECentralRole::BLECentralRole(): + _central(NULL), _adv_event_handle(NULL) +{ + memset(_peripherial, 0, sizeof (_peripherial)); + for (int i = 0; i < BLE_MAX_CONN_CFG; i++) + { + _peripherial[i] = new BLEPeripheralHelper(this); + } + memset (&_scan_param, 0x00, sizeof (_scan_param)); + _central.setAddress(_local_bda); +} + + +BLECentralRole::~BLECentralRole() +{ + for (int i = 0; i < BLE_MAX_CONN_CFG; i++) + { + delete (_peripherial[i]); + //_peripherial[i] = NULL; + } +} + +const BLECentralHelper *BLECentralRole::central(void) const +{ + return &_central; +} + +bool BLECentralRole::connect(const bt_addr_le_t *addr, const struct bt_le_conn_param *param) +{ + BLEPeripheralHelper* temp = NULL; + BLEPeripheralHelper* unused = NULL; + bool link_existed = false; + bool retval = false; + + // Find free peripheral Items + for (int i = 0; i < BLE_MAX_CONN_CFG; i++) + { + temp = _peripherial[i]; + if (true == *temp) + { + if (*temp == *addr) + { + // Connect request has scheduled but connection don't established. + // The central can see the ADV and no need to send connect request. + link_existed = true; + break; + } + } + else + { + if (NULL == unused) + { + unused = temp; + } + } + } + + if (!link_existed) + { + // Send connect request + struct bt_conn* conn = bt_conn_create_le(addr, param); + if (NULL != conn) + { + unused->setAddress(*addr); + retval = true; + bt_conn_unref(conn); + } + } + return retval; +} + +bool BLECentralRole::startScan() +{ + 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; +} + +bool BLECentralRole::startScan(const struct bt_le_scan_param &scan_param) +{ + setScanParam(scan_param); + return startScan(); +} + +void BLECentralRole::setScanParam(const struct bt_le_scan_param &scan_param) +{ + memcpy(&_scan_param, &scan_param, sizeof (_scan_param)); +} + +const struct bt_le_scan_param* BLECentralRole::getScanParam() +{ + return &_scan_param; +} + + +bool BLECentralRole::stopScan() +{ + int err = bt_le_scan_stop(); + if (err) + { + pr_info(LOG_MODULE_BLE, "Stop LE scan failed (err %d)\n", err); + return false; + } + return true; +} + +BLEPeripheralHelper* BLECentralRole::peripheral(struct bt_conn *conn) +{ + BLEPeripheralHelper* temp = NULL; + const bt_addr_le_t *addr = bt_conn_get_dst(conn); + // Find free peripheral Items + for (int i = 0; i < BLE_MAX_CONN_CFG; i++) + { + temp = _peripherial[i]; + if (*temp == *addr) + { + return temp; + } + } + return NULL; +} + + +void BLECentralRole::handleDeviceFound(const bt_addr_le_t *addr, + int8_t rssi, + uint8_t type, + const uint8_t *ad, + uint8_t data_len) +{ + const uint8_t *data = ad; + + if (_adv_event_handle == NULL) + { + return; + } + + /* We're only interested in connectable events */ + if (type == BT_LE_ADV_IND || type == BT_LE_ADV_DIRECT_IND) + { + pr_debug(LOG_MODULE_BLE, "%s", __FUNCTION__); + + while (data_len > 1) + { + uint8_t len = data[0]; + + /* Check for early termination */ + if (len == 0) { + return; + } + + if ((len + 1 > data_len) || (data_len < 2)) { + pr_info(LOG_MODULE_BLE, "AD malformed\n"); + return; + } + + if (!_adv_event_handle(data[1], &data[2], len - 1, (void *)addr)) + { + return; + } + + data_len -= len + 1; + data += len + 1; + } + pr_debug(LOG_MODULE_BLE, "%s: done", __FUNCTION__); + } +} + +void BLECentralRole::handleConnectEvent(struct bt_conn *conn, uint8_t err) +{ + if (_event_handlers[BLEConnected]) + { + BLEPeripheralHelper *temp = peripheral(conn); + _event_handlers[BLEConnected](*temp); + } +} + +void BLECentralRole::handleDisconnectEvent(struct bt_conn *conn, uint8_t reason) +{ + if (_event_handlers[BLEDisconnected]) + { + BLEPeripheralHelper *temp = peripheral(conn); + _event_handlers[BLEDisconnected](*temp); + temp->linkLost(); + } +} + +void BLECentralRole::handleParamUpdated(struct bt_conn *conn, + uint16_t interval, + uint16_t latency, + uint16_t timeout) +{ + if (_event_handlers[BLEUpdateParam]) + { + // Fix me Add parameter proc + BLEPeripheralHelper *temp = peripheral(conn); + _event_handlers[BLEUpdateParam](*temp); + } +} + +void BLECentralRole::setEventHandler(BLERoleEvent event, BLERoleEventHandler callback) +{ + + if (event < sizeof(_event_handlers)) + { + _event_handlers[event] = callback; + } +} + +void BLECentralRole::setAdvertiseHandler(ble_advertise_handle_cb_t advcb) +{ + _adv_event_handle = advcb; +} + +void BLECentralRole::addAttribute(BLEAttribute& attribute) +{ + for (int i = 0; i < BLE_MAX_CONN_CFG; i++) + { + _peripherial[i]->addAttribute(attribute); + } +} + +bool BLECentralRole::begin() +{ + BleStatus status; + status = _init(); + if (status != BLE_STATUS_SUCCESS) + { + return false; + } + return true; +} + +bool BLECentralRole::disconnect() +{ + return true; +} + + diff --git a/libraries/CurieBLE/src/BLECentralRole.h b/libraries/CurieBLE/src/BLECentralRole.h new file mode 100644 index 00000000..d3757fae --- /dev/null +++ b/libraries/CurieBLE/src/BLECentralRole.h @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef _BLE_CENTRALROLE_H_INCLUDED +#define _BLE_CENTRALROLE_H_INCLUDED +#include "BLECommon.h" +#include "BLEPeripheralHelper.h" +#include "BLECentralHelper.h" +#include "BLERoleBase.h" + +class BLECentralRole: public BLERoleBase { +public: + /** + * @brief Start scan + * + * @param none + * + * @return bool Indicate the success or error + * + * @note none + */ + bool startScan(); + + /** + * @brief Start scan with scan parameter + * + * @param none + * + * @return bool Indicate the success or error + * + * @note none + */ + bool startScan(const struct bt_le_scan_param &scan_param); + + /** + * @brief Stop scan + * + * @param none + * + * @return bool Indicate the success or error + * + * @note none + */ + bool stopScan(); + + /** + * @brief Schedule a connect request to peripheral to establish a connection + * + * @param addr The MAC address of peripheral device that want to establish connection + * + * @param param The connetion parameters + * + * @return bool Indicate the success or error + * + * @note none + */ + bool connect(const bt_addr_le_t *addr, const struct bt_le_conn_param *param); + + /** + * @brief Set the scan parameter + * + * @param scan_param The scan parameter want to be set + * + * @return none + * + * @note none + */ + void setScanParam(const struct bt_le_scan_param &scan_param); + + /** + * @brief Get the scan parameter + * + * @param none + * + * @return const struct bt_le_scan_param* The scan parameter that current used + * + * @note none + */ + const struct bt_le_scan_param* getScanParam(); + + /** + * @brief Discover the peripheral device profile + * + * @param peripheral The Peripheral that need to discover the profile + * + * @return none + * + * @note none + */ + void discover(BLEPeripheralHelper &peripheral); + + /** + * @brief Add an attribute to the BLE Central Device + * + * @param attribute Attribute to add to Central + * + * @return none + * + * @note The attribute will used for discover the peripheral handler + */ + void addAttribute(BLEAttribute& attribute); + + /** + * Provide a function to be called when events related to this Device are raised + * + * @param event Event type for callback + * @param callback Pointer to callback function to invoke when an event occurs. + */ + void setEventHandler(BLERoleEvent event, BLERoleEventHandler callback); + + /** + * @brief Provide a function to be called when scanned the advertisement + * + * @param advcb Pointer to callback function to invoke when advertisement received + * + * @return none + * + * @note none + */ + void setAdvertiseHandler(ble_advertise_handle_cb_t advcb); + + /** + * @brief Get BLE peripheral helper by conntion + * + * @param conn The connection object + * + * @return BLEPeripheralHelper* The BLE peripheral helper + * + * @note none + */ + BLEPeripheralHelper* peripheral(struct bt_conn *conn); + + /** + * @brief Get BLE central helper that for APP use + * + * @param none + * + * @return const BLECentralHelper * The BLE central helper + * + * @note none + */ + const BLECentralHelper *central(void) const; + + /** + * Setup attributes and start advertising + * + * @return bool indicating success or error + */ + bool begin(); + + /** + * @brief Disconnect the central connected if there is one connected + * + * @param none + * + * @return bool Indicating success or error + * + * @note none + */ + bool disconnect(); + + /** + * @brief Get BLE Central instance. + * + * @param none + * + * @return BLECentralRole* The BLE Central instance + * + * @note Singleton. Only have one object to communicate with + * stack and manage the device + */ + static BLECentralRole *instance(); + +protected: + friend void ble_central_device_found(const bt_addr_le_t *addr, + int8_t rssi, + uint8_t type, + const uint8_t *ad, + uint8_t len); + + /** + * @brief Handle the connected event + * + * @param conn The object that established the connection + * + * @param err The code of the process + * + * @return none + * + * @note none + */ + void handleConnectEvent(struct bt_conn *conn, uint8_t err); + + /** + * @brief Handle the disconnected event + * + * @param conn The object that lost the connection + * + * @param reason The link lost reason + * + * @return none + * + * @note none + */ + void handleDisconnectEvent(struct bt_conn *conn, uint8_t reason); + + /** + * @brief Handle the conntion update request + * + * @param conn The connection object that need to process the update request + * + * @param interval The connection interval + * + * @param latency The connection latency + * + * @param timeout The connection timeout + * + * @return none + * + * @note none + */ + void handleParamUpdated(struct bt_conn *conn, + uint16_t interval, + uint16_t latency, + uint16_t timeout); + /** + * @brief Handle the advertisement + * + * @param addr The device's MAC address that send out ADV + * + * @param rssi The antenna's RSSI + * + * @param type The advertise type + * + * @param ad The advertisement RAW data + * + * @param len The RAW data's length + * + * @return none + * + * @note none + */ + void handleDeviceFound(const bt_addr_le_t *addr, + int8_t rssi, + uint8_t type, + const uint8_t *ad, + uint8_t len); +private: + BLECentralRole(); + ~BLECentralRole(); + BLEPeripheralHelper* _peripherial[BLE_MAX_CONN_CFG]; + BLECentralHelper _central; + struct bt_le_scan_param _scan_param; + + static BLECentralRole* _ble_central_ins; + ble_advertise_handle_cb_t _adv_event_handle; +}; + +#endif + diff --git a/libraries/CurieBLE/src/BLECharacteristic.cpp b/libraries/CurieBLE/src/BLECharacteristic.cpp index a6c46c07..5c810a5f 100644 --- a/libraries/CurieBLE/src/BLECharacteristic.cpp +++ b/libraries/CurieBLE/src/BLECharacteristic.cpp @@ -18,28 +18,75 @@ */ #include "BLECharacteristic.h" +#include "BLEPeripheralHelper.h" #include "internal/ble_client.h" -#define BLE_CCCD_NOTIFY_EN_MASK 0x1 -#define BLE_CCCD_INDICATE_EN_MASK 0x2 +uint8_t profile_notify_process (struct bt_conn *conn, + struct bt_gatt_subscribe_params *params, + const void *data, uint16_t length); +uint8_t profile_read_rsp_process(struct bt_conn *conn, int err, + struct bt_gatt_read_params *params, + const void *data, + uint16_t length); + +unsigned char BLECharacteristic::_numNotifyAttributes = 0; + +struct bt_uuid_16 BLECharacteristic::_gatt_chrc_uuid = {BT_UUID_TYPE_16, BT_UUID_GATT_CHRC_VAL}; +struct bt_uuid_16 BLECharacteristic::_gatt_ccc_uuid = {BT_UUID_TYPE_16, BT_UUID_GATT_CCC_VAL}; BLECharacteristic::BLECharacteristic(const char* uuid, const unsigned char properties, const unsigned short maxLength) : BLEAttribute(uuid, BLETypeCharacteristic), - _properties(properties), _value_length(0), _written(false), - _cccd_value(0), - _value_handle(0), - _cccd_handle(0), _user_description(NULL), - _presentation_format(NULL) + _presentation_format(NULL), + _attr_chrc_declaration(NULL), + _attr_chrc_value(NULL), + _attr_cccd(NULL) { _value_size = maxLength > BLE_MAX_ATTR_DATA_LEN ? BLE_MAX_ATTR_DATA_LEN : maxLength; _value = (unsigned char*)malloc(_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)); + + _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) + { + _gatt_chrc.properties |= BT_GATT_CHRC_INDICATE; + _sub_params.value |= BT_GATT_CCC_INDICATE; + } + _gatt_chrc.uuid = this->uuid(); memset(_event_handlers, 0, sizeof(_event_handlers)); + + _numNotifyAttributes++; + if (properties & (BT_GATT_CHRC_NOTIFY | BT_GATT_CHRC_INDICATE)) + { + _numNotifyAttributes++; + } + _sub_params.notify = profile_notify_process; } BLECharacteristic::BLECharacteristic(const char* uuid, @@ -61,44 +108,40 @@ BLECharacteristic::~BLECharacteristic() unsigned char BLECharacteristic::properties() const { - return _properties; + return _gatt_chrc.properties; } bool BLECharacteristic::setValue(const unsigned char value[], uint16_t length) { - BleStatus status; + int status; _setValue(value, length); - if (_value_handle) { - status = ble_client_gatts_set_attribute_value(_value_handle, _value_length, _value, 0); - if (BLE_STATUS_SUCCESS != status) { + if (_attr_chrc_value) + { + // TODO: Notify for peripheral. + // Write request for central. + status = bt_gatt_notify(NULL, _attr_chrc_value, value, length, NULL); + if (0 != status) + { return false; } - - if (subscribed()) { - boolean_t indication = (_cccd_value & BLE_CCCD_INDICATE_EN_MASK); - - status = ble_client_gatts_send_notif_ind(_value_handle, _value_length, _value, 0, indication); - if (BLE_STATUS_SUCCESS != status) { - return false; - } - } } - return true; } void -BLECharacteristic::setValue(BLECentral& central, const unsigned char* value, unsigned short length) +BLECharacteristic::setValue(BLEHelper& blehelper, const unsigned char* value, unsigned short length) { + //BLEHelper *bledevice = ¢ral; _setValue(value, length); _written = true; + _reading = false; if (_event_handlers[BLEWritten]) { - _event_handlers[BLEWritten](central, *this); + _event_handlers[BLEWritten](blehelper, *this); } } @@ -139,7 +182,7 @@ BLECharacteristic::written() bool BLECharacteristic::subscribed() { - return (_cccd_value & (BLE_CCCD_NOTIFY_EN_MASK | BLE_CCCD_INDICATE_EN_MASK)); + return (_gatt_chrc.properties & (BT_GATT_CHRC_NOTIFY | BT_GATT_CHRC_INDICATE)); } void @@ -152,114 +195,212 @@ BLECharacteristic::setEventHandler(BLECharacteristicEvent event, BLECharacterist interrupts(); } -bool -BLECharacteristic::add(uint16_t serviceHandle) +uint16_t +BLECharacteristic::valueHandle() { - bt_uuid uuid = btUuid(); + uint16_t handle = 0; + if (NULL != _attr_chrc_value) + { + handle = _attr_chrc_value->handle; + } + + return handle; +} - struct ble_gatts_characteristic char_data; - struct ble_gatts_char_handles handles; - struct ble_gatt_char_user_desc user_desc; - struct ble_gatt_pf_desc pf_desc; +uint16_t +BLECharacteristic::cccdHandle() +{ + uint16_t handle = 0; + if (NULL != _attr_cccd) + { + handle = _attr_cccd->handle; + } + return handle; +} - memset(&char_data, 0, sizeof(char_data)); +void +BLECharacteristic::setUserDescription(BLEDescriptor *descriptor) +{ + _user_description = descriptor; +} - char_data.p_uuid = &uuid; - char_data.props.props = _properties; +void +BLECharacteristic::setPresentationFormat(BLEDescriptor *descriptor) +{ + _presentation_format = descriptor; +} - if (_properties & (BLERead | BLENotify | BLEIndicate)) { - char_data.perms.rd = GAP_SEC_MODE_1 | GAP_SEC_LEVEL_1; - } else { - char_data.perms.rd = GAP_SEC_NO_PERMISSION; +void +BLECharacteristic::_setValue(const uint8_t value[], uint16_t length) +{ + if (length > _value_size) { + length = _value_size; } - if (_properties & (BLEWriteWithoutResponse | BLEWrite)) { - char_data.perms.wr = GAP_SEC_MODE_1 | GAP_SEC_LEVEL_1; - } else { - char_data.perms.wr = GAP_SEC_NO_PERMISSION; - } + memcpy(_value, value, length); + _value_length = length; +} + +unsigned char +BLECharacteristic::numNotifyAttributes(void) { + return _numNotifyAttributes; +} - char_data.init_len = _value_length; - char_data.max_len = _value_size; - char_data.p_value = _value; +struct _bt_gatt_ccc* BLECharacteristic::getCccCfg(void) +{ + return &_ccc_value; +} - if (_user_description) { - user_desc.buffer = (uint8_t*)_user_description->value(); - user_desc.len = _user_description->valueLength(); +struct bt_gatt_chrc* BLECharacteristic::getCharacteristicAttValue(void) +{ + return &_gatt_chrc; +} - char_data.p_user_desc = &user_desc; +uint8_t BLECharacteristic::getPermission(void) +{ + uint8_t perm = 0; + if (_gatt_chrc.properties & BT_GATT_CHRC_READ) + { + perm |= BT_GATT_PERM_READ; + } + if (_gatt_chrc.properties & (BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP)) + { + perm |= BT_GATT_PERM_WRITE; } + return perm; +} - if (_presentation_format) { - const uint8_t* pfValue = _presentation_format->value(); +struct bt_uuid* BLECharacteristic::getCharacteristicAttributeUuid(void) +{ + return (struct bt_uuid*) &_gatt_chrc_uuid; +} +struct bt_uuid* BLECharacteristic::getClientCharacteristicConfigUuid(void) +{ + return (struct bt_uuid*) &_gatt_ccc_uuid; +} - pf_desc.format = pfValue[0]; - pf_desc.exp = pfValue[1]; - pf_desc.unit = (pfValue[3] << 8) | pfValue[2]; - pf_desc.name_spc = pfValue[4]; - pf_desc.descr = (pfValue[6] << 8) | pfValue[5]; - char_data.p_char_pf_desc = &pf_desc; - } - - BleStatus status = ble_client_gatts_add_characteristic(serviceHandle, &char_data, &handles); - if (BLE_STATUS_SUCCESS == status) { - _value_handle = handles.value_handle; - _cccd_handle = handles.cccd_handle; - } +void BLECharacteristic::addCharacteristicDeclaration(struct bt_gatt_attr *gatt_attr) +{ + _attr_chrc_declaration = gatt_attr; +} - return (BLE_STATUS_SUCCESS == status); +void BLECharacteristic::addCharacteristicValue(struct bt_gatt_attr *gatt_attr) +{ + _attr_chrc_value = gatt_attr; } -uint16_t -BLECharacteristic::valueHandle() +void BLECharacteristic::addCharacteristicConfigDescriptor(struct bt_gatt_attr *gatt_attr) { - return _value_handle; + _attr_cccd = gatt_attr; } -uint16_t -BLECharacteristic::cccdHandle() +void BLECharacteristic::discover(struct bt_gatt_discover_params *params) { - return _cccd_handle; + params->type = BT_GATT_DISCOVER_CHARACTERISTIC; + params->uuid = this->uuid(); + // Start discovering + _discoverying = true; + // Re-Init the read/write parameter + _reading = false; } -void -BLECharacteristic::setCccdValue(BLECentral& central, uint16_t value) + +void BLECharacteristic::discover(const struct bt_gatt_attr *attr, + struct bt_gatt_discover_params *params) { - if (_cccd_value != value) { - _cccd_value = value; - - if (subscribed()) { - if (_event_handlers[BLESubscribed]) { - _event_handlers[BLESubscribed](central, *this); - } - } else { - if (_event_handlers[BLEUnsubscribed]) { - _event_handlers[BLEUnsubscribed](central, *this); - } + if (!attr) + { + // Discovery complete + _discoverying = false; + return; + } + + // Chracteristic Char + if (params->uuid == this->uuid()) + { + // Set Discover CCCD parameter + params->start_handle = attr->handle + 2; + if (subscribed()) + { + // Include CCCD + params->type = BT_GATT_DISCOVER_DESCRIPTOR; + params->uuid = this->getClientCharacteristicConfigUuid(); + } + else + { + // Complete the discover + _discoverying = false; } } + else if (params->uuid == this->getClientCharacteristicConfigUuid()) + { + params->start_handle = attr->handle + 1; + _discoverying = false; + } } -void -BLECharacteristic::setUserDescription(BLEDescriptor *descriptor) +struct bt_gatt_subscribe_params *BLECharacteristic::getSubscribeParams() { - _user_description = descriptor; + return &_sub_params; } -void -BLECharacteristic::setPresentationFormat(BLEDescriptor *descriptor) +bool BLECharacteristic::read(BLEPeripheralHelper &peripheral) { - _presentation_format = descriptor; + int retval = 0; + struct bt_conn* conn = NULL; + if (_reading) + { + // Already in reading state + return false; + } + + _read_params.func = profile_read_rsp_process; + _read_params.handle_count = 1; + _read_params.single.handle = peripheral.valueHandle(this); + _read_params.single.offset = 0; + + if (0 == _read_params.single.handle) + { + // Discover not complete + return false; + } + + conn = bt_conn_lookup_addr_le(peripheral.bt_le_address()); + if (NULL == conn) + { + return false; + } + + // Send read request + retval = bt_gatt_read(conn, &_read_params); + bt_conn_unref(conn); + if (0 == retval) + { + _reading = true; + } + return _reading; } -void -BLECharacteristic::_setValue(const uint8_t value[], uint16_t length) +bool BLECharacteristic::write(BLEPeripheralHelper &peripheral, + const unsigned char value[], + uint16_t length) { - if (length > _value_size) { - length = _value_size; + int retval = 0; + struct bt_conn* conn = NULL; + + conn = bt_conn_lookup_addr_le(peripheral.bt_le_address()); + if (NULL == conn) + { + return false; } - - memcpy(_value, value, length); - _value_length = length; + + // Send read request + retval = bt_gatt_write_without_response(conn, + peripheral.valueHandle(this), + value, length, false); + bt_conn_unref(conn); + return (0 == retval); } + + diff --git a/libraries/CurieBLE/src/BLECharacteristic.h b/libraries/CurieBLE/src/BLECharacteristic.h index a5afaa36..a867e296 100644 --- a/libraries/CurieBLE/src/BLECharacteristic.h +++ b/libraries/CurieBLE/src/BLECharacteristic.h @@ -20,8 +20,10 @@ #ifndef _BLE_CHARACTERISTIC_H_INCLUDED #define _BLE_CHARACTERISTIC_H_INCLUDED +#include "BLECommon.h" + #include "BLEAttribute.h" -#include "BLECentral.h" +#include "BLECentralHelper.h" #include "BLEDescriptor.h" /** @@ -38,9 +40,10 @@ enum BLECharacteristicEvent { /* Forward declaration needed for callback function prototype below */ class BLECharacteristic; class BLEPeripheral; +class BLEHelper; /** Function prototype for BLE Characteristic event callback */ -typedef void (*BLECharacteristicEventHandler)(BLECentral ¢ral, BLECharacteristic &characteristic); +typedef void (*BLECharacteristicEventHandler)(BLEHelper &bleHelper, BLECharacteristic &characteristic); /** * BLE Characteristic Property types @@ -94,6 +97,18 @@ class BLECharacteristic : public BLEAttribute { */ bool setValue(const unsigned char value[], unsigned short length); + /** + * Set the current value of the Characteristic + * + * @param central The central device that update the value. + * @param value New value to set, as a byte array. Data is stored in internal copy. + * @param length Length, in bytes, of valid data in the array to write. + * Must not exceed maxLength set for this characteristic. + * + * @return bool true set value success, false on error + */ + void setValue(BLEHelper& blehelper, const uint8_t value[], uint16_t length); + /** * Get the property mask of the Characteristic * @@ -146,38 +161,161 @@ class BLECharacteristic : public BLEAttribute { */ void setEventHandler(BLECharacteristicEvent event, BLECharacteristicEventHandler callback); -protected: - bool add(uint16_t serviceHandle); + /** + * @brief Get Notify Attribute counter that created + * + * @param none + * + * @return unsigned char The totla number of the notify attributes + * + * @note none + */ + static unsigned char numNotifyAttributes(void); + + /** + * @brief Schedule the read request to read the characteristic in peripheral + * + * @param peripheral The peripheral device that want to read. + * + * @return bool Indicate the success or error + * + * @note Only for central device + */ + bool read(BLEPeripheralHelper &peripheral); + + /** + * @brief Schedule the write request to update the characteristic in peripheral + * + * @param peripheral The peripheral device that want to be updated + * @param value New value to set, as a byte array. Data is stored in internal copy. + * @param length Length, in bytes, of valid data in the array to write. + * Must not exceed maxLength set for this characteristic. + * + * @return bool true set value success, false on error + * + * @note none + */ + bool write(BLEPeripheralHelper &peripheral, + const unsigned char value[], + uint16_t length); +protected: + friend class BLEProfile; + + void addCharacteristicDeclaration(struct bt_gatt_attr *gatt_attr); + void addCharacteristicValue(struct bt_gatt_attr *gatt_attr); + void addCharacteristicConfigDescriptor(struct bt_gatt_attr *gatt_attr); + + /** + * @brief Get the characteristic value handle + * + * @param none + * + * @return none + * + * @note Only for peripheral + */ uint16_t valueHandle(void); - + + /** + * @brief Get characteristic configuration descriptor value handle + * + * @param none + * + * @return uint16_t The value handle + * 0 is invalid handle + * + * @note Only for peripheral + */ uint16_t cccdHandle(void); - void setValue(BLECentral& central, const uint8_t value[], uint16_t length); - void setCccdValue(BLECentral& central, uint16_t value); - + void setUserDescription(BLEDescriptor *descriptor); void setPresentationFormat(BLEDescriptor *descriptor); - - friend class BLEPeripheral; + + struct _bt_gatt_ccc* getCccCfg(void); + struct bt_gatt_chrc* getCharacteristicAttValue(void); + static struct bt_uuid* getCharacteristicAttributeUuid(void); + static struct bt_uuid* getClientCharacteristicConfigUuid(void); + + /** + * @brief Get the characteristic permission + * + * @param none + * + * @return uint8_t The characteristic permission + * + * @note none + */ + uint8_t getPermission(void); + + /** + * @brief For central to discover the peripherial profile + * + * @param attr The discover response + * + * @param params The discover parameter that need to fill + * + * @return none + * + * @note Only for central + */ + void discover(const struct bt_gatt_attr *attr, + struct bt_gatt_discover_params *params); + + /** + * @brief For central to discover the peripherial profile + * + * @param params The discover parameter that need to fill + * + * @return none + * + * @note Only for central + */ + void discover(struct bt_gatt_discover_params *params); + + /** + * @brief Get the subscribe parameter + * + * @param none + * + * @return struct bt_gatt_subscribe_params * the subscribe parameter + * + * @note Only for central + */ + struct bt_gatt_subscribe_params* getSubscribeParams(); private: void _setValue(const uint8_t value[], uint16_t length); private: - unsigned char _properties; + + static unsigned char _numNotifyAttributes; + static struct bt_uuid_16 _gatt_chrc_uuid; + static struct bt_uuid_16 _gatt_ccc_uuid; + unsigned short _value_size; unsigned short _value_length; unsigned char* _value; bool _written; - uint16_t _cccd_value; uint16_t _value_handle; - uint16_t _cccd_handle; + struct bt_gatt_ccc_cfg _ccc_cfg; + struct _bt_gatt_ccc _ccc_value; + struct bt_gatt_chrc _gatt_chrc; BLEDescriptor* _user_description; BLEDescriptor* _presentation_format; + struct bt_gatt_attr *_attr_chrc_declaration; + struct bt_gatt_attr *_attr_chrc_value; + struct bt_gatt_attr *_attr_cccd; + + // For central device to subscribe the Notification/Indication + struct bt_gatt_subscribe_params _sub_params; + + bool _reading; + struct bt_gatt_read_params _read_params; BLECharacteristicEventHandler _event_handlers[BLECharacteristicEventLast]; }; diff --git a/libraries/CurieBLE/src/BLECommon.h b/libraries/CurieBLE/src/BLECommon.h index 20bf0e23..00c31342 100644 --- a/libraries/CurieBLE/src/BLECommon.h +++ b/libraries/CurieBLE/src/BLECommon.h @@ -22,9 +22,21 @@ #include "Arduino.h" -#include "../src/services/ble/ble_protocol.h" -#include "services/ble/ble_service_gatt.h" -#include "services/ble/ble_service_gatts_api.h" +#include "../src/services/ble_service/ble_protocol.h" + + +#include "infra/log.h" + + +#include +#include +#include +#include + +#define BLE_ADDR_LEN 6 + +#define MAX_UUID_SIZE 16 + /* Theoretically we should be able to support attribute lengths up to 512 bytes * but this involves splitting it across multiple packets. For simplicity, @@ -40,6 +52,30 @@ /* Invalid BLE Address type */ #define BLE_DEVICE_ADDR_INVALID 0xFF +/** BLE response/event status codes. */ +enum BLE_STATUS { + BLE_STATUS_SUCCESS = 0, /**< General BLE Success code */ + BLE_STATUS_PENDING, /**< Request received and execution started, response pending */ + BLE_STATUS_TIMEOUT, /**< Request timed out */ + BLE_STATUS_NOT_SUPPORTED, /**< Request/feature/parameter not supported */ + BLE_STATUS_NOT_ALLOWED, /**< Request not allowed */ + BLE_STATUS_LINK_TIMEOUT, /**< Link timeout (link loss) */ + BLE_STATUS_NOT_ENABLED, /**< BLE not enabled, @ref ble_enable */ + BLE_STATUS_ERROR, /**< Generic Error */ + BLE_STATUS_ALREADY_REGISTERED, /**< BLE service already registered */ + BLE_STATUS_WRONG_STATE, /**< Wrong state for request */ + BLE_STATUS_ERROR_PARAMETER, /**< Parameter in request is wrong */ + BLE_STATUS_GAP_BASE = 0x100, /**< GAP specific error base */ + BLE_STATUS_GATT_BASE = 0x200, /**< GATT specific Error base */ +}; + +typedef uint16_t ble_status_t; /**< Response and event BLE service status type @ref BLE_STATUS */ + typedef ble_status_t BleStatus; +#define BLE_MAX_CONN_CFG 2 + +typedef bool (*ble_advertise_handle_cb_t)(uint8_t type, const uint8_t *data, + uint8_t data_len, void *user_data); + #endif // _BLE_COMMON_H_INCLUDED diff --git a/libraries/CurieBLE/src/BLEDescriptor.cpp b/libraries/CurieBLE/src/BLEDescriptor.cpp index 8e50120b..d611d471 100644 --- a/libraries/CurieBLE/src/BLEDescriptor.cpp +++ b/libraries/CurieBLE/src/BLEDescriptor.cpp @@ -63,23 +63,3 @@ BLEDescriptor::operator[] (int offset) const return _value[offset]; } -bool -BLEDescriptor::add(uint16_t serviceHandle) -{ - bt_uuid uuid = btUuid(); - struct ble_gatts_descriptor desc; - uint16_t handle = 0; - - memset(&desc, 0, sizeof(desc)); - - desc.p_uuid = &uuid; - - desc.p_value = _value; - desc.length = _value_length; - - // this class only supports read-only descriptors - desc.perms.rd = GAP_SEC_MODE_1 | GAP_SEC_LEVEL_1; - desc.perms.wr = GAP_SEC_NO_PERMISSION; - - return (ble_client_gatts_add_descriptor(serviceHandle, &desc, &handle) == BLE_STATUS_SUCCESS); -} diff --git a/libraries/CurieBLE/src/BLEDescriptor.h b/libraries/CurieBLE/src/BLEDescriptor.h index 08e53f13..498035a0 100644 --- a/libraries/CurieBLE/src/BLEDescriptor.h +++ b/libraries/CurieBLE/src/BLEDescriptor.h @@ -65,7 +65,6 @@ class BLEDescriptor : public BLEAttribute { unsigned char operator[] (int offset) const; protected: - bool add(uint16_t serviceHandle); friend BLEPeripheral; diff --git a/libraries/CurieBLE/src/BLEHelper.cpp b/libraries/CurieBLE/src/BLEHelper.cpp new file mode 100644 index 00000000..b756f5d4 --- /dev/null +++ b/libraries/CurieBLE/src/BLEHelper.cpp @@ -0,0 +1,135 @@ + +#include "BLECentralHelper.h" + +#include "BLEPeripheral.h" + + +BLEHelper::BLEHelper() +{ + clearAddress(); + memset(&_conn_params, 0x00, sizeof(_conn_params)); + _conn_params.interval_max = BT_GAP_INIT_CONN_INT_MAX; + _conn_params.interval_min = BT_GAP_INIT_CONN_INT_MIN; + _conn_params.latency = 0; + _conn_params.timeout = 400; +} + +BLEHelper::~BLEHelper() +{ + #if 0 + if (NULL != _conn) + { + bt_conn_unref(_conn); + } + #endif +} + +#if 0 +void BLEHelper::setConn(struct bt_conn *conn) +{ + if (conn == _conn) + { + return; + } + + if (NULL != _conn) + { + bt_conn_unref(_conn); + } + _conn = conn; +} +#endif + +BLEHelper::operator bool() const +{ + bt_addr_le_t zero; + + memset(&zero, 0, sizeof(zero)); + + return (memcmp(&_address, &zero, sizeof(_address)) != 0); +} + +bool BLEHelper::operator==(const BLEHelper& rhs) const +{ + return (memcmp(&_address, &rhs._address, sizeof(_address)) == 0); +} + +bool +BLEHelper::operator==(const bt_addr_le_t& address) const { + return (memcmp(&_address, &address, sizeof(_address)) == 0); +} + +bool +BLEHelper::operator!=(const BLEHelper& rhs) const { + return !(*this == rhs); +} + +const char* +BLEHelper::address() const { + static char address[18]; + + String addressStr = ""; + + for (int i = 5; i >= 0; i--) { + unsigned char a = _address.val[i]; + + if (a < 0x10) { + addressStr += "0"; + } + + addressStr += String(a, 16); + + if (i > 0) { + addressStr += ":"; + } + } + + strcpy(address, addressStr.c_str()); + + return address; +} +/* +const bt_addr_t *BLEHelper::address(void) const +{ + return (bt_addr_t *)_address.val; +} +*/ + +const bt_addr_le_t *BLEHelper::bt_le_address(void) const +{ + return &_address; +} + +void +BLEHelper::poll() { + delay(1); +} + +void +BLEHelper::setAddress(bt_addr_le_t address) { + _address = address; +} + +void +BLEHelper::clearAddress() { + memset(&_address, 0x00, sizeof(_address)); +} + +const struct bt_le_conn_param *BLEHelper::getConnParams() +{ + return &_conn_params; +} + +void BLEHelper::setConnParames(uint16_t intervalmin, + uint16_t intervalmax, + uint16_t latency, + uint16_t timeout) +{ + _conn_params.interval_max = intervalmin; + _conn_params.interval_min = intervalmax; + _conn_params.latency = latency; + _conn_params.timeout = timeout; + +} + + diff --git a/libraries/CurieBLE/src/BLEHelper.h b/libraries/CurieBLE/src/BLEHelper.h new file mode 100644 index 00000000..f844eea6 --- /dev/null +++ b/libraries/CurieBLE/src/BLEHelper.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef _BLE_HELPER_H_ +#define _BLE_HELPER_H_ + + +class BLEHelper { + public: + /** + * Is the Central connected + * + * @return boolean_t true if the central is connected, otherwise false + */ + virtual bool connected(void) = 0; + + /** + * Get the address of the Central in string form + * + * @return const char* address of the Central in string form + */ + const char* address(void) const; + + const bt_addr_le_t *bt_le_address(void) const; + /** + * Disconnect the central if it is connected + * + */ + virtual bool disconnect(void) = 0; + + /** + * Poll the central for events + */ + void poll(void); + + operator bool(void) const; + bool operator==(const BLEHelper& rhs) const; + bool operator==(const bt_addr_le_t& rhs) const; + bool operator!=(const BLEHelper& rhs) const; + void operator=(const BLEHelper& rhs); + void setConn(struct bt_conn *conn); + + const struct bt_le_conn_param *getConnParams(); + void setConnParames(uint16_t intervalmin, + uint16_t intervalmax, + uint16_t latency, + uint16_t timeout); + + protected: + void setAddress(bt_addr_le_t address); + void clearAddress(); + BLEHelper(); + virtual ~BLEHelper(); + + private: + bt_addr_le_t _address; + //struct bt_conn *_conn; + struct bt_le_conn_param _conn_params; +}; + +#endif + + diff --git a/libraries/CurieBLE/src/BLEPeripheral.cpp b/libraries/CurieBLE/src/BLEPeripheral.cpp index f1218bcd..ca40137b 100644 --- a/libraries/CurieBLE/src/BLEPeripheral.cpp +++ b/libraries/CurieBLE/src/BLEPeripheral.cpp @@ -18,112 +18,42 @@ */ #include "BLEPeripheral.h" +#include "BLEPeripheralRole.h" -#include "BLECharacteristic.h" -#include "BLEDescriptor.h" -#include "BLEService.h" -#include "BLEUuid.h" - - -#define BLE_DISCONNECT_REASON_LOCAL_TERMINATION 0x16 - -void -blePeripheralGapEventHandler(ble_client_gap_event_t event, struct ble_gap_event *event_data, void *param) -{ - BLEPeripheral* p = (BLEPeripheral*)param; - - p->handleGapEvent(event, event_data); -} - -void -blePeripheralGattsEventHandler(ble_client_gatts_event_t event, struct ble_gatts_evt_msg *event_data, void *param) -{ - BLEPeripheral* p = (BLEPeripheral*)param; - - p->handleGattsEvent(event, event_data); -} +//#include "BLECharacteristic.h" BLEPeripheral::BLEPeripheral(void) : - _state(BLE_PERIPH_STATE_NOT_READY), - _advertise_service_uuid(NULL), _local_name(NULL), - _service_data_uuid(NULL), - _service_data(NULL), - _service_data_length(0), _appearance(0), - _min_conn_interval(DEFAULT_MIN_CONN_INTERVAL), - _max_conn_interval(DEFAULT_MAX_CONN_INTERVAL), - _central(this), - _attributes(NULL), - _num_attributes(0), - _last_added_characteritic(NULL) + _adv_data_idx(0) { - memset(_event_handlers, 0x00, sizeof(_event_handlers)); - - ble_client_get_factory_config(&_local_bda, _device_name); + memset(_adv_data, 0x00, sizeof(_adv_data)); + + // Default Advertising parameter + setAdvertisingParam(BT_LE_ADV_IND , + 0xA0, + 0xF0); } BLEPeripheral::~BLEPeripheral(void) { - if (this->_attributes) { - free(this->_attributes); - } } bool BLEPeripheral::begin() { - BleStatus status; - - status = _init(); - if (status != BLE_STATUS_SUCCESS) { + bool ret = false; + + pr_info(LOG_MODULE_BLE, "%s: %d", __FUNCTION__, 1); + + ret = BLEPeripheralRole::instance()->begin(); + if (!ret) + { return false; } - - /* Populate advertising data - */ - _advDataInit(); - - status = ble_client_gap_wr_adv_data(_adv_data, _adv_data_len); - if (BLE_STATUS_SUCCESS != status) { - return false; - } - - uint16_t lastServiceHandle = 0; - - for (int i = 0; i < _num_attributes; i++) { - BLEAttribute* attribute = _attributes[i]; - BLEAttributeType type = attribute->type(); - bool addResult = false; - - if (BLETypeService == type) { - BLEService* service = (BLEService*)attribute; - - addResult = service->add(); - - lastServiceHandle = service->handle(); - } else if (BLETypeCharacteristic == type) { - BLECharacteristic* characteristic = (BLECharacteristic*)attribute; - - addResult = characteristic->add(lastServiceHandle); - } else if (BLETypeDescriptor == type) { - BLEDescriptor *descriptor = (BLEDescriptor*)attribute; - - if (strcmp(descriptor->uuid(), "2901") == 0 || - strcmp(descriptor->uuid(), "2902") == 0 || - strcmp(descriptor->uuid(), "2903") == 0 || - strcmp(descriptor->uuid(), "2904") == 0) { - continue; // skip - } - - addResult = descriptor->add(lastServiceHandle); - } - - if (!addResult) { - return false; - } - } - - return (_startAdvertising() == BLE_STATUS_SUCCESS); + + pr_info(LOG_MODULE_BLE, "%s: %d", __FUNCTION__, 2); + + return (startAdvertising() == BLE_STATUS_SUCCESS); } void @@ -136,23 +66,11 @@ BLEPeripheral::poll() void BLEPeripheral::end() { - _stop(); -} - -uint8_t -BLEPeripheral::getAdvertisingLength() -{ - return _adv_data_len; -} - -uint8_t* -BLEPeripheral::getAdvertising() -{ - return _adv_data; + BLEPeripheralRole::instance()->stop(); } void -BLEPeripheral::setAdvertisedServiceUuid(const char* advertisedServiceUuid) +BLEPeripheral::setAdvertisedServiceUuid(const struct bt_uuid* advertisedServiceUuid) { _advertise_service_uuid = advertisedServiceUuid; } @@ -164,23 +82,28 @@ BLEPeripheral::setLocalName(const char* localName) } void -BLEPeripheral::setAdvertisedServiceData(const char* serviceDataUuid, uint8_t* serviceData, uint8_t serviceDataLength) +BLEPeripheral::setAdvertisedServiceData(const struct bt_uuid* serviceDataUuid, + uint8_t* serviceData, + uint8_t serviceDataLength) { _service_data_uuid = serviceDataUuid; _service_data = serviceData; _service_data_length = serviceDataLength; } +void BLEPeripheral::setAdvertisingParam(uint8_t type, + uint16_t interval_min, + uint16_t interval_max) +{ + BLEPeripheralRole::instance()->setAdvertisingParam(type, + interval_min, + interval_max); +} + void BLEPeripheral::setDeviceName(const char deviceName[]) { - memset(_device_name, 0, sizeof(_device_name)); - if (deviceName && deviceName[0]) { - int len = strlen(deviceName); - if (len > BLE_MAX_DEVICE_NAME) - len = BLE_MAX_DEVICE_NAME; - memcpy(_device_name, deviceName, len); - } + BLEPeripheralRole::instance()->setDeviceName(deviceName); } void @@ -192,286 +115,160 @@ BLEPeripheral::setAppearance(const uint16_t appearance) void BLEPeripheral::setConnectionInterval(const unsigned short minConnInterval, const unsigned short maxConnInterval) { - _min_conn_interval = minConnInterval; - _max_conn_interval = maxConnInterval; - - if (_min_conn_interval < MIN_CONN_INTERVAL) { - _min_conn_interval = MIN_CONN_INTERVAL; - } else if (_min_conn_interval > MAX_CONN_INTERVAL) { - _min_conn_interval = MAX_CONN_INTERVAL; - } - - if (_max_conn_interval < _min_conn_interval) { - _max_conn_interval = _min_conn_interval; - } else if (_max_conn_interval > MAX_CONN_INTERVAL) { - _max_conn_interval = MAX_CONN_INTERVAL; - } + BLEPeripheralRole::instance()->setConnectionInterval(minConnInterval, + maxConnInterval); } void -BLEPeripheral::setEventHandler(BLEPeripheralEvent event, BLEPeripheralEventHandler callback) +BLEPeripheral::setEventHandler(BLERoleEvent event, BLERoleEventHandler callback) { - if (event < sizeof(_event_handlers)) { - _event_handlers[event] = callback; - } -} - -void -BLEPeripheral::addAttribute(BLEAttribute& attribute) -{ - if (_attributes == NULL) { - _attributes = (BLEAttribute**)malloc(BLEAttribute::numAttributes() * sizeof(BLEAttribute*)); - } - - _attributes[_num_attributes] = &attribute; - _num_attributes++; - - BLEAttributeType type = attribute.type(); - - if (BLETypeCharacteristic == type) { - _last_added_characteritic = (BLECharacteristic*)&attribute; - } else if (BLETypeDescriptor == type) { - if (_last_added_characteritic) { - BLEDescriptor* descriptor = (BLEDescriptor*)&attribute; - - if (strcmp("2901", descriptor->uuid()) == 0) { - _last_added_characteritic->setUserDescription(descriptor); - } else if (strcmp("2904", descriptor->uuid()) == 0) { - _last_added_characteritic->setPresentationFormat(descriptor); - } - } - } + BLEPeripheralRole::instance()->setEventHandler(event, callback); } bool BLEPeripheral::disconnect() { - BleStatus status; - - if (BLE_PERIPH_STATE_CONNECTED == _state) { - status = ble_client_gap_disconnect(BLE_DISCONNECT_REASON_LOCAL_TERMINATION); - } else { - status = BLE_STATUS_WRONG_STATE; - } - - return (status == BLE_STATUS_SUCCESS); + return BLEPeripheralRole::instance()->disconnect(); } -BLECentral +BLECentralHelper BLEPeripheral::central() { - poll(); - - return _central; + return BLEPeripheralRole::instance()->central(); } bool BLEPeripheral::connected() { - poll(); - - return _central; + return BLEPeripheralRole::instance()->connected(); } -BleStatus -BLEPeripheral::_init() +void BLEPeripheral::addAttribute(BLEAttribute& attribute) { - BleStatus status; - int8_t txPower = 127; - - if (BLE_PERIPH_STATE_NOT_READY != _state) - return BLE_STATUS_WRONG_STATE; - - status = ble_client_init(blePeripheralGapEventHandler, this, - blePeripheralGattsEventHandler, this); - if (BLE_STATUS_SUCCESS != status) { - return status; - } - - status = ble_client_gap_set_enable_config(_device_name, &_local_bda, _appearance, txPower, _min_conn_interval, _max_conn_interval); - if (BLE_STATUS_SUCCESS != status) { - return status; - } - - _state = BLE_PERIPH_STATE_READY; - return BLE_STATUS_SUCCESS; + BLEPeripheralRole::instance()->addAttribute(attribute); } -void + +BleStatus BLEPeripheral::_advDataInit(void) { - uint8_t *adv_tmp = _adv_data; - - memset(_adv_data, 0, sizeof(_adv_data)); - + uint8_t lengthTotal = 2; // Flags data length + _adv_data_idx = 0; + /* Add flags */ - *adv_tmp++ = 2; - *adv_tmp++ = BLE_ADV_TYPE_FLAGS; - *adv_tmp++ = BLE_SVC_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; - _adv_data_len = 3; - - if (_advertise_service_uuid) { - BLEUuid bleUuid = BLEUuid(_advertise_service_uuid); - struct bt_uuid uuid = bleUuid.uuid(); - - if (BT_UUID16 == uuid.type) { - uint8_t *adv_tmp = &_adv_data[_adv_data_len]; - *adv_tmp++ = (1 + sizeof(uint16_t)); /* Segment data length */ - *adv_tmp++ = BLE_ADV_TYPE_COMP_16_UUID; /* Needed for Eddystone */ - UINT16_TO_LESTREAM(adv_tmp, uuid.uuid16); - _adv_data_len += (2 + sizeof(uint16_t)); - } else if (BT_UUID128 == uuid.type) { - uint8_t *adv_tmp = &_adv_data[_adv_data_len]; - *adv_tmp++ = (1 + MAX_UUID_SIZE); /* Segment data length */ - *adv_tmp++ = BLE_ADV_TYPE_INC_128_UUID; - memcpy(adv_tmp, uuid.uuid128, MAX_UUID_SIZE); - _adv_data_len += (2 + MAX_UUID_SIZE); + _adv_type = (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR); + _adv_data[_adv_data_idx].type = BT_DATA_FLAGS; + _adv_data[_adv_data_idx].data = &_adv_type; + _adv_data[_adv_data_idx].data_len = 1; + _adv_data_idx++; + + if (_advertise_service_uuid) + { + uint8_t type; + uint8_t length; + uint8_t *data = NULL; + + pr_info(LOG_MODULE_BLE, "ADV Type-%d", _advertise_service_uuid->type); + if (BT_UUID_TYPE_16 == _advertise_service_uuid->type) + { + //UINT16_TO_LESTREAM(adv_tmp, uuid.uuid16); + data = (uint8_t *)&(((struct bt_uuid_16 *)_advertise_service_uuid)->val); + length = sizeof(uint16_t); + type = BT_DATA_UUID16_ALL; + } + else if (BT_UUID_TYPE_128 == _advertise_service_uuid->type) + { + data = ((struct bt_uuid_128 *)_advertise_service_uuid)->val; + length = MAX_UUID_SIZE; + type = BT_DATA_UUID128_ALL; + } + if (NULL != data) + { + _adv_data[_adv_data_idx].type = type; + _adv_data[_adv_data_idx].data = data; + _adv_data[_adv_data_idx].data_len = length; + _adv_data_idx++; + lengthTotal += length; + + pr_info(LOG_MODULE_BLE, "Service UUID Len -%d", length); } } - if (_local_name) { + if (_local_name) + { /* Add device name (truncated if too long) */ - uint8_t calculated_len; - - adv_tmp = &_adv_data[_adv_data_len]; - if (_adv_data_len + strlen(_local_name) + 2 <= BLE_MAX_ADV_SIZE) { - *adv_tmp++ = strlen(_local_name) + 1; - *adv_tmp++ = BLE_ADV_TYPE_COMP_LOCAL_NAME; - calculated_len = strlen(_local_name); - } else { - *adv_tmp++ = BLE_MAX_ADV_SIZE - _adv_data_len - 1; - *adv_tmp++ = BLE_ADV_TYPE_SHORT_LOCAL_NAME; - calculated_len = BLE_MAX_ADV_SIZE - _adv_data_len - 2; - } - - memcpy(adv_tmp, _local_name, calculated_len); - _adv_data_len += calculated_len + 2; + _adv_data[_adv_data_idx].type = BT_DATA_NAME_COMPLETE; + _adv_data[_adv_data_idx].data = (const uint8_t*)_local_name; + _adv_data[_adv_data_idx].data_len = strlen(_local_name); + _adv_data_idx++; + + lengthTotal += strlen(_local_name); + pr_info(LOG_MODULE_BLE, "Local Name -%s", _local_name); + pr_info(LOG_MODULE_BLE, "Local Name Len -%d", strlen(_local_name)); } - if (_service_data) { + if (_service_data) + { /* Add Service Data (if it will fit) */ - BLEUuid bleUuid = BLEUuid(_service_data_uuid); - struct bt_uuid uuid = bleUuid.uuid(); - /* A 128-bit Service Data UUID won't fit in an Advertising packet */ - if (BT_UUID16 != uuid.type) { - return; /* We support service data only for 16-bit service UUID */ + if (BT_UUID_TYPE_16 != _service_data_uuid->type) + { + /* We support service data only for 16-bit service UUID */ + return BLE_STATUS_NOT_SUPPORTED; } - uint8_t block_len = 1 + sizeof(uint16_t) + _service_data_length; - if (_adv_data_len + 1 + block_len > BLE_MAX_ADV_SIZE) { - return; // Service data block is too large. + uint8_t block_len = sizeof(uint16_t) + _service_data_length; + if (1 + block_len > BLE_MAX_ADV_SIZE) + { + // Service data block is too large. + return BLE_STATUS_ERROR_PARAMETER; } + + _adv_data[_adv_data_idx].type = BT_DATA_SVC_DATA16; + _adv_data[_adv_data_idx].data = _service_data_buf; + _adv_data[_adv_data_idx].data_len = block_len; + _adv_data_idx++; - adv_tmp = &_adv_data[_adv_data_len]; + uint8_t *adv_tmp = _service_data_buf; - *adv_tmp++ = block_len; - _adv_data_len++; - - *adv_tmp++ = BLE_ADV_TYPE_SERVICE_DATA_16_UUID; - UINT16_TO_LESTREAM(adv_tmp, uuid.uuid16); + UINT16_TO_LESTREAM(adv_tmp, (((struct bt_uuid_16 *)_service_data_uuid)->val)); memcpy(adv_tmp, _service_data, _service_data_length); - - _adv_data_len += block_len; + + lengthTotal += block_len; + pr_info(LOG_MODULE_BLE, "SVC Len -%d", block_len); + } + if (lengthTotal > BLE_MAX_ADV_SIZE) + { + pr_error(LOG_MODULE_BLE, "ADV Total length-%d", lengthTotal); + // Service data block is too large. + return BLE_STATUS_ERROR_PARAMETER; } -} - -BleStatus -BLEPeripheral::_startAdvertising() -{ - BleStatus status; - - if (_state != BLE_PERIPH_STATE_READY) - return BLE_STATUS_WRONG_STATE; - - status = ble_client_gap_start_advertise(0); // 0 = no timeout - if (BLE_STATUS_SUCCESS != status) - return status; - - _state = BLE_PERIPH_STATE_ADVERTISING; return BLE_STATUS_SUCCESS; } BleStatus -BLEPeripheral::_stop(void) +BLEPeripheral::startAdvertising() { - BleStatus status; - - if (BLE_PERIPH_STATE_ADVERTISING == _state) - status = ble_client_gap_stop_advertise(); - else - status = disconnect(); - + BleStatus status = BLE_STATUS_SUCCESS; + status = _advDataInit(); if (BLE_STATUS_SUCCESS != status) + { return status; - - _state = BLE_PERIPH_STATE_READY; - return BLE_STATUS_SUCCESS; -} - -void -BLEPeripheral::handleGapEvent(ble_client_gap_event_t event, struct ble_gap_event *event_data) -{ - if (BLE_CLIENT_GAP_EVENT_CONNECTED == event) { - _state = BLE_PERIPH_STATE_CONNECTED; - _central.setAddress(event_data->connected.peer_bda); - - if (_event_handlers[BLEConnected]) { - _event_handlers[BLEConnected](_central); - } - } else if (BLE_CLIENT_GAP_EVENT_DISCONNECTED == event) { - - for (int i = 0; i < _num_attributes; i++) { - BLEAttribute* attribute = _attributes[i]; - - if (attribute->type() == BLETypeCharacteristic) { - BLECharacteristic* characteristic = (BLECharacteristic*)attribute; - - characteristic->setCccdValue(_central, 0x0000); // reset CCCD - } - } - - if (_event_handlers[BLEDisconnected]) - _event_handlers[BLEDisconnected](_central); - - _state = BLE_PERIPH_STATE_READY; - _central.clearAddress(); - - _startAdvertising(); - } else if (BLE_CLIENT_GAP_EVENT_CONN_TIMEOUT == event) { - _state = BLE_PERIPH_STATE_READY; - - _startAdvertising(); } + status = BLEPeripheralRole::instance()->startAdvertising(_adv_data, + _adv_data_idx, + NULL, + 0); + return status; } -void -BLEPeripheral::handleGattsEvent(ble_client_gatts_event_t event, struct ble_gatts_evt_msg *event_data) +BleStatus +BLEPeripheral::stopAdvertising() { - if (BLE_CLIENT_GATTS_EVENT_WRITE == event) { - uint16_t handle = event_data->wr.attr_handle; - - for (int i = 0; i < _num_attributes; i++) { - BLEAttribute* attribute = _attributes[i]; - - if (attribute->type() != BLETypeCharacteristic) { - continue; - } - - BLECharacteristic* characteristic = (BLECharacteristic*)attribute; - - if (characteristic->valueHandle() == handle) { - characteristic->setValue(_central, event_data->wr.data, event_data->wr.len); - break; - } else if (characteristic->cccdHandle() == handle) { - uint16_t cccdValue = 0; - - memcpy(&cccdValue, event_data->wr.data, event_data->wr.len); - - characteristic->setCccdValue(_central, cccdValue); - break; - } - } - } + BleStatus status = BLE_STATUS_SUCCESS; + + status = BLEPeripheralRole::instance()->stopAdvertising(); + return status; } + diff --git a/libraries/CurieBLE/src/BLEPeripheral.h b/libraries/CurieBLE/src/BLEPeripheral.h index 054af330..67b6f07b 100644 --- a/libraries/CurieBLE/src/BLEPeripheral.h +++ b/libraries/CurieBLE/src/BLEPeripheral.h @@ -22,28 +22,17 @@ #include "internal/ble_client.h" -#include "BLEAttribute.h" -#include "BLECentral.h" -#include "BLECharacteristic.h" #include "BLECommon.h" - -/** - * BLE Peripheral Events - */ -enum BLEPeripheralEvent { - BLEConnected = 0, - BLEDisconnected = 1, - - BLEPeripheralEventLast = 2 -}; +#include "BLERoleBase.h" +#include "BLEPeripheralHelper.h" /** Function prototype for BLE Peripheral Device event callback */ -typedef void (*BLEPeripheralEventHandler)(BLECentral ¢ral); +typedef void (*BLEPeripheralEventHandler)(BLECentralHelper ¢ral); /** * BLE Peripheral */ -class BLEPeripheral { +class BLEPeripheral{ public: /** * Default Constructor for BLE Peripheral Device @@ -55,23 +44,6 @@ class BLEPeripheral { */ virtual ~BLEPeripheral(void); - /** - * Return the number of bytes in the advertising block. - * Useful for debugging advertising problems. - * - * @note Call only after calling begin(). - */ - uint8_t getAdvertisingLength(); - - /** - * Returns a pointer to the advertising block - * of length getAdvertisingLength(). - * Useful for debugging advertising problems. - * - * @note Call only after calling begin(). - */ - uint8_t* getAdvertising(); - /** * Set the service UUID that the BLE Peripheral Device advertises * @@ -80,7 +52,7 @@ class BLEPeripheral { * * @note This method must be called before the begin method */ - void setAdvertisedServiceUuid(const char* advertisedServiceUuid); + void setAdvertisedServiceUuid(const struct bt_uuid* advertisedServiceUuid); /** * Set the local name that the BLE Peripheral Device advertises @@ -113,8 +85,23 @@ class BLEPeripheral { * the service data will silently not be copied * into the advertising block. */ - void setAdvertisedServiceData(const char* serviceDataUuid, uint8_t* serviceData, uint8_t serviceDataLength); - + void setAdvertisedServiceData(const struct bt_uuid* serviceDataUuid, + uint8_t* serviceData, + uint8_t serviceDataLength); + /** + * Set the ADV parameters about the ADV-Type and interval + * + * @param type Advertising types + * + * @param interval_min Minimum Advertising Interval (N * 0.625) + * + * @param interval_max Maximum Advertising Interval (N * 0.625) + * + * @note none + */ + void setAdvertisingParam(uint8_t type, + uint16_t interval_min, + uint16_t interval_max); /** * Set the device name for the BLE Peripheral Device * @@ -168,7 +155,7 @@ class BLEPeripheral { * @param event Event type for callback * @param callback Pointer to callback function to invoke when an event occurs. */ - void setEventHandler(BLEPeripheralEvent event, BLEPeripheralEventHandler callback); + void setEventHandler(BLERoleEvent event, BLERoleEventHandler callback); /** * Setup attributes and start advertising @@ -199,7 +186,7 @@ class BLEPeripheral { * * @return BleStatus indicating success or error */ - BLECentral central(void); + BLECentralHelper central(void); /** * Is a central connected? @@ -207,52 +194,58 @@ class BLEPeripheral { * @return boolean_t true if central connected, otherwise false */ bool connected(void); - + + /** + * @brief Init the ADV data and start send advertisement + * + * @param none + * + * @return BleStatus 0 - Success. Others - error code + * + * @note none + */ + BleStatus startAdvertising(void); + + /** + * @brief Stop send advertisement + * + * @param none + * + * @return BleStatus 0 - Success. Others - error code + * + * @note none + */ + BleStatus stopAdvertising(void); + protected: - friend void blePeripheralGapEventHandler(ble_client_gap_event_t event, struct ble_gap_event *event_data, void *param); - friend void blePeripheralGattsEventHandler(ble_client_gatts_event_t event, struct ble_gatts_evt_msg *event_data, void *param); - - void handleGapEvent(ble_client_gap_event_t event, struct ble_gap_event *event_data); - void handleGattsEvent(ble_client_gatts_event_t event, struct ble_gatts_evt_msg *event_data); + void handleConnectEvent(struct bt_conn *conn, uint8_t err); + void handleDisconnectEvent(struct bt_conn *conn, uint8_t reason); + void handleParamUpdated(struct bt_conn *conn, + uint16_t interval, + uint16_t latency, + uint16_t timeout); private: - BleStatus _init(void); - BleStatus _startAdvertising(void); + BleStatus _stop(void); - void _advDataInit(void); + BleStatus _advDataInit(void); private: - - enum BLEPeripheralState { - BLE_PERIPH_STATE_NOT_READY = 0, - BLE_PERIPH_STATE_READY, - BLE_PERIPH_STATE_ADVERTISING, - BLE_PERIPH_STATE_CONNECTED, - }; - - BLEPeripheralState _state; - - const char* _advertise_service_uuid; const char* _local_name; - const char* _service_data_uuid; + + const struct bt_uuid* _service_data_uuid; uint8_t* _service_data; - uint8_t _service_data_length; - char _device_name[BLE_MAX_DEVICE_NAME+1]; + uint8_t _service_data_length; + uint8_t _service_data_buf[BLE_MAX_ADV_SIZE]; + uint16_t _appearance; - uint16_t _min_conn_interval; - uint16_t _max_conn_interval; - uint8_t _adv_data[BLE_MAX_ADV_SIZE]; - uint8_t _adv_data_len; - ble_addr_t _local_bda; - BLECentral _central; - - BLEPeripheralEventHandler _event_handlers[BLEPeripheralEventLast]; - - BLEAttribute** _attributes; - uint16_t _num_attributes; - - BLECharacteristic* _last_added_characteritic; + + const struct bt_uuid* _advertise_service_uuid; + + uint8_t _adv_type; + struct bt_data _adv_data[4]; + size_t _adv_data_idx; }; #endif // _BLE_DEVICE_H_INCLUDED diff --git a/libraries/CurieBLE/src/BLEPeripheralHelper.cpp b/libraries/CurieBLE/src/BLEPeripheralHelper.cpp new file mode 100644 index 00000000..65d54c3d --- /dev/null +++ b/libraries/CurieBLE/src/BLEPeripheralHelper.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "BLEPeripheralHelper.h" + +BLEAttribute *BLEPeripheralHelper::attribute(uint16_t handle) +{ + return _profile.attribute(handle); +} + +BLEAttribute *BLEPeripheralHelper::attribute(struct bt_gatt_subscribe_params *params) +{ + return _profile.attribute(params); +} + +void BLEPeripheralHelper::discover(const struct bt_gatt_attr *attr) +{ + // Not allow to call the discover + if (NULL == _central) + { + return; + } + _profile.discover(attr); +} + +void BLEPeripheralHelper::discover() +{ + if (NULL == _central) + { + return; + } + _profile.discover(); +} + +BLEPeripheralHelper::BLEPeripheralHelper(BLECentralRole* central): + _profile(this), + _central(central) +{ + ; +} +BLEPeripheralHelper::~BLEPeripheralHelper() +{ + +} + +bool BLEPeripheralHelper::disconnect(void) +{ + int err = 0; + struct bt_conn* conn = bt_conn_lookup_addr_le(this->bt_le_address()); + if (NULL == conn) + { + return false; + } + + err = bt_conn_disconnect (conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + bt_conn_unref(conn); + return (err == 0); +} + +bool BLEPeripheralHelper::connected(void) +{ + struct bt_conn* conn = bt_conn_lookup_addr_le(this->bt_le_address()); + if (NULL == conn) + { + return false; + } + bt_conn_unref(conn); + return true; +} + +void BLEPeripheralHelper::linkLost(void) +{ + clearAddress(); + if (NULL != _central) + { + // Only central role need to do + _profile.clearHandles(); + } +} + +void BLEPeripheralHelper::addAttribute(BLEAttribute& attribute) +{ + _profile.addAttribute(attribute); +} + +int BLEPeripheralHelper::registerProfile() +{ + return _profile.registerProfile(); +} + +uint16_t BLEPeripheralHelper::valueHandle(BLEAttribute *attr) +{ + return _profile.valueHandle(attr); +} + +uint16_t BLEPeripheralHelper::cccdHandle(BLEAttribute *attr) +{ + return _profile.cccdHandle(attr); +} + + diff --git a/libraries/CurieBLE/src/BLEPeripheralHelper.h b/libraries/CurieBLE/src/BLEPeripheralHelper.h new file mode 100644 index 00000000..2d29a210 --- /dev/null +++ b/libraries/CurieBLE/src/BLEPeripheralHelper.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef _BLE_PERIPHERAL_HELPER_H_ +#define _BLE_PERIPHERAL_HELPER_H_ + +#include "BLECommon.h" +#include "BLEHelper.h" +#include "BLEProfile.h" + +class BLEAttribute; +class BLECentralRole; + +class BLEPeripheralHelper : public BLEHelper { + friend class BLECentralRole; + friend class BLEPeripheralRole; + public: + /** + * Is the Central connected + * + * @return boolean_t true if the central is connected, otherwise false + */ + bool connected(void); + + /** + * Disconnect the central if it is connected + * + */ + bool disconnect(void); + + /** + * Add an attribute to the BLE Peripheral helper + * + * @param attribute Attribute to add to Peripheral + * + * @note This method must be called before the begin method + */ + void addAttribute(BLEAttribute& attribute); + + BLEAttribute *attribute(struct bt_gatt_subscribe_params *params); + BLEAttribute *attribute(uint16_t handle); + + /** + * For central to discover the profile + */ + void discover(); + void discover(const struct bt_gatt_attr *attr); + + // For peripheral to register the tree + int registerProfile(); + void linkLost(void); + + // Get value handle. + // 0 is invalid + uint16_t valueHandle(BLEAttribute *attr); + uint16_t cccdHandle(BLEAttribute *attr); + + protected: + BLEPeripheralHelper(BLECentralRole* central); + ~BLEPeripheralHelper(); + + private: + BLEProfile _profile; + BLECentralRole* _central; +}; + +#endif + diff --git a/libraries/CurieBLE/src/BLEPeripheralRole.cpp b/libraries/CurieBLE/src/BLEPeripheralRole.cpp new file mode 100644 index 00000000..dc13b566 --- /dev/null +++ b/libraries/CurieBLE/src/BLEPeripheralRole.cpp @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2015 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "BLEPeripheralRole.h" + +#include "BLECharacteristic.h" +#include "BLEDescriptor.h" +#include "BLEService.h" + +BLEPeripheralRole* BLEPeripheralRole::_ins = NULL; + +BLEPeripheralRole* BLEPeripheralRole::instance() +{ + if (NULL == _ins) + { + _ins = new BLEPeripheralRole(); + } + return _ins; +} + +BLEPeripheralRole::BLEPeripheralRole(void) : + _state(BLE_PERIPH_STATE_NOT_READY), + _min_conn_interval(DEFAULT_MIN_CONN_INTERVAL), + _max_conn_interval(DEFAULT_MAX_CONN_INTERVAL), + _peripheral(NULL), + _central(this) +{ + memset(_event_handlers, 0x00, sizeof(_event_handlers)); + _peripheral.setAddress(_local_bda); +} + +BLEPeripheralRole::~BLEPeripheralRole(void) +{ +} + +bool BLEPeripheralRole::begin() +{ + BleStatus status; + + if (BLE_PERIPH_STATE_NOT_READY != _state) + return BLE_STATUS_WRONG_STATE; + + status = _init(); + if (status != BLE_STATUS_SUCCESS) { + return false; + } + _state = BLE_PERIPH_STATE_READY; + + // Set device name + setDeviceName(); + // Register profile + _peripheral.registerProfile(); + delay(2); // Temp solution for send data fast will makes ADV data set failed + return true; +} + +void +BLEPeripheralRole::poll() +{ + // no-op for now + delay(1); +} + +void +BLEPeripheralRole::setDeviceName(const char deviceName[]) +{ + memset(_device_name, 0, sizeof(_device_name)); + if (deviceName && deviceName[0]) { + int len = strlen(deviceName); + if (len > BLE_MAX_DEVICE_NAME) + len = BLE_MAX_DEVICE_NAME; + memcpy(_device_name, deviceName, len); + setDeviceName(); + } +} + +void +BLEPeripheralRole::setDeviceName() +{ + int len = strlen(_device_name); + bt_le_set_device_name(_device_name, len); +} + +void +BLEPeripheralRole::setConnectionInterval(const unsigned short minConnInterval, const unsigned short maxConnInterval) +{ + _min_conn_interval = minConnInterval; + _max_conn_interval = maxConnInterval; + + if (_min_conn_interval < MIN_CONN_INTERVAL) { + _min_conn_interval = MIN_CONN_INTERVAL; + } else if (_min_conn_interval > MAX_CONN_INTERVAL) { + _min_conn_interval = MAX_CONN_INTERVAL; + } + + if (_max_conn_interval < _min_conn_interval) { + _max_conn_interval = _min_conn_interval; + } else if (_max_conn_interval > MAX_CONN_INTERVAL) { + _max_conn_interval = MAX_CONN_INTERVAL; + } +} + +void +BLEPeripheralRole::setEventHandler(BLERoleEvent event, BLERoleEventHandler callback) +{ + if (event < sizeof(_event_handlers)) { + _event_handlers[event] = callback; + } +} + +bool +BLEPeripheralRole::disconnect() +{ + BleStatus status = BLE_STATUS_WRONG_STATE; + + if (BLE_PERIPH_STATE_CONNECTED == _state) + { + struct bt_conn *central_conn = bt_conn_lookup_addr_le(_central.bt_le_address()); + if (NULL != central_conn) + { + status = bt_conn_disconnect (central_conn, + BT_HCI_ERR_REMOTE_USER_TERM_CONN); + bt_conn_unref(central_conn); + } + } + return (status == BLE_STATUS_SUCCESS); +} + +BLECentralHelper +BLEPeripheralRole::central() +{ + poll(); + + return _central; +} + +bool +BLEPeripheralRole::connected() +{ + poll(); + + return _central; +} + +void BLEPeripheralRole::addAttribute(BLEAttribute& attribute) +{ + _peripheral.addAttribute(attribute); +} + +BleStatus +BLEPeripheralRole::stopAdvertising() +{ + int err_code = 0; + BleStatus status = BLE_STATUS_WRONG_STATE; + + if (BLE_PERIPH_STATE_ADVERTISING == _state) + { + err_code = bt_le_adv_stop(); + status = errorno_to_ble_status(err_code); + } + + if (BLE_STATUS_SUCCESS != status) + return status; + + _state = BLE_PERIPH_STATE_READY; + return BLE_STATUS_SUCCESS; +} + +BleStatus +BLEPeripheralRole::startAdvertising(const struct bt_data *ad, + size_t ad_len, + const struct bt_data *sd, + size_t sd_len) +{ + int ret; + + pr_info(LOG_MODULE_BLE, "%s-ad_len%d", __FUNCTION__, ad_len); + if (_state != BLE_PERIPH_STATE_READY) + return BLE_STATUS_WRONG_STATE; + + ret = bt_le_adv_start(&_adv_param, ad, ad_len, sd, sd_len); + if (0 != ret) + { + pr_error(LOG_MODULE_APP, "[ADV] Start failed. Error: %d", ret); + return BLE_STATUS_WRONG_STATE; + } + _state = BLE_PERIPH_STATE_ADVERTISING; + return BLE_STATUS_SUCCESS; +} + +void BLEPeripheralRole::setAdvertisingParam(uint8_t type, + uint16_t interval_min, + uint16_t interval_max) +{ + _adv_param.addr_type = _local_bda.type; + _adv_param.type = type; + _adv_param.interval_min = interval_min; + _adv_param.interval_max = interval_max; +} + +BleStatus +BLEPeripheralRole::stop(void) +{ + int err_code; + BleStatus status; + + if (BLE_PERIPH_STATE_ADVERTISING == _state) + { + err_code = bt_le_adv_stop(); + status = errorno_to_ble_status(err_code); + } + else + status = disconnect(); + + if (BLE_STATUS_SUCCESS != status) + return status; + + _state = BLE_PERIPH_STATE_READY; + return BLE_STATUS_SUCCESS; +} + +void BLEPeripheralRole::handleConnectEvent(struct bt_conn *conn, uint8_t err) +{ + // Update the central address + const bt_addr_le_t *central_addr = bt_conn_get_dst(conn); + _central.setAddress(*central_addr); + + pr_info(LOG_MODULE_BLE, "Connected: %d", err); + // Call the CB + if (_event_handlers[BLEConnected]) + _event_handlers[BLEConnected](_central); +} + + +void BLEPeripheralRole::handleDisconnectEvent(struct bt_conn *conn, uint8_t reason) +{ + struct bt_conn *central_conn = bt_conn_lookup_addr_le(_central.bt_le_address()); + if (conn == central_conn) + { + pr_info(LOG_MODULE_BLE, "Peripheral Disconnect reason: %d", reason); + if (_event_handlers[BLEDisconnected]) + _event_handlers[BLEDisconnected](_central); + } + _central.clearAddress(); + if (NULL != central_conn) + { + bt_conn_unref(central_conn); + } +} + +void BLEPeripheralRole::handleParamUpdated(struct bt_conn *conn, + uint16_t interval, + uint16_t latency, + uint16_t timeout) +{ + pr_info(LOG_MODULE_BLE, "Parameter updated\r\n\tConn: %p\r\n\tinterval: %d\r\n\tlatency: %d\r\n\ttimeout: %d", + conn, interval, latency, timeout); + if (_event_handlers[BLEUpdateParam]) + _event_handlers[BLEUpdateParam](_central); +} + + diff --git a/libraries/CurieBLE/src/BLEPeripheralRole.h b/libraries/CurieBLE/src/BLEPeripheralRole.h new file mode 100644 index 00000000..0fcbd40e --- /dev/null +++ b/libraries/CurieBLE/src/BLEPeripheralRole.h @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2015 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef _BLE_PERIPHERALROLE_H_INCLUDED +#define _BLE_PERIPHERALROLE_H_INCLUDED + +#include "internal/ble_client.h" + +#include "BLECommon.h" +#include "BLERoleBase.h" +#include "BLEPeripheralHelper.h" + +/** + * BLE Peripheral Role + */ +class BLEPeripheralRole: public BLERoleBase{ +public: + /** + * Default Constructor for BLE Peripheral Device + */ + BLEPeripheralRole(void); + + /** + * Destructor for BLE Peripheral Device + */ + virtual ~BLEPeripheralRole(void); + + /** + * Set the device name for the BLE Peripheral Device + * + * If device name is not set, a default name will be used instead + * + * @param deviceName User-defined name string for this device. Truncated if + * more than maximum allowed string length (20 bytes). + * + * @note This method must be called before the begin method + */ + void setDeviceName(const char *deviceName); + + /** + * Set the min and max connection interval BLE Peripheral Device + * + * @param minConnInterval Minimum connection interval (1.25 ms units), minimum 0x0006 (7.5ms) + * @param maxConnInterval Maximum connection interval (1.25 ms units), maximum 0x095f (2998.75ms) + * + * @note This method must be called before the begin method + */ + void setConnectionInterval(const unsigned short minConnInterval, const unsigned short maxConnInterval); + + /** + * Add an attribute to the BLE Peripheral Device + * + * @param attribute Attribute to add to Peripheral + * + * @return BleStatus indicating success or error + * + * @note This method must be called before the begin method + */ + void addAttribute(BLEAttribute& attribute); + + /** + * Provide a function to be called when events related to this Device are raised + * + * @param event Event type for callback + * @param callback Pointer to callback function to invoke when an event occurs. + */ + void setEventHandler(BLERoleEvent event, BLERoleEventHandler callback); + + /** + * Setup attributes and start advertising + * + * @return bool indicating success or error + */ + bool begin(void); + + /** + * Poll the peripheral for events + */ + void poll(void); + + /** + * Stop advertising and disconnect a central if connected + */ + BleStatus stop(void); + + /** + * Disconnect the central connected if there is one connected + * + * @return bool indicating success or error + */ + bool disconnect(void); + + /** + * Setup attributes and start advertising + * + * @return BleStatus indicating success or error + */ + BLECentralHelper central(void); + + /** + * Is a central connected? + * + * @return boolean_t true if central connected, otherwise false + */ + bool connected(void); + + /** + * @brief Start peripheral advertising + * + * @param ad The ADV data array + * + * @param ad_len The ADV data array length + * + * @param sd The Scan response data array + * + * @param sd_len The Scan response data array length + * + * @return BleStatus + * + * @note none + */ + BleStatus startAdvertising(const struct bt_data *ad, + size_t ad_len, + const struct bt_data *sd, + size_t sd_len); + + /** + * @brief Stop send advertisement + * + * @param none + * + * @return none + * + * @note none + */ + BleStatus stopAdvertising(); + + /** + * @brief Set advertising parameter + * + * @param type Advertising type + * + * @param interval_min Minimum Advertising Interval (N * 0.625) + * + * @param interval_max Maximum Advertising Interval (N * 0.625) + * + * @return none + * + * @note none + */ + void setAdvertisingParam(uint8_t type, + uint16_t interval_min, + uint16_t interval_max); + + /** + * @brief Get BLE Peripheral instance. + * + * @param none + * + * @return BLEPeripheralRole* The BLE perpheral instance + * + * @note Singleton. Only have one object to communicate with + * stack and manage the device + */ + static BLEPeripheralRole* instance(); + +protected: + /** + * @brief Handle the connected event + * + * @param conn The object that established the connection + * + * @param err The code of the process + * + * @return none + * + * @note none + */ + void handleConnectEvent(struct bt_conn *conn, uint8_t err); + + /** + * @brief Handle the disconnected event + * + * @param conn The object that lost the connection + * + * @param reason The link lost reason + * + * @return none + * + * @note none + */ + void handleDisconnectEvent(struct bt_conn *conn, uint8_t reason); + + /** + * @brief Handle the conntion update request + * + * @param conn The connection object that need to process the update request + * + * @param interval The connection interval + * + * @param latency The connection latency + * + * @param timeout The connection timeout + * + * @return none + * + * @note none + */ + void handleParamUpdated(struct bt_conn *conn, + uint16_t interval, + uint16_t latency, + uint16_t timeout); + +private: + + /** + * Set the device name to Nordic BLE's profile + * + * @param none + * + * @note none + */ + void setDeviceName(); + + enum BLEPeripheralState { + BLE_PERIPH_STATE_NOT_READY = 0, + BLE_PERIPH_STATE_READY, + BLE_PERIPH_STATE_ADVERTISING, + BLE_PERIPH_STATE_CONNECTED, + }; + + BLEPeripheralState _state; + + uint16_t _min_conn_interval; + uint16_t _max_conn_interval; + + struct bt_le_adv_param _adv_param; + + BLEPeripheralHelper _peripheral; + BLECentralHelper _central; + + BLERoleEventHandler _event_handlers[BLERoleEventLast]; + static BLEPeripheralRole *_ins; +}; + +#endif // _BLE_DEVICE_H_INCLUDED diff --git a/libraries/CurieBLE/src/BLEProfile.cpp b/libraries/CurieBLE/src/BLEProfile.cpp new file mode 100644 index 00000000..186bf4fa --- /dev/null +++ b/libraries/CurieBLE/src/BLEProfile.cpp @@ -0,0 +1,535 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include "BLEProfile.h" +#include "BLEPeripheral.h" +#include "BLECentralRole.h" +#include "BLEPeripheralRole.h" + +// Only for peripheral +ssize_t profile_read_process(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + void *buf, uint16_t len, + uint16_t offset) +{ + const unsigned char *pvalue; + BLEAttribute *bleattr = (BLEAttribute *)attr->user_data; + BLECharacteristic* blecharacteritic; + BLEAttributeType type = bleattr->type(); + if (BLETypeCharacteristic != type) + { + return 0; + } + blecharacteritic = (BLECharacteristic*)bleattr; + pvalue = blecharacteritic->value(); + return bt_gatt_attr_read(conn, attr, buf, len, offset, pvalue, + blecharacteritic->valueLength()); +} + +// Only for peripheral +ssize_t profile_write_process(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + const void *buf, uint16_t len, + uint16_t offset) +{ + pr_info(LOG_MODULE_BLE, "%s1", __FUNCTION__); + BLEAttribute *bleattr = (BLEAttribute *)attr->user_data; + BLECharacteristic* blecharacteritic; + BLEAttributeType type = bleattr->type(); + BLECentralHelper central = BLEPeripheralRole::instance()->central(); + if ((BLETypeCharacteristic != type) || 0 != offset) + { + return 0; + } + + blecharacteritic = (BLECharacteristic*)bleattr; + blecharacteritic->setValue(*((BLEHelper *)¢ral), (const uint8_t *) buf, len); + + return len; +} + + +// Only for central +uint8_t profile_notify_process (struct bt_conn *conn, + struct bt_gatt_subscribe_params *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 + BLECharacteristic *chrc = (BLECharacteristic *)notifyatt; + + //assert(notifyatt->type() == BLETypeCharacteristic); + pr_debug(LOG_MODULE_APP, "%s1", __FUNCTION__); + chrc->setValue(*((BLEHelper *)peripheral),(const unsigned char *)data, length); + return BT_GATT_ITER_CONTINUE; +} + +// Only for central +uint8_t profile_discover_process(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + struct bt_gatt_discover_params *params) +{ + BLEPeripheralHelper* peripheral = BLECentralRole::instance()->peripheral(conn);// Find peripheral by bt_conn + peripheral->discover(attr); + return BT_GATT_ITER_STOP; +} + +// Only for central +uint8_t profile_read_rsp_process(struct bt_conn *conn, int err, + struct bt_gatt_read_params *params, + const void *data, + uint16_t length) +{ + if (NULL == data) + { + return BT_GATT_ITER_STOP; + } + BLEPeripheralHelper* peripheral = BLECentralRole::instance()->peripheral(conn);// Find peripheral by bt_conn + BLEAttribute* readatt = peripheral->attribute(params->single.handle); + BLECharacteristic *chrc = (BLECharacteristic *)readatt; + + //assert(readatt->type() == BLETypeCharacteristic); + chrc->setValue(*((BLEHelper *)peripheral), (const unsigned char *)data, length); + return BT_GATT_ITER_STOP; +} + +BLEProfile::BLEProfile (BLEPeripheralHelper *peripheral): + _attr_base(NULL), + _attr_index(0), + _attributes(NULL), + _num_attributes(0), + _sub_param(NULL), + _sub_param_idx(0) +{ + _peripheral = peripheral; + memset(&_discover_params, 0, sizeof(_discover_params)); + _discover_params.end_handle = 0xFFFF; + _discover_params.start_handle = 0x0001; + _discover_params.func = profile_discover_process; +} + +BLEProfile::~BLEProfile (void) +{ + if (this->_attributes) { + free(this->_attributes); + } + if (this->_attr_base) + { + free(this->_attr_base); + } + if (this->_sub_param) + { + free(this->_sub_param); + } +} + +void BLEProfile::addAttribute (BLEAttribute& attribute) +{ + struct bt_gatt_attr *start; + if (NULL == _attributes) + { + _attributes = (BLEAttribute**)malloc(BLEAttribute::numAttributes() * sizeof(BLEAttribute*)); + memset(_attributes, 0x00, BLEAttribute::numAttributes() * sizeof(BLEAttribute*)); + } + if (NULL == _attr_base) + { + _attr_base = (struct bt_gatt_attr *)malloc((BLEAttribute::numAttributes() + BLECharacteristic::numNotifyAttributes()) * sizeof(struct bt_gatt_attr)); + memset(_attr_base, 0x00, ((BLEAttribute::numAttributes() + BLECharacteristic::numNotifyAttributes()) * sizeof(struct bt_gatt_attr))); + pr_info(LOG_MODULE_BLE, "_attr_base_-%p, size-%d", _attr_base, sizeof(_attr_base)); + } + if (NULL == _sub_param) + { + _sub_param = (struct bt_gatt_subscribe_params *)malloc((BLECharacteristic::numNotifyAttributes()) * sizeof(struct bt_gatt_subscribe_params)); + memset(_sub_param, 0x00, ((BLECharacteristic::numNotifyAttributes()) * sizeof(struct bt_gatt_subscribe_params))); + } + + _attributes[_num_attributes] = &attribute; + _num_attributes++; + start = _attr_base + _attr_index; + pr_info(LOG_MODULE_BLE, "_attr_base_-%p", _attr_base); + + BLEAttributeType type = attribute.type(); + pr_info(LOG_MODULE_BLE, "%s: idx-%d, %p, %d", __FUNCTION__,_num_attributes, &attribute ,attribute.uuid()->type); + + + if (BLETypeCharacteristic == type) + { + BLECharacteristic* characteritic = (BLECharacteristic*) &attribute; + + // Characteristic + memset(start, 0, sizeof(struct bt_gatt_attr)); + start->uuid = BLECharacteristic::getCharacteristicAttributeUuid(); + start->perm = BT_GATT_PERM_READ; + start->read = bt_gatt_attr_read_chrc; + start->user_data = characteritic->getCharacteristicAttValue(); + characteritic->addCharacteristicDeclaration(start); + pr_info(LOG_MODULE_BLE, "chrc-%p, uuid type-%d", start, start->uuid->type); + start++; + _attr_index++; + + // Descriptor + memset(start, 0, sizeof(struct bt_gatt_attr)); + start->uuid = characteritic->uuid(); + start->perm = characteritic->getPermission(); + start->read = profile_read_process; + start->write = profile_write_process; + start->user_data = (void*)&attribute; + characteritic->addCharacteristicValue(start); + pr_info(LOG_MODULE_BLE, "desc-%p, uuid: 0x%x", start, ((struct bt_uuid_16*) start->uuid)->val); + + start++; + _attr_index++; + // CCCD + if (characteritic->subscribed()) + { + pr_info(LOG_MODULE_BLE, "cccd-%p", start); + // Descriptor + memset(start, 0, sizeof(struct bt_gatt_attr)); + start->uuid = characteritic->getClientCharacteristicConfigUuid(); + start->perm = BT_GATT_PERM_READ | BT_GATT_PERM_WRITE; + start->read = bt_gatt_attr_read_ccc; + start->write = bt_gatt_attr_write_ccc; + start->user_data = characteritic->getCccCfg(); + characteritic->addCharacteristicConfigDescriptor(start); + + start++; + _attr_index++; + } + } + else if (BLETypeService == type) + { + pr_info(LOG_MODULE_BLE, "service-%p", start); + start->uuid = BLEService::getPrimayUuid(); + start->perm = BT_GATT_PERM_READ; + start->read = bt_gatt_attr_read_service; + start->user_data = attribute.uuid(); + start++; + _attr_index++; + } + +} + +int BLEProfile::registerProfile() +{ + int ret = 0; + + // Start debug + int i; + + for (i = 0; i < _attr_index; i++) { + { + 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); + } + } + + delay(1000); + // End for debug + + ret = bt_gatt_register(_attr_base, + _attr_index); + pr_info(LOG_MODULE_APP, "%s: ret, %d", __FUNCTION__, ret); + + return ret; +} + +void BLEProfile::discover(const struct bt_gatt_attr *attr) +{ + BLEAttribute* attribute = NULL; + int err; + int i; + bool send_discover = false; + + for (i = 0; i < _num_attributes; i++) + { + attribute = _attributes[i]; + if (attribute->discovering()) + { + if (NULL != attr) + { + // Discover success + switch (_discover_params.type) + { + case BT_GATT_DISCOVER_CHARACTERISTIC: + { + struct bt_gatt_attr *attr_dec = declarationAttr(attribute); + attr_dec++; + attr_dec->handle = attr->handle + 1; + break; + } + case BT_GATT_DISCOVER_DESCRIPTOR: + { + BLECharacteristic *chrc = (BLECharacteristic *)attribute; + struct bt_gatt_attr *attr_dec = declarationAttr(attribute); + struct bt_gatt_attr *attr_chrc = attr_dec + 1; + struct bt_gatt_attr *attr_cccd = attr_dec + 2; + struct bt_gatt_subscribe_params *sub_param_tmp = chrc->getSubscribeParams(); + struct bt_gatt_subscribe_params *sub_param = _sub_param + _sub_param_idx; + struct bt_conn *conn = bt_conn_lookup_addr_le(_peripheral->bt_le_address()); + if (NULL == conn) + { + // Link lost + return; + } + + _sub_param_idx++; + attr_cccd->handle = attr->handle; + memcpy(sub_param, sub_param_tmp, sizeof(struct bt_gatt_subscribe_params)); + sub_param->ccc_handle = attr_cccd->handle; + sub_param->value_handle = attr_chrc->handle; + + // Enable CCCD to allow peripheral send Notification/Indication + err = bt_gatt_subscribe(conn, sub_param); + bt_conn_unref(conn); + if (err && err != -EALREADY) + { + pr_debug(LOG_MODULE_APP, "Subscribe failed (err %d)\n", err); + } + break; + } + case BT_GATT_DISCOVER_PRIMARY: + default: + { + // Do nothing + break; + } + } + } + attribute->discover(attr, &_discover_params); + break; + } + } + + // Send discover + if (attribute->discovering()) + { + send_discover = true; + } + else + { + // Current attribute complete discovery + // Find next attribute to discover + i++; + if (i < _num_attributes) + { + attribute = _attributes[i]; + attribute->discover(&_discover_params); + send_discover = true; + } + } + + if (send_discover) + { + struct bt_conn *conn = bt_conn_lookup_addr_le(_peripheral->bt_le_address()); + + if (NULL == conn) + { + // Link lost + pr_debug(LOG_MODULE_APP, "Can't find connection\n"); + return; + } + err = bt_gatt_discover(conn, &_discover_params); + bt_conn_unref(conn); + if (err) + { + pr_debug(LOG_MODULE_APP, "Discover failed(err %d)\n", err); + return; + } + } +} + + +void BLEProfile::discover() +{ + int err; + BLEService *serviceattr = (BLEService *)_attributes[0]; + struct bt_conn *conn = bt_conn_lookup_addr_le(_peripheral->bt_le_address()); + + if (NULL == conn) + { + // Link lost + pr_debug(LOG_MODULE_APP, "Can't find connection\n"); + return; + } + + // Reset start handle + _discover_params.start_handle = 0x0001; + serviceattr->discover(&_discover_params); + + err = bt_gatt_discover(conn, &_discover_params); + bt_conn_unref(conn); + if (err) + { + pr_debug(LOG_MODULE_APP, "Discover failed(err %d)\n", err); + return; + } +} + +BLEAttribute *BLEProfile::attribute(struct bt_gatt_subscribe_params *params) +{ + return attribute(params->value_handle); +} + +BLEAttribute *BLEProfile::attribute(const struct bt_uuid* uuid) +{ + int i; + BLEAttribute *attr_tmp = NULL; + BLECharacteristic *chrc_tmp = NULL; + bool att_found = false; + + for (i = 0; i < _num_attributes; i++) + { + attr_tmp = _attributes[i]; + if ((NULL == attr_tmp) || (attr_tmp->type() != BLETypeCharacteristic)) + { + continue; + } + chrc_tmp = (BLECharacteristic *)attr_tmp; + if (chrc_tmp->uuid() == uuid); + { + att_found = true; + break; + } + } + + if (false == att_found) + { + pr_debug(LOG_MODULE_APP, "Attributes not found"); + // Didn't found the characteristic + chrc_tmp = NULL; + } + return chrc_tmp; +} + + +BLEAttribute *BLEProfile::attribute(uint16_t handle) +{ + int i; + struct bt_gatt_attr *attr_gatt = NULL; + for (i = 0; i < _attr_index; i++) + { + attr_gatt = _attr_base + i; + if (handle == attr_gatt->handle) + { + break; + } + } + + if (i < _attr_index && i > 1) + { + // Found the GATT ATTR + // Serach the attribute + // Characteristic Declaration + // Characteristic Descriptor + // CCCD + attr_gatt--; + if (attr_gatt->uuid == BLECharacteristic::getCharacteristicAttributeUuid()) + { + attr_gatt++; + } + else + { + attr_gatt--; + if (attr_gatt->uuid == BLECharacteristic::getCharacteristicAttributeUuid()) + { + attr_gatt++; + } + else + { + attr_gatt = NULL; + } + } + } + else + { + attr_gatt = NULL; + } + + if (NULL != attr_gatt) + { + return attribute(attr_gatt->uuid); + } + return NULL; +} + + +void BLEProfile::clearHandles(void) +{ + int i; + struct bt_gatt_attr *attr = NULL; + // Didn't need to unsubscribe + // The stack will unsubscribe the notify when disconnected. + // The sub_param has some pointer. So can't call memset. Just reset the index. + _sub_param_idx = 0; + + for (i = 0; i < _attr_index; i++) + { + // Clear the handle + attr = _attr_base + i; + attr->handle = 0; + } +} + +struct bt_gatt_attr* BLEProfile::declarationAttr(BLEAttribute *attr) +{ + int i; + struct bt_gatt_attr *attr_gatt = NULL; + + for (i = 0; i < _attr_index; i++) + { + // Clear the handle + attr_gatt = _attr_base + i; + if (attr->uuid() == attr_gatt->uuid) + { + attr_gatt--; + return attr_gatt; + } + } + return NULL; +} + +uint16_t BLEProfile::valueHandle(BLEAttribute *attr) +{ + uint16_t handle = 0; + struct bt_gatt_attr *attr_gatt = declarationAttr(attr); + attr_gatt++; + if (attr_gatt->uuid == attr->uuid()) + { + handle = attr_gatt->handle; + } + return handle; +} + +uint16_t BLEProfile::cccdHandle(BLEAttribute *attr) +{ + uint16_t handle = 0; + struct bt_gatt_attr *attr_gatt = declarationAttr(attr); + attr_gatt+= 2; + if (attr_gatt->uuid == BLECharacteristic::getClientCharacteristicConfigUuid()) + { + handle = attr_gatt->handle; + } + return handle; +} + + + diff --git a/libraries/CurieBLE/src/BLEProfile.h b/libraries/CurieBLE/src/BLEProfile.h new file mode 100644 index 00000000..33b06c75 --- /dev/null +++ b/libraries/CurieBLE/src/BLEProfile.h @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __BLE_PROFILE_H__ +#define __BLE_PROFILE_H__ + +#include "BLECommon.h" +#include "BLEAttribute.h" +#include "BLECentralHelper.h" +#include "BLECharacteristic.h" +#include "BLEService.h" + +class BLEProfile{ +public: + BLEProfile(BLEPeripheralHelper *peripheral); + ~BLEProfile (void); + + /** + * @brief Add an attribute to the BLE Peripheral Device + * + * @param attribute Attribute to add to Peripheral + * + * @return BleStatus indicating success or error + * + * @note This method must be called before the begin method + */ + void addAttribute(BLEAttribute& attribute); + + /** + * @brief Register the profile to Nordic BLE stack + * + * @param none + * + * @return int std C errno + * + * @note none + */ + int registerProfile(); + + /** + * @brief Get BLEAttribute by subscribe parameter + * + * @param struct bt_gatt_subscribe_params * Subscribe parameter + * + * @return BLEAttribute * NULL - Not found + * Not NULL - The BLEAttribute object + * + * @note none + */ + BLEAttribute *attribute(struct bt_gatt_subscribe_params *params); + + /** + * @brief Get BLEAttribute by characteristic handle + * + * @param uint16_t The characteristic handle + * + * @return BLEAttribute * NULL - Not found + * Not NULL - The BLEAttribute object + * + * @note none + */ + BLEAttribute *attribute(uint16_t handle); + + /** + * @brief Process the discover response and + * discover the BLE peripheral profile + * + * @param const struct bt_gatt_attr * The gatt attribute response + * + * @return none + * + * @note This function only for the central device. + */ + void discover(const struct bt_gatt_attr *attr); + + /** + * @brief Discover the BLE peripheral profile + * + * @param none + * + * @return none + * + * @note This function only for the central device. + * + * @note The central deivce didn't know the connected BLE's profile. + * Need send discover request to search the attribute in the BLE peripheral + */ + void discover(); + + /** + * @brief Clear the handle in central mode + * + * @param none + * + * @return none + * + * @note The peripheral can't call this. + * Because the central need discover the handles. + * Peripheral device only get the handle when register the profile. + */ + void clearHandles(void); + + /** + * @brief Get the characteristic value handle + * + * @param none + * + * @return uint16_t The value handle + * 0 is invalid handle + * + * @note none + */ + uint16_t valueHandle(BLEAttribute *attr); + + /** + * @brief Get characteristic configuration descriptor value handle + * + * @param none + * + * @return uint16_t The value handle + * 0 is invalid handle + * + * @note none + */ + uint16_t cccdHandle(BLEAttribute *attr); +protected: + friend ssize_t profile_write_process(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + const void *buf, uint16_t len, + uint16_t offset); +private: + /** + * @brief Get BLEAttribute by UUID + * + * @param const struct bt_uuid* The UUID + * + * @return BLEAttribute * NULL - Not found + * Not NULL - The BLEAttribute object + * + * @note Use the pointer value instead the UUID value. + * Because the uuid pointer in bt_gatt_attr is got from BLEAttribute + * So set this as private. + */ + BLEAttribute *attribute(const struct bt_uuid* uuid); + + /** + * @brief Get bt_gatt_attr by BLEAttribute class + * + * @param BLEAttribute * The BLEAttribute object + * + * @return struct bt_gatt_attr* NULL - Not found + * Not NULL - The bt_gatt_attr in the stack + * + * @note none + */ + struct bt_gatt_attr* declarationAttr(BLEAttribute *attr); + +private: + BLEPeripheralHelper *_peripheral; + struct bt_gatt_attr *_attr_base; + int _attr_index; + + BLEAttribute** _attributes; + uint16_t _num_attributes; + + struct bt_gatt_subscribe_params *_sub_param; + int _sub_param_idx; + + struct bt_gatt_discover_params _discover_params; +}; + +#endif + diff --git a/libraries/CurieBLE/src/BLERoleBase.cpp b/libraries/CurieBLE/src/BLERoleBase.cpp new file mode 100644 index 00000000..6ab9def5 --- /dev/null +++ b/libraries/CurieBLE/src/BLERoleBase.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "internal/ble_client.h" + +#include "BLERoleBase.h" + +void bleConnectEventHandler(struct bt_conn *conn, + uint8_t err, + void *param) +{ + BLERoleBase* p = (BLERoleBase*)param; + + p->handleConnectEvent(conn, err); +} + + +void bleDisconnectEventHandler(struct bt_conn *conn, + uint8_t reason, + void *param) +{ + BLERoleBase* p = (BLERoleBase*)param; + + pr_info(LOG_MODULE_BLE, "Connect lost. Reason: %d", reason); + + p->handleDisconnectEvent(conn, reason); +} + +void bleParamUpdatedEventHandler(struct bt_conn *conn, + uint16_t interval, + uint16_t latency, + uint16_t timeout, + void *param) +{ + BLERoleBase* p = (BLERoleBase*)param; + + p->handleParamUpdated(conn, interval, latency, timeout); +} + +uint8_t BLERoleBase::m_init_cnt = 0; + +void BLERoleBase::setTxPower (int8_t tx_power) +{ + ble_gap_set_tx_power(tx_power); +} + + +BleStatus +BLERoleBase::_init() +{ + // Curie may support multi-role at same time in future. + // Make sure the BLE only init once. + if (this->m_init_cnt == 0) + { + ble_client_init(bleConnectEventHandler, this, + bleDisconnectEventHandler, this, + bleParamUpdatedEventHandler, this); + } + this->m_init_cnt++; + + return BLE_STATUS_SUCCESS; +} + +BLERoleBase::BLERoleBase(): m_connected(false) +{ + memset (_event_handlers, 0x00, sizeof (_event_handlers)); + ble_client_get_factory_config(&_local_bda, _device_name); +} + + diff --git a/libraries/CurieBLE/src/BLERoleBase.h b/libraries/CurieBLE/src/BLERoleBase.h new file mode 100644 index 00000000..4db80c48 --- /dev/null +++ b/libraries/CurieBLE/src/BLERoleBase.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2016 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __BLEROLEBASE_H__ +#define __BLEROLEBASE_H__ + +#include "BLECommon.h" + +/** + * BLE Events + */ +enum BLERoleEvent { + BLEConnected = 0, + BLEDisconnected = 1, + BLEUpdateParam, + + BLERoleEventLast +}; + +class BLEHelper; + +typedef void (*BLERoleEventHandler)(BLEHelper &role); + + +class BLERoleBase{ +public: + virtual bool begin()=0; + virtual bool disconnect()=0; + BLERoleBase(); + + /** + * Is connected? + * + * @return boolean_t true if established connection, otherwise false + */ + bool connected (void) {return m_connected;} + + /** + * Set TX output power + * + * @param tx_power The antenna TX power + * + * @return boolean_t true if established connection, otherwise false + */ + void setTxPower (int8_t tx_power); +protected: + virtual BleStatus _init(void); + + friend void bleConnectEventHandler(struct bt_conn *conn, + uint8_t err, + void *param); + friend void bleDisconnectEventHandler(struct bt_conn *conn, + uint8_t reason, + void *param); + friend void bleParamUpdatedEventHandler(struct bt_conn *conn, + uint16_t interval, + uint16_t latency, + uint16_t timeout, + void *param); + + /** + * @brief Handle the connected event + * + * @param conn The object that established the connection + * + * @param err The code of the process + * + * @return none + * + * @note virtual function. Just define the interface and the children need to implement + */ + virtual void handleConnectEvent(struct bt_conn *conn, uint8_t err) = 0; + + /** + * @brief Handle the disconnected event + * + * @param conn The object that lost the connection + * + * @param reason The link lost reason + * + * @return none + * + * @note virtual function. Just define the interface and the children need to implement + */ + virtual void handleDisconnectEvent(struct bt_conn *conn, uint8_t reason) = 0; + + /** + * @brief Handle the conntion update request + * + * @param conn The connection object that need to process the update request + * + * @param interval The connection interval + * + * @param latency The connection latency + * + * @param timeout The connection timeout + * + * @return none + * + * @note virtual function. Just define the interface and the children need to implement + */ + virtual void handleParamUpdated (struct bt_conn *conn, + uint16_t interval, + uint16_t latency, + uint16_t timeout) = 0; + + char _device_name[BLE_MAX_DEVICE_NAME+1]; + bt_addr_le_t _local_bda; + BLERoleEventHandler _event_handlers[BLERoleEventLast]; + +private: + bool m_connected; + static uint8_t m_init_cnt; // Reserved for support multi-role at same time +}; + +#endif + diff --git a/libraries/CurieBLE/src/BLEService.cpp b/libraries/CurieBLE/src/BLEService.cpp index f7569e3b..2e25f161 100644 --- a/libraries/CurieBLE/src/BLEService.cpp +++ b/libraries/CurieBLE/src/BLEService.cpp @@ -20,21 +20,33 @@ #include "internal/ble_client.h" #include "BLEService.h" +struct bt_uuid_16 BLEService::_gatt_primary_uuid = {BT_UUID_TYPE_16, BT_UUID_GATT_PRIMARY_VAL}; +struct bt_uuid *BLEService::getPrimayUuid(void) +{ + return (struct bt_uuid *)&_gatt_primary_uuid; +} BLEService::BLEService(const char* uuid) : BLEAttribute(uuid, BLETypeService) { } -bool -BLEService::add() { - bt_uuid uuid = btUuid(); - uint16_t handle = 0; - BleStatus status = ble_client_gatts_add_service(&uuid, BLE_GATT_SVC_PRIMARY, &handle); - if (BLE_STATUS_SUCCESS == status) { - setHandle(handle); - } +void BLEService::discover(struct bt_gatt_discover_params *params) +{ + params->type = BT_GATT_DISCOVER_PRIMARY; + + params->uuid = this->uuid(); + // Start discovering + _discoverying = true; +} - return (BLE_STATUS_SUCCESS == status); +void BLEService::discover(const struct bt_gatt_attr *attr, + struct bt_gatt_discover_params *params) +{ + params->start_handle = attr->handle + 1; + + // Complete the discover + _discoverying = false; } + diff --git a/libraries/CurieBLE/src/BLEService.h b/libraries/CurieBLE/src/BLEService.h index 17311f72..2d4c4999 100644 --- a/libraries/CurieBLE/src/BLEService.h +++ b/libraries/CurieBLE/src/BLEService.h @@ -22,6 +22,10 @@ #include "BLEAttribute.h" #include "BLECommon.h" +#include "BLEProfile.h" + +class BLEPeripheral; +class BLEProfile; /** * BLE GATT Service @@ -37,8 +41,14 @@ class BLEService : public BLEAttribute { protected: friend BLEPeripheral; - - bool add(void); + friend BLEProfile; + void discover(const struct bt_gatt_attr *attr, + struct bt_gatt_discover_params *params); + void discover(struct bt_gatt_discover_params *params); + + static struct bt_uuid *getPrimayUuid(void); +private: + static bt_uuid_16 _gatt_primary_uuid; }; #endif // _BLE_SERVICE_H_INCLUDED diff --git a/libraries/CurieBLE/src/BLEUuid.cpp b/libraries/CurieBLE/src/BLEUuid.cpp deleted file mode 100644 index f0764383..00000000 --- a/libraries/CurieBLE/src/BLEUuid.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2015 Intel Corporation. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "BLEUuid.h" - -BLEUuid::BLEUuid(const char * str) -{ - char temp[] = {0, 0, 0}; - int strLength = strlen(str); - int length = 0; - - memset(&_uuid, 0x00, sizeof(_uuid)); - - for (int i = strLength - 1; i >= 0 && length < MAX_UUID_SIZE; i -= 2) { - if (str[i] == '-') { - i++; - continue; - } - - temp[0] = str[i - 1]; - temp[1] = str[i]; - - _uuid.uuid128[length] = strtoul(temp, NULL, 16); - - length++; - } - - if (length == 2) { - _uuid.type = BT_UUID16; - } else { - _uuid.type = BT_UUID128; - } -} - -bt_uuid BLEUuid::uuid() const -{ - return _uuid; -} diff --git a/libraries/CurieBLE/src/BLEUuid.h b/libraries/CurieBLE/src/BLEUuid.h deleted file mode 100644 index 39b8aff5..00000000 --- a/libraries/CurieBLE/src/BLEUuid.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2015 Intel Corporation. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifndef _BLE_UUID_H_INCLUDED -#define _BLE_UUID_H_INCLUDED - -#include "BLECommon.h" - -class BLEUuid -{ -public: - BLEUuid(const char * str); - - bt_uuid uuid(void) const; - -private: - struct bt_uuid _uuid; -}; - -#endif // _BLE_UUID_H_INCLUDED diff --git a/libraries/CurieBLE/src/CurieBLE.h b/libraries/CurieBLE/src/CurieBLE.h index fb51dd58..bc1be251 100644 --- a/libraries/CurieBLE/src/CurieBLE.h +++ b/libraries/CurieBLE/src/CurieBLE.h @@ -23,3 +23,5 @@ #include "BLEService.h" #include "BLEPeripheral.h" #include "BLETypedCharacteristics.h" + +#include "BLECentral.h" diff --git a/libraries/CurieBLE/src/internal/ble_client.c b/libraries/CurieBLE/src/internal/ble_client.c index a4f4cbc6..5731a75f 100644 --- a/libraries/CurieBLE/src/internal/ble_client.c +++ b/libraries/CurieBLE/src/internal/ble_client.c @@ -27,6 +27,8 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ + +#include #include #include "cfw/cfw.h" @@ -48,327 +50,71 @@ #include "ble_client.h" #include "platform.h" -/* Advertising parameters */ -#define BLE_GAP_ADV_TYPE_ADV_IND 0x00 /**< Connectable undirected. */ -#define BLE_GAP_ADV_FP_ANY 0x00 /**< Allow scan requests and connect requests from any device. */ -/** options see \ref BLE_ADV_OPTIONS */ -/* options: BLE_NO_ADV_OPT */ -#define APP_ULTRA_FAST_ADV_INTERVAL 32 -#define APP_ULTRA_FAST_ADV_TIMEOUT_IN_SECONDS 180 -/* options: BLE_SLOW_ADV */ -#define APP_DISC_ADV_INTERVAL 160 -#define APP_DISC_ADV_TIMEOUT_IN_SECONDS 180 -/* options: BLE_NON_DISC_ADV */ -#define APP_NON_DISC_ADV_FAST_INTERVAL 160 -#define APP_NON_DISC_ADV_FAST_TIMEOUT_IN_SECONDS 30 -/* options: BLE_SLOW_ADV | BLE_NON_DISC_ADV */ -#define APP_NON_DISC_ADV_SLOW_INTERVAL 2056 -#define APP_NON_DISC_ADV_SLOW_TIMEOUT_IN_SECONDS 0 +#include "infra/log.h" -struct cfw_msg_rsp_sync { - volatile unsigned response; - volatile ble_status_t status; - void *param; -}; - -#define TIMEOUT_TICKS_1SEC 32768 /* ~1 second in RTC timer ticks */ -#define TIMEOUT_TICKS_1MS 32 /* ~1 millisecond in RTC timer ticks */ -#define wait_for_condition(cond, status) \ -do { \ - unsigned timeout = get_uptime_32k() + TIMEOUT_TICKS_1SEC; \ - status = BLE_STATUS_SUCCESS; \ - while (!(cond)) { \ - if (get_uptime_32k() > timeout) { \ - status = BLE_STATUS_TIMEOUT; \ - break; \ - } \ - } \ -} while(0) - -static cfw_handle_t client_handle; -static svc_client_handle_t *service_handle; -static uint16_t conn_handle; -static bool connected; - -static ble_client_gap_event_cb_t ble_client_gap_event_cb; -static void *ble_client_gap_event_param; - -static ble_client_gatts_event_cb_t ble_client_gatts_event_cb; -static void *ble_client_gatts_event_param; - -volatile struct cfw_msg_rsp_sync sync; - - -static void handle_msg_id_cfw_svc_avail_evt(cfw_svc_available_evt_msg_t *evt, void *param) -{ - if (evt->service_id == BLE_CORE_SERVICE_ID) { - sync.status = BLE_STATUS_SUCCESS; - sync.response = 1; - } -} - -static void handle_msg_id_cfw_open_svc(cfw_open_conn_rsp_msg_t *rsp, void *param) -{ - service_handle = (svc_client_handle_t *)(rsp->client_handle); - - sync.status = BLE_STATUS_SUCCESS; - sync.response = 1; -} - -static void handle_msg_id_ble_gap_wr_conf_rsp(struct ble_rsp *rsp, void *param) -{ - sync.status = rsp->status; - sync.response = 1; -} - -static void handle_msg_id_ble_gap_rd_bda_rsp(ble_bda_rd_rsp_t *rsp, void *param) -{ - ble_addr_t *p_bda = (ble_addr_t *)sync.param; - - if (p_bda && BLE_STATUS_SUCCESS == rsp->status) - memcpy(p_bda, &rsp->bd, sizeof(*p_bda)); - - sync.status = rsp->status; - sync.response = 1; -} - -static void handle_msg_id_ble_gap_sm_config_rsp(struct ble_rsp *rsp, void *param) -{ - sync.status = rsp->status; - sync.response = 1; -} - -static void handle_msg_id_ble_gap_wr_adv_data_rsp(struct ble_rsp *rsp, void *param) -{ - sync.status = rsp->status; - sync.response = 1; -} - -static void handle_msg_id_ble_gap_enable_adv_rsp(struct ble_rsp *rsp, void *param) -{ - /* No waiting for this response, so nothing to do here */ -} - -static void handle_msg_id_ble_gap_disable_adv_rsp(struct ble_rsp *rsp, void *param) -{ - /* No waiting for this response, so nothing to do here */ -} - -static void handle_msg_id_gatts_add_service_rsp(struct ble_gatts_add_svc_rsp *rsp, void *param) -{ - uint16_t *p_svc_handle = (uint16_t *)sync.param; - - if (p_svc_handle && BLE_STATUS_SUCCESS == rsp->status) - *p_svc_handle = rsp->svc_handle; - - sync.status = rsp->status; - sync.response = 1; -} - -static void handle_msg_id_gatts_add_characteristic_rsp(struct ble_gatts_add_char_rsp *rsp, void *param) -{ - struct ble_gatts_char_handles *p_handles = (struct ble_gatts_char_handles *)sync.param; - - if (p_handles && BLE_STATUS_SUCCESS == rsp->status) - memcpy(p_handles, &rsp->char_h, sizeof(*p_handles)); - - sync.status = rsp->status; - sync.response = 1; -} - -static void handle_msg_id_gatts_add_desc_rsp(struct ble_gatts_add_desc_rsp *rsp, void *param) -{ - uint16_t *p_handle = (uint16_t *)sync.param; - - if (p_handle && BLE_STATUS_SUCCESS == rsp->status) - *p_handle = rsp->handle; - - sync.status = rsp->status; - sync.response = 1; -} - -static void handle_msg_id_ble_gatts_set_attribute_value_rsp(struct ble_gatts_set_attr_rsp_msg *rsp, void *param) -{ - sync.status = rsp->status; - sync.response = 1; -} - -static void handle_msg_id_ble_gap_connect_evt_msg(struct ble_gap_event *evt, void *param) -{ - conn_handle = evt->conn_handle; - connected = true; - - if (ble_client_gap_event_cb) - ble_client_gap_event_cb(BLE_CLIENT_GAP_EVENT_CONNECTED, evt, ble_client_gap_event_param); -} - -static void handle_msg_id_ble_gap_disconnect_evt_msg(struct ble_gap_event *evt, void *param) -{ - connected = false; - - if (ble_client_gap_event_cb) - ble_client_gap_event_cb(BLE_CLIENT_GAP_EVENT_DISCONNECTED, evt, ble_client_gap_event_param); -} +// APP callback +static ble_client_connect_event_cb_t ble_client_connect_event_cb = NULL; +static void *ble_client_connect_event_param; -static void handle_msg_id_ble_gap_timeout_evt_msg(struct ble_gap_event *evt, void *param) -{ - connected = false; +static ble_client_disconnect_event_cb_t ble_client_disconnect_event_cb = NULL; +static void *ble_client_disconnect_event_param; - if (!ble_client_gap_event_cb) - return; +static ble_client_update_param_event_cb_t ble_client_update_param_event_cb = NULL; +static void *ble_client_update_param_event_param; - switch (evt->timeout.reason) { - case BLE_SVC_GAP_TO_ADV: - ble_client_gap_event_cb(BLE_CLIENT_GAP_EVENT_ADV_TIMEOUT, evt, ble_client_gap_event_param); - break; - case BLE_SVC_GAP_TO_CONN: - ble_client_gap_event_cb(BLE_CLIENT_GAP_EVENT_CONN_TIMEOUT, evt, ble_client_gap_event_param); - break; - }; -} -static void handle_msg_id_ble_gap_rssi_evt_msg(struct ble_gap_event *evt, void *param) -{ - if (ble_client_gap_event_cb) - ble_client_gap_event_cb(BLE_CLIENT_GAP_EVENT_RSSI, evt, ble_client_gap_event_param); -} +#define NIBBLE_TO_CHAR(n) \ + ((n) >= 0xA ? ('A' + (n) - 0xA) : ('0' + (n))) -static void handle_msg_id_ble_gatts_write_evt_msg(struct ble_gatts_evt_msg *evt, void *param) -{ - if (ble_client_gatts_event_cb) - ble_client_gatts_event_cb(BLE_CLIENT_GATTS_EVENT_WRITE, evt, ble_client_gatts_event_param); -} +#define BYTE_TO_STR(s, byte) \ + do { \ + *s++ = NIBBLE_TO_CHAR(byte >> 4); \ + *s++ = NIBBLE_TO_CHAR(byte & 0xF); \ + }while(0) -static void handle_msg_id_ble_gatts_send_notif_ind_rsp(ble_gatts_rsp_t *rsp, void *param) -{ - sync.status = rsp->status; - sync.response = 1; -} -static void handle_msg_id_ble_gap_disconnect_rsp(struct ble_rsp *rsp, void *param) -{ - sync.status = rsp->status; - sync.response = 1; -} +#ifdef __cplusplus +extern "C" { +#endif -static void handle_msg_id_ble_gap_set_rssi_report_rsp(struct ble_rsp *rsp, void *param) +static void on_connected(struct bt_conn *conn, uint8_t err) { - sync.status = rsp->status; - sync.response = 1; + if (ble_client_connect_event_cb) + { + ble_client_connect_event_cb(conn, err, ble_client_connect_event_param); + } } -static void handle_msg_id_ble_gap_dtm_init_rsp(struct ble_generic_msg *rsp, void *param) +static void on_disconnected(struct bt_conn *conn, uint8_t reason) { - sync.status = rsp->status; - sync.response = 1; + if (ble_client_disconnect_event_cb) + { + ble_client_disconnect_event_cb(conn, reason, ble_client_disconnect_event_param); + } } -static void ble_core_client_handle_message(struct cfw_message *msg, void *param) +static void on_le_param_updated(struct bt_conn *conn, uint16_t interval, + uint16_t latency, uint16_t timeout) { - switch (CFW_MESSAGE_ID(msg)) { - - case MSG_ID_CFW_SVC_AVAIL_EVT: - handle_msg_id_cfw_svc_avail_evt((cfw_svc_available_evt_msg_t *)msg, param); - break; - - case MSG_ID_CFW_OPEN_SERVICE: - handle_msg_id_cfw_open_svc((cfw_open_conn_rsp_msg_t *)msg, param); - break; - - case MSG_ID_BLE_GAP_WR_CONF_RSP: - handle_msg_id_ble_gap_wr_conf_rsp((struct ble_rsp *)msg, param); - break; - - case MSG_ID_BLE_GAP_RD_BDA_RSP: - handle_msg_id_ble_gap_rd_bda_rsp((ble_bda_rd_rsp_t *)msg, param); - break; - - case MSG_ID_BLE_GAP_SM_CONFIG_RSP: - handle_msg_id_ble_gap_sm_config_rsp((struct ble_rsp *)msg, param); - break; - - case MSG_ID_BLE_GAP_WR_ADV_DATA_RSP: - handle_msg_id_ble_gap_wr_adv_data_rsp((struct ble_rsp *)msg, param); - break; - - case MSG_ID_BLE_GAP_ENABLE_ADV_RSP: - handle_msg_id_ble_gap_enable_adv_rsp((struct ble_rsp *)msg, param); - break; - - case MSG_ID_BLE_GAP_DISABLE_ADV_RSP: - handle_msg_id_ble_gap_disable_adv_rsp((struct ble_rsp *)msg, param); - break; - - case MSG_ID_BLE_GATTS_ADD_SERVICE_RSP: - handle_msg_id_gatts_add_service_rsp((struct ble_gatts_add_svc_rsp *)msg, param); - break; - - case MSG_ID_BLE_GATTS_ADD_CHARACTERISTIC_RSP: - handle_msg_id_gatts_add_characteristic_rsp((struct ble_gatts_add_char_rsp *)msg, param); - break; - - case MSG_ID_BLE_GATTS_ADD_DESCRIPTOR_RSP: - handle_msg_id_gatts_add_desc_rsp((struct ble_gatts_add_desc_rsp *)msg, param); - break; - - case MSG_ID_BLE_GATTS_SET_ATTRIBUTE_VALUE_RSP: - handle_msg_id_ble_gatts_set_attribute_value_rsp((struct ble_gatts_set_attr_rsp_msg *)msg, param); - break; - - case MSG_ID_BLE_GATTS_SEND_NOTIF_RSP: - case MSG_ID_BLE_GATTS_SEND_IND_RSP: - handle_msg_id_ble_gatts_send_notif_ind_rsp((ble_gatts_rsp_t *)msg, param); - break; - - case MSG_ID_BLE_GAP_CONNECT_EVT: - handle_msg_id_ble_gap_connect_evt_msg((struct ble_gap_event *)msg, param); - break; - - case MSG_ID_BLE_GAP_DISCONNECT_EVT: - handle_msg_id_ble_gap_disconnect_evt_msg((struct ble_gap_event *)msg, param); - break; - - case MSG_ID_BLE_GAP_TO_EVT: - handle_msg_id_ble_gap_timeout_evt_msg((struct ble_gap_event *)msg, param); - break; - - case MSG_ID_BLE_GAP_RSSI_EVT: - handle_msg_id_ble_gap_rssi_evt_msg((struct ble_gap_event *)msg, param); - break; - - case MSG_ID_BLE_GATTS_WRITE_EVT: - handle_msg_id_ble_gatts_write_evt_msg((struct ble_gatts_evt_msg *)msg, param); - break; - - case MSG_ID_BLE_GAP_DISCONNECT_RSP: - handle_msg_id_ble_gap_disconnect_rsp((struct ble_rsp *)msg, param); - break; - - case MSG_ID_BLE_GAP_SET_RSSI_REPORT_RSP: - handle_msg_id_ble_gap_set_rssi_report_rsp((struct ble_rsp *)msg, param); - break; - - case MSG_ID_BLE_GAP_DTM_INIT_RSP: - handle_msg_id_ble_gap_dtm_init_rsp((struct ble_generic_msg *)msg, param); - break; + if (ble_client_update_param_event_cb) + { + ble_client_update_param_event_cb (conn, + interval, + latency, + timeout, + ble_client_update_param_event_param); } - cfw_msg_free(msg); } -#ifdef __cplusplus -extern "C" { -#endif +static struct bt_conn_cb conn_callbacks = { + .connected = on_connected, + .disconnected = on_disconnected, + .le_param_updated = on_le_param_updated +}; -#define NIBBLE_TO_CHAR(n) \ - ((n) >= 0xA ? ('A' + (n) - 0xA) : ('0' + (n))) -#define BYTE_TO_STR(s, byte) \ - do { \ - *s++ = NIBBLE_TO_CHAR(byte >> 4); \ - *s++ = NIBBLE_TO_CHAR(byte & 0xF); \ - }while(0) -void ble_client_get_factory_config(ble_addr_t *bda, char *name) +void ble_client_get_factory_config(bt_addr_le_t *bda, char *name) { struct curie_oem_data *p_oem = NULL; unsigned i; @@ -382,7 +128,7 @@ void ble_client_get_factory_config(ble_addr_t *bda, char *name) 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->addr[i] = p_oem->bt_address[BLE_ADDR_LEN - 1 - i]; + bda->val[i] = p_oem->bt_address[BLE_ADDR_LEN - 1 - i]; } } } @@ -419,9 +165,9 @@ void ble_client_get_factory_config(ble_addr_t *bda, char *name) if (bda && bda->type != BLE_DEVICE_ADDR_INVALID) { *suffix++ = '-'; - BYTE_TO_STR(suffix, p_oem->bt_address[4]); - BYTE_TO_STR(suffix, p_oem->bt_address[5]); - *suffix = 0; /* NULL-terminate the string. Note the macro BYTE_TO_STR + BYTE_TO_STR(suffix, p_oem->bt_address[4]); + BYTE_TO_STR(suffix, p_oem->bt_address[5]); + *suffix = 0; /* NULL-terminate the string. Note the macro BYTE_TO_STR automatically move the pointer */ } else @@ -433,453 +179,57 @@ void ble_client_get_factory_config(ble_addr_t *bda, char *name) } } -BleStatus ble_client_init(ble_client_gap_event_cb_t gap_event_cb, void *gap_event_param, - ble_client_gatts_event_cb_t gatts_event_cb, void *gatts_event_param) -{ - BleStatus status; - uint32_t delay_until; - - cfw_platform_nordic_init(); - - client_handle = cfw_init(cfw_get_service_queue(), - ble_core_client_handle_message, - NULL); - - sync.response = 0; - if (cfw_register_svc_available(client_handle, - BLE_CORE_SERVICE_ID, - NULL)) - return BLE_STATUS_ERROR; - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - /* We need to wait for ~1 ms before continuing */ - delay_until = get_uptime_32k() + TIMEOUT_TICKS_1MS; - while (get_uptime_32k() < delay_until); - - sync.response = 0; - cfw_open_service(client_handle, - BLE_CORE_SERVICE_ID, - NULL); - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - ble_client_gap_event_cb = gap_event_cb; - ble_client_gap_event_param = gap_event_param; - - ble_client_gatts_event_cb = gatts_event_cb; - ble_client_gatts_event_param = gatts_event_param; - - return sync.status; -} - -BleStatus ble_client_gap_set_enable_config(const char *name, - const ble_addr_t *bda, - const uint16_t appearance, - const int8_t tx_power, - const uint16_t min_conn_interval, - const uint16_t max_conn_interval) -{ - struct ble_wr_config config; - BleStatus status; - - config.p_bda = (bda && bda->type != BLE_DEVICE_ADDR_INVALID) ? (ble_addr_t *)bda : NULL; - config.p_name = (uint8_t *)name; - config.appearance = appearance; - config.tx_power = tx_power; - config.peripheral_conn_params.interval_min = min_conn_interval; - config.peripheral_conn_params.interval_max = max_conn_interval; - config.peripheral_conn_params.slave_latency = SLAVE_LATENCY; - config.peripheral_conn_params.link_sup_to = CONN_SUP_TIMEOUT; - config.central_conn_params.interval_min = min_conn_interval; - config.central_conn_params.interval_max = max_conn_interval; - config.central_conn_params.slave_latency = SLAVE_LATENCY; - config.central_conn_params.link_sup_to = CONN_SUP_TIMEOUT; - - sync.response = 0; - if (ble_gap_set_enable_config(service_handle, &config, NULL)) - return BLE_STATUS_ERROR; - /* Wait for response message */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - if (sync.status) - return sync.status; - - struct ble_gap_sm_config_params sm_params = { - .options = BLE_GAP_BONDING, - .io_caps = BLE_GAP_IO_NO_INPUT_NO_OUTPUT, - .key_size = 16, - }; - sync.response = 0; - if (ble_gap_sm_config(service_handle, &sm_params, NULL)) - return BLE_STATUS_ERROR; - /* Wait for response message */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - return sync.status; -} - -BleStatus ble_client_gap_get_bda(ble_addr_t *p_bda) -{ - BleStatus status; - - sync.response = 0; - sync.param = (void *)p_bda; - if (ble_gap_read_bda(service_handle, NULL)) - return BLE_STATUS_ERROR; - /* Wait for response message */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - return sync.status; -} - -BleStatus ble_client_gap_wr_adv_data(uint8_t *adv_data, const uint8_t adv_data_len) -{ - BleStatus status; - - struct ble_gap_adv_rsp_data adv_rsp_data = { - .p_data = adv_data, - .len = adv_data_len, - }; - - /* write advertisement data */ - sync.response = 0; - if (ble_gap_wr_adv_data(service_handle, &adv_rsp_data, NULL, NULL)) - return BLE_STATUS_ERROR; - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - return sync.status; -} - -BleStatus ble_client_gap_start_advertise(uint16_t timeout) -{ - /* Hard-coding these advertising parameters for now - * Could be changed to support advanced features such as: - * - slow advertising - * - directed advertising - * - whitelist filtering - * - etc. - */ - ble_gap_adv_param_t adv_params = { - .timeout = timeout, - .interval_min = APP_ULTRA_FAST_ADV_INTERVAL, - .interval_max = APP_ULTRA_FAST_ADV_INTERVAL, - .type = BLE_GAP_ADV_TYPE_ADV_IND, - .filter_policy = BLE_GAP_ADV_FP_ANY, - .p_peer_bda = NULL, - .options = BLE_GAP_OPT_ADV_DEFAULT, - }; - - /* For this message, we don't wait for the response, just fire - * and forget. This allows us to invoke it within the - * disconnect event handler to restart the connection - */ - return ble_gap_start_advertise(service_handle, &adv_params, NULL); -} - -BleStatus ble_client_gap_stop_advertise(void) -{ - /* For this message, we don't wait for the response, just fire - * and forget. - */ - return ble_gap_stop_advertise(service_handle, NULL); -} - -BleStatus ble_client_gatts_add_service(const struct bt_uuid *uuid, - const uint8_t type, - uint16_t *svc_handle) -{ - BleStatus status; - - sync.response = 0; - sync.param = (void *)svc_handle; - if (ble_gatts_add_service(service_handle, uuid, type, NULL, NULL)) - return BLE_STATUS_ERROR; - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - return sync.status; -} - -BleStatus ble_client_gatts_include_service(const uint16_t primary_svc_handle, - const uint16_t included_svc_handle) -{ - BleStatus status; - - sync.response = 0; - if (ble_gatts_add_included_svc(service_handle, - primary_svc_handle, - included_svc_handle, - NULL)) - return BLE_STATUS_ERROR; - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - return sync.status; -} - -BleStatus ble_client_gatts_add_characteristic(const uint16_t svc_handle, - struct ble_gatts_characteristic *char_data, - struct ble_gatts_char_handles *handles) -{ - BleStatus status; - - sync.response = 0; - sync.param = (void *)handles; - - if (ble_gatts_add_characteristic(service_handle, svc_handle, char_data, - NULL, NULL)) - return BLE_STATUS_ERROR; - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - return sync.status; -} - -BleStatus ble_client_gatts_add_descriptor(const uint16_t svc_handle, - struct ble_gatts_descriptor *desc, - uint16_t *handle) -{ - BleStatus status; - - sync.response = 0; - sync.param = (void *)handle; - - if (ble_gatts_add_descriptor(service_handle, desc, NULL, NULL)) - return BLE_STATUS_ERROR; - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - return sync.status; -} - -BleStatus ble_client_gatts_set_attribute_value(const uint16_t value_handle, - const uint16_t len, const uint8_t * p_value, - const uint16_t offset) -{ - BleStatus status; - - sync.response = 0; - if (ble_gatts_set_attribute_value(service_handle, value_handle, - len, p_value, offset, NULL)) - return BLE_STATUS_ERROR; - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - return sync.status; -} - -BleStatus ble_client_gatts_send_notif_ind(const uint16_t value_handle, - const uint16_t len, uint8_t * p_value, - const uint16_t offset, - const bool indication) -{ - BleStatus status; - - ble_gatts_ind_params_t ind_params = { - .val_handle = value_handle, - .len = len, - .p_data = p_value, - .offset = offset, - }; - - sync.response = 0; - if (indication) - status = ble_gatts_send_ind(service_handle, conn_handle, &ind_params, NULL, NULL); - else - status = ble_gatts_send_notif(service_handle, conn_handle, &ind_params, NULL, NULL); - - if (status) - return BLE_STATUS_ERROR; - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - return sync.status; -} - -BleStatus ble_client_gap_disconnect(const uint8_t reason) -{ - BleStatus status; - - if (!connected) - return BLE_STATUS_WRONG_STATE; - - sync.response = 0; - if (ble_gap_disconnect(service_handle, conn_handle, reason, NULL)) - return BLE_STATUS_ERROR; - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - return sync.status; -} - -BleStatus ble_client_gap_set_rssi_report(boolean_t enable) -{ - BleStatus status; - struct rssi_report_params params; - - if (!connected) - return BLE_STATUS_WRONG_STATE; - - params.conn_hdl = conn_handle; - params.op = enable ? BLE_GAP_RSSI_ENABLE_REPORT : BLE_GAP_RSSI_DISABLE_REPORT; - /* TODO - pick sensible defaults for these and/or allow user to specify */ - params.delta_dBm = 5; - params.min_count = 3; - - sync.response = 0; - if (ble_gap_set_rssi_report(service_handle, ¶ms, NULL)) - return BLE_STATUS_ERROR; - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - return sync.status; -} - -BleStatus ble_client_dtm_init(void) -{ - BleStatus status; - - /* Ensure that the ble_client_init() has been called already */ - if (!service_handle) - return BLE_STATUS_WRONG_STATE; - - /* Instruct the Nordic to enter Direct Test Mode */ - sync.response = 0; - ble_gap_dtm_init_req(service_handle, NULL); - - /* Wait for response messages */ - wait_for_condition(sync.response, status); - if (status != BLE_STATUS_SUCCESS) - return status; - - /* DTM is active. Detach UART IPC driver to allow direct access */ - if (BLE_STATUS_SUCCESS == sync.status) - uart_ipc_disable(IPC_UART); - - return sync.status; -} - -static int uart_raw_ble_core_tx_rx(uint8_t * send_data, uint8_t send_no, - uint8_t * rcv_data, uint8_t rcv_no) -{ - int i; - uint8_t rx_byte; - int res; - /* send command */ - for (i = 0; i < send_no; i++) - uart_poll_out(IPC_UART, send_data[i]); - /* answer */ - i = 0; - do { - res = uart_poll_in(IPC_UART, &rx_byte); - if (res == 0) { - rcv_data[i++] = rx_byte; - } - } while (i < rcv_no); - return i; -} - -BleStatus ble_client_dtm_cmd(const struct ble_test_cmd *test_cmd, - struct ble_dtm_test_result *test_result) -{ - BleStatus status; - - uint8_t send_data[7]; - uint8_t rcv_data[9] = {}; - int send_no; - int rcv_no; - - send_data[0] = DTM_HCI_CMD; - send_data[1] = test_cmd->mode; - send_data[2] = DTM_HCI_OPCODE2; - - switch (test_cmd->mode) { - case BLE_TEST_START_DTM_RX: - send_data[3] = 1; /* length */ - send_data[4] = test_cmd->rx.freq; - send_no = 5; - rcv_no = 7; +void ble_client_init(ble_client_connect_event_cb_t connect_cb, void* connect_param, + 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; + pr_info(LOG_MODULE_BLE, "%s", __FUNCTION__); + ble_client_connect_event_cb = connect_cb; + ble_client_connect_event_param = connect_param; + + ble_client_disconnect_event_cb = disconnect_cb; + ble_client_disconnect_event_param = disconnect_param; + + ble_client_update_param_event_cb = update_param_cb; + ble_client_update_param_event_param = update_param_param; + + bt_conn_cb_register(&conn_callbacks); + return; +} + +BleStatus errorno_to_ble_status(int err) +{ + BleStatus err_code; + err = 0 - err; + + switch(err) { + case 0: + err_code = BLE_STATUS_SUCCESS; + break; + case EIO: + err_code = BLE_STATUS_WRONG_STATE; break; - case BLE_TEST_START_DTM_TX: - send_data[3] = 3; /* length */ - send_data[4] = test_cmd->tx.freq; - send_data[5] = test_cmd->tx.len; - send_data[6] = test_cmd->tx.pattern; - send_no = 7; - rcv_no = 7; + case EBUSY: + err_code = BLE_STATUS_TIMEOUT; break; - case BLE_TEST_SET_TXPOWER: - send_data[3] = 1; /* length */ - send_data[4] = test_cmd->tx_pwr.dbm; - send_no = 5; - rcv_no = 7; + case EFBIG: + case ENOTSUP: + err_code = BLE_STATUS_NOT_SUPPORTED; break; - case BLE_TEST_END_DTM: - send_data[3] = 0; /* length */ - send_no = 4; - rcv_no = 9; + case EPERM: + case EACCES: + err_code = BLE_STATUS_NOT_ALLOWED; break; + case ENOMEM: // No memeory default: - return BLE_STATUS_NOT_SUPPORTED; - } - - uart_raw_ble_core_tx_rx(send_data, send_no, rcv_data, rcv_no); - - status = rcv_data[DTM_HCI_STATUS_IDX]; - - test_result->mode = test_cmd->mode; - - uint8_t *p; - switch (test_cmd->mode) { - case BLE_TEST_END_DTM: - p = &rcv_data[DTM_HCI_LE_END_IDX]; - LESTREAM_TO_UINT16(p, test_result->nb); + err_code = BLE_STATUS_ERROR; break; } - - return status; + return err_code; } + #ifdef __cplusplus } #endif diff --git a/libraries/CurieBLE/src/internal/ble_client.h b/libraries/CurieBLE/src/internal/ble_client.h index 3fe47bd4..b7495867 100644 --- a/libraries/CurieBLE/src/internal/ble_client.h +++ b/libraries/CurieBLE/src/internal/ble_client.h @@ -87,63 +87,26 @@ enum { uuid.type = BT_UUID128; \ } while(0) -typedef enum { - BLE_CLIENT_GAP_EVENT_CONNECTED = 0, - BLE_CLIENT_GAP_EVENT_DISCONNECTED, - BLE_CLIENT_GAP_EVENT_ADV_TIMEOUT, - BLE_CLIENT_GAP_EVENT_CONN_TIMEOUT, - BLE_CLIENT_GAP_EVENT_RSSI, -} ble_client_gap_event_t; -typedef enum { - BLE_CLIENT_GATTS_EVENT_WRITE = 0, -} ble_client_gatts_event_t; +typedef void (*ble_client_connect_event_cb_t)(struct bt_conn *conn, uint8_t err, void *param); +typedef void (*ble_client_disconnect_event_cb_t)(struct bt_conn *conn, uint8_t reason, void *param); +typedef void (*ble_client_update_param_event_cb_t)(struct bt_conn *conn, + uint16_t interval, + uint16_t latency, + uint16_t timeout, + void *param); -typedef void (*ble_client_gap_event_cb_t)(ble_client_gap_event_t event, struct ble_gap_event *event_data, void *param); -typedef void (*ble_client_gatts_event_cb_t)(ble_client_gatts_event_t event, struct ble_gatts_evt_msg *event_data, void *param); #ifdef __cplusplus extern "C" { #endif -void ble_client_get_factory_config(ble_addr_t *bda, char *name); -BleStatus ble_client_init(ble_client_gap_event_cb_t gap_event_cb, - void *gap_event_param, - ble_client_gatts_event_cb_t gatts_event_cb, - void *gatts_event_param); -BleStatus ble_client_gap_set_enable_config(const char *name, - const ble_addr_t *bda, - const uint16_t appearance, - const int8_t tx_power, - const uint16_t min_conn_interval, - const uint16_t max_conn_interval); -BleStatus ble_client_gap_get_bda(ble_addr_t *p_bda); -BleStatus ble_client_gap_wr_adv_data(uint8_t *adv_data, - const uint8_t adv_data_len); -BleStatus ble_client_gap_start_advertise(uint16_t timeout); -BleStatus ble_client_gap_stop_advertise(void); -BleStatus ble_client_gatts_add_service(const struct bt_uuid *uuid, const uint8_t type, uint16_t *svc_handle); -BleStatus ble_client_gatts_include_service(const uint16_t primary_svc_handle, uint16_t included_svc_handle); -BleStatus ble_client_gatts_add_characteristic(const uint16_t svc_handle, - struct ble_gatts_characteristic *char_data, - struct ble_gatts_char_handles *handles); -BleStatus ble_client_gatts_add_descriptor(const uint16_t svc_handle, - struct ble_gatts_descriptor *desc, - uint16_t *handle); -BleStatus ble_client_gatts_set_attribute_value(const uint16_t value_handle, - const uint16_t len, const uint8_t *value, - const uint16_t offset); -BleStatus ble_client_gatts_send_notif_ind(const uint16_t value_handle, - const uint16_t len, uint8_t * p_value, - const uint16_t offset, - const bool indication); -BleStatus ble_client_gap_disconnect(const uint8_t reason); -BleStatus ble_client_gap_set_rssi_report(boolean_t enable); - -/* Direct Test Mode (DTM) API - for internal use only */ -BleStatus ble_client_dtm_init(void); -BleStatus ble_client_dtm_cmd(const struct ble_test_cmd *test_cmd, - struct ble_dtm_test_result *test_result); +void ble_client_init(ble_client_connect_event_cb_t connect_cb, void* connect_param, + 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); +void ble_client_get_factory_config(bt_addr_le_t *bda, char *name); +void ble_gap_set_tx_power(int8_t tx_power); +BleStatus errorno_to_ble_status(int err); #ifdef __cplusplus } diff --git a/platform.txt b/platform.txt index e5493cb2..ecac9280 100644 --- a/platform.txt +++ b/platform.txt @@ -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__ +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.elf.cmd=arc-elf32-gcc compiler.c.elf.flags=-nostartfiles -nodefaultlibs -nostdlib -static -Wl,-X -Wl,-N -Wl,-mcpu=quarkse_em -Wl,-marcelf -Wl,--gc-sections compiler.S.flags=-c -g -x assembler-with-cpp compiler.cpp.cmd=arc-elf32-g++ -compiler.cpp.flags=-c -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 -fno-rtti -fno-exceptions -D__ARDUINO_ARC__ -std=c++11 +compiler.cpp.flags=-c -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 -fno-rtti -fno-exceptions -D__ARDUINO_ARC__ -std=c++11 -DCONFIG_BLUETOOTH_PERIPHERAL -DCONFIG_BLUETOOTH_CENTRAL -DCONFIG_BLUETOOTH_GATT_CLIENT compiler.ar.cmd=arc-elf32-ar compiler.ar.flags=rcs compiler.objcopy.cmd=arc-elf32-objcopy diff --git a/system/libarc32_arduino101/Makefile b/system/libarc32_arduino101/Makefile index 9602e3ad..2e947bc9 100644 --- a/system/libarc32_arduino101/Makefile +++ b/system/libarc32_arduino101/Makefile @@ -3,10 +3,12 @@ ASM_SRC+=$(wildcard $(PWD)/drivers/*.S) ASM_SRC+=$(wildcard $(PWD)/common/*.S) C_SRC+=$(wildcard $(PWD)/bootcode/*.c) C_SRC+=$(wildcard $(PWD)/drivers/*.c) +C_SRC+=$(wildcard $(PWD)/drivers/rpc/*.c) C_SRC+=$(wildcard $(PWD)/common/*.c) C_SRC+=$(wildcard $(PWD)/framework/src/*.c) C_SRC+=$(wildcard $(PWD)/framework/src/services/*.c) C_SRC+=$(wildcard $(PWD)/framework/src/services/ble/*.c) +C_SRC+=$(wildcard $(PWD)/framework/src/services/ble_service/*.c) C_SRC+=$(wildcard $(PWD)/framework/src/cfw/*.c) C_SRC+=$(wildcard $(PWD)/framework/src/infra/*.c) C_SRC+=$(wildcard $(PWD)/framework/src/util/*.c) @@ -25,8 +27,21 @@ HWFLAGS=-mARCv2EM -mav2em -mlittle-endian CFGFLAGS=-DCONFIG_SOC_GPIO_32 -DCONFIG_SOC_GPIO_AON -DINFRA_MULTI_CPU_SUPPORT -DCFW_MULTI_CPU_SUPPORT -DCONFIG_HAS_SHARED_MEM -DCONFIG_INFRA_IS_MASTER OPTFLAGS=-g -Os -Wall -Werror +CFGFLAGS+=-DCONFIG_SOC_QUARK_SE +#CFGFLAGS+=-DTRACK_ALLOCS +#CFGFLAGS+=-DIPC_UART_DBG_RX +#CFGFLAGS+=-DIPC_UART_DBG_TX +CFGFLAGS+=-DBT_GATT_DEBUG +CFGFLAGS+=-DCONFIG_RPC_IN +CFGFLAGS+=-DCONFIG_IPC_UART_NS16550 CFGFLAGS+=-DCONFIG_IPC_UART_BAUDRATE=1000000 -INCLUDES=-I. -Icommon -Idrivers -Ibootcode -Iframework/include -Iframework/src/services/ble +CFGFLAGS+=-DCONFIG_BLUETOOTH_MAX_CONN=2 +CFGFLAGS+=-DCONFIG_BT_GATT_BLE_MAX_SERVICES=10 +CFGFLAGS+=-DCONFIG_BLUETOOTH_GATT_CLIENT +CFGFLAGS+=-DCONFIG_BLUETOOTH_CENTRAL -DCONFIG_BLUETOOTH_PERIPHERAL +INCLUDES=-I. -Icommon -Idrivers -Ibootcode -Iframework/include -Iframework/include/services/ble -Iframework/src/services/ble_service +#-Iframework/src/services/ble -Iframework/include/services/ble +INCLUDES+= -Idrivers/rpc -Iframework/src EXTRA_CFLAGS=-D__CPU_ARC__ -DCLOCK_SPEED=32 -std=c99 -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 CFLAGS=$(HWFLAGS) $(OPTFLAGS) $(EXTRA_CFLAGS) $(CFGFLAGS) $(INCLUDES) @@ -39,7 +54,7 @@ lib: $(TARGET_LIB) $(TARGET_LIB): $(C_OBJ) $(ASM_OBJ) @echo "Link $@" - $(AR) rcs $@ $^ + @$(AR) rcs $@ $^ %.o: %.S @echo "Assembling $<" @@ -47,7 +62,7 @@ $(TARGET_LIB): $(C_OBJ) $(ASM_OBJ) %.o: %.c @echo "Compiling $<" - $(CC) -c $(CFLAGS) $< -o $@ + @$(CC) -c $(CFLAGS) $< -o $@ lib_install: lib @if test "$(LIB_INSTALL_PATH)" = "" ; then \ diff --git a/system/libarc32_arduino101/common/atomic.h b/system/libarc32_arduino101/common/atomic.h new file mode 100644 index 00000000..d30cfbe4 --- /dev/null +++ b/system/libarc32_arduino101/common/atomic.h @@ -0,0 +1,156 @@ +/* atomic operations */ + +/* + * Copyright (c) 1997-2015, Wind River Systems, Inc. + * + * 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 __ATOMIC_H__ +#define __ATOMIC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int atomic_t; +typedef atomic_t atomic_val_t; + +extern atomic_val_t atomic_add(atomic_t *target, atomic_val_t value); +extern atomic_val_t atomic_and(atomic_t *target, atomic_val_t value); +extern atomic_val_t atomic_dec(atomic_t *target); +extern atomic_val_t atomic_inc(atomic_t *target); +extern atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value); +extern atomic_val_t atomic_or(atomic_t *target, atomic_val_t value); +extern atomic_val_t atomic_sub(atomic_t *target, atomic_val_t value); +extern atomic_val_t atomic_xor(atomic_t *target, atomic_val_t value); +extern atomic_val_t atomic_clear(atomic_t *target); +extern atomic_val_t atomic_get(const atomic_t *target); +extern atomic_val_t atomic_set(atomic_t *target, atomic_val_t value); +extern int atomic_cas(atomic_t *target, + atomic_val_t oldValue, atomic_val_t newValue); + + +#define ATOMIC_INIT(i) {(i)} + +#define ATOMIC_BITS (sizeof(atomic_val_t) * 8) +#define ATOMIC_MASK(bit) (1 << ((bit) & (ATOMIC_BITS - 1))) +#define ATOMIC_ELEM(addr, bit) ((addr) + ((bit) / ATOMIC_BITS)) + +/** @brief Test whether a bit is set + * + * Test whether bit number bit is set or not. + * + * Also works for an array of multiple atomic_t variables, in which + * case the bit number may go beyond the number of bits in a single + * atomic_t variable. + * + * @param addr base address to start counting from + * @param bit bit number counted from the base address + * + * @return 1 if the bit was set, 0 if it wasn't + */ +static inline int atomic_test_bit(const atomic_t *addr, int bit) +{ + atomic_val_t val = atomic_get(ATOMIC_ELEM(addr, bit)); + + return (1 & (val >> (bit & (ATOMIC_BITS - 1)))); +} + +/** @brief Clear a bit and return its old value + * + * Atomically clear a bit and return its old value. + * + * Also works for an array of multiple atomic_t variables, in which + * case the bit number may go beyond the number of bits in a single + * atomic_t variable. + * + * @param addr base address to start counting from + * @param bit bit number counted from the base address + * + * @return 1 if the bit was set, 0 if it wasn't + */ +static inline int atomic_test_and_clear_bit(atomic_t *addr, int bit) +{ + atomic_val_t mask = ATOMIC_MASK(bit); + atomic_val_t old; + + old = atomic_and(ATOMIC_ELEM(addr, bit), ~mask); + + return (old & mask) != 0; +} + +/** @brief Set a bit and return its old value + * + * Atomically set a bit and return its old value. + * + * Also works for an array of multiple atomic_t variables, in which + * case the bit number may go beyond the number of bits in a single + * atomic_t variable. + * + * @param addr base address to start counting from + * @param bit bit number counted from the base address + * + * @return 1 if the bit was set, 0 if it wasn't + */ +static inline int atomic_test_and_set_bit(atomic_t *addr, int bit) +{ + atomic_val_t mask = ATOMIC_MASK(bit); + atomic_val_t old; + + old = atomic_or(ATOMIC_ELEM(addr, bit), mask); + + return (old & mask) != 0; +} + +/** @brief Clear a bit + * + * Atomically clear a bit. + * + * Also works for an array of multiple atomic_t variables, in which + * case the bit number may go beyond the number of bits in a single + * atomic_t variable. + * + * @param addr base address to start counting from + * @param bit bit number counted from the base address + */ +static inline void atomic_clear_bit(atomic_t *addr, int bit) +{ + atomic_val_t mask = ATOMIC_MASK(bit); + + atomic_and(ATOMIC_ELEM(addr, bit), ~mask); +} + +/** @brief Set a bit + * + * Atomically set a bit. + * + * Also works for an array of multiple atomic_t variables, in which + * case the bit number may go beyond the number of bits in a single + * atomic_t variable. + * + * @param addr base address to start counting from + * @param bit bit number counted from the base address + */ +static inline void atomic_set_bit(atomic_t *addr, int bit) +{ + atomic_val_t mask = ATOMIC_MASK(bit); + + atomic_or(ATOMIC_ELEM(addr, bit), mask); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __ATOMIC_H__ */ diff --git a/system/libarc32_arduino101/common/misc/byteorder.h b/system/libarc32_arduino101/common/misc/byteorder.h new file mode 100644 index 00000000..67cecbc3 --- /dev/null +++ b/system/libarc32_arduino101/common/misc/byteorder.h @@ -0,0 +1,44 @@ +/* byteorder.h - Byte order helpers */ + +/* + * Copyright (c) 2015, 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. + */ + +#define bswap_16(x) ((uint16_t) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))) + +#define bswap_32(x) ((uint32_t) ((((x) >> 24) & 0xff) | (((x) >> 8) & 0xff00) \ + | (((x) & 0xff00) << 8) | (((x) & 0xff) << 24))) + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define sys_le16_to_cpu(val) (val) +#define sys_cpu_to_le16(val) (val) +#define sys_be16_to_cpu(val) bswap_16(val) +#define sys_cpu_to_be16(val) bswap_16(val) +#define sys_le32_to_cpu(val) (val) +#define sys_cpu_to_le32(val) (val) +#define sys_be32_to_cpu(val) bswap_32(val) +#define sys_cpu_to_be32(val) bswap_32(val) +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define sys_le16_to_cpu(val) bswap_16(val) +#define sys_cpu_to_le16(val) bswap_16(val) +#define sys_be16_to_cpu(val) (val) +#define sys_cpu_to_be16(val) (val) +#define sys_le32_to_cpu(val) bswap_32(val) +#define sys_cpu_to_le32(val) bswap_32(val) +#define sys_be32_to_cpu(val) (val) +#define sys_cpu_to_be32(val) (val) +#else +#error "Unknown byte order" +#endif diff --git a/system/libarc32_arduino101/common/misc/util.h b/system/libarc32_arduino101/common/misc/util.h index 626c2b69..ab45bbb1 100644 --- a/system/libarc32_arduino101/common/misc/util.h +++ b/system/libarc32_arduino101/common/misc/util.h @@ -44,6 +44,11 @@ extern "C" { #ifndef _ASMLANGUAGE +#define ARRAY_SIZE(array) ((unsigned long)(sizeof(array) / sizeof((array)[0]))) +#define CONTAINER_OF(ptr, type, field) \ + ((type *)(((char *)(ptr)) - offsetof(type, field))) + + /* round "x" up/down to next multiple of "align" (which must be a power of 2) */ #define ROUND_UP(x, align) \ (((unsigned long)(x) + ((unsigned long)align - 1)) & \ diff --git a/system/libarc32_arduino101/drivers/atomic_native.c b/system/libarc32_arduino101/drivers/atomic_native.c new file mode 100644 index 00000000..41bed7d4 --- /dev/null +++ b/system/libarc32_arduino101/drivers/atomic_native.c @@ -0,0 +1,370 @@ +/* + * Copyright (c) 2016 Intel Corporation + * Copyright (c) 2011-2014 Wind River Systems, Inc. + * + * 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 Atomic ops for ARC EM + * + * This module provides the atomic operators for ARC EM family processors + * which do not support native atomic operations. + * + * The atomic operations are guaranteed to be atomic with respect + * to interrupt service routines, and to operations performed by peer + * processors. + * + * (originally from x86's atomic.c) + */ + +#include +//#include +//#include +#include +#define irq_lock() interrupt_lock() +#define irq_unlock(key) interrupt_unlock(key) + +#if defined(__clang__) +#define FUNC_NO_FP +#else +#define FUNC_NO_FP __attribute__((optimize("-fomit-frame-pointer"))) +#endif +/** + * + * @brief Atomic compare-and-set primitive + * + * This routine provides the compare-and-set operator. If the original value at + * equals , then is stored at and the + * function returns 1. + * + * If the original value at does not equal , then the store + * is not done and the function returns 0. + * + * The reading of the original value at , the comparison, + * and the write of the new value (if it occurs) all happen atomically with + * respect to both interrupts and accesses of other processors to . + * + * @param target address to be tested + * @param old_value value to compare against + * @param new_value value to compare against + * @return Returns 1 if is written, 0 otherwise. + */ +FUNC_NO_FP int atomic_cas(atomic_t *target, atomic_val_t old_value, + atomic_val_t new_value) +{ + unsigned int key; + int ret = 0; + + key = irq_lock(); + + if (*target == old_value) { + *target = new_value; + ret = 1; + } + + irq_unlock(key); + + return ret; +} + +/** + * + * @brief Atomic addition primitive + * + * This routine provides the atomic addition operator. The is + * atomically added to the value at , placing the result at , + * and the old value from is returned. + * + * @param target memory location to add to + * @param value the value to add + * + * @return The previous value from + */ +FUNC_NO_FP atomic_val_t atomic_add(atomic_t *target, atomic_val_t value) +{ + unsigned int key; + atomic_val_t ret; + + key = irq_lock(); + + ret = *target; + *target += value; + + irq_unlock(key); + + return ret; +} + +/** + * + * @brief Atomic subtraction primitive + * + * This routine provides the atomic subtraction operator. The is + * atomically subtracted from the value at , placing the result at + * , and the old value from is returned. + * + * @param target the memory location to subtract from + * @param value the value to subtract + * + * @return The previous value from + */ +FUNC_NO_FP atomic_val_t atomic_sub(atomic_t *target, atomic_val_t value) +{ + unsigned int key; + atomic_val_t ret; + + key = irq_lock(); + + ret = *target; + *target -= value; + + irq_unlock(key); + + return ret; +} + +/** + * + * @brief Atomic increment primitive + * + * @param target memory location to increment + * + * This routine provides the atomic increment operator. The value at + * is atomically incremented by 1, and the old value from is returned. + * + * @return The value from before the increment + */ +FUNC_NO_FP atomic_val_t atomic_inc(atomic_t *target) +{ + unsigned int key; + atomic_val_t ret; + + key = irq_lock(); + + ret = *target; + (*target)++; + + irq_unlock(key); + + return ret; +} + +/** + * + * @brief Atomic decrement primitive + * + * @param target memory location to decrement + * + * This routine provides the atomic decrement operator. The value at + * is atomically decremented by 1, and the old value from is returned. + * + * @return The value from prior to the decrement + */ +FUNC_NO_FP atomic_val_t atomic_dec(atomic_t *target) +{ + unsigned int key; + atomic_val_t ret; + + key = irq_lock(); + + ret = *target; + (*target)--; + + irq_unlock(key); + + return ret; +} + +/** + * + * @brief Atomic get primitive + * + * @param target memory location to read from + * + * This routine provides the atomic get primitive to atomically read + * a value from . It simply does an ordinary load. Note that + * is expected to be aligned to a 4-byte boundary. + * + * @return The value read from + */ +FUNC_NO_FP atomic_val_t atomic_get(const atomic_t *target) +{ + return *target; +} + +/** + * + * @brief Atomic get-and-set primitive + * + * This routine provides the atomic set operator. The is atomically + * written at and the previous value at is returned. + * + * @param target the memory location to write to + * @param value the value to write + * + * @return The previous value from + */ +FUNC_NO_FP atomic_val_t atomic_set(atomic_t *target, atomic_val_t value) +{ + unsigned int key; + atomic_val_t ret; + + key = irq_lock(); + + ret = *target; + *target = value; + + irq_unlock(key); + + return ret; +} + +/** + * + * @brief Atomic clear primitive + * + * This routine provides the atomic clear operator. The value of 0 is atomically + * written at and the previous value at is returned. (Hence, + * atomic_clear(pAtomicVar) is equivalent to atomic_set(pAtomicVar, 0).) + * + * @param target the memory location to write + * + * @return The previous value from + */ +FUNC_NO_FP atomic_val_t atomic_clear(atomic_t *target) +{ + unsigned int key; + atomic_val_t ret; + + key = irq_lock(); + + ret = *target; + *target = 0; + + irq_unlock(key); + + return ret; +} + +/** + * + * @brief Atomic bitwise inclusive OR primitive + * + * This routine provides the atomic bitwise inclusive OR operator. The + * is atomically bitwise OR'ed with the value at , placing the result + * at , and the previous value at is returned. + * + * @param target the memory location to be modified + * @param value the value to OR + * + * @return The previous value from + */ +FUNC_NO_FP atomic_val_t atomic_or(atomic_t *target, atomic_val_t value) +{ + unsigned int key; + atomic_val_t ret; + + key = irq_lock(); + + ret = *target; + *target |= value; + + irq_unlock(key); + + return ret; +} + +/** + * + * @brief Atomic bitwise exclusive OR (XOR) primitive + * + * This routine provides the atomic bitwise exclusive OR operator. The + * is atomically bitwise XOR'ed with the value at , placing the result + * at , and the previous value at is returned. + * + * @param target the memory location to be modified + * @param value the value to XOR + * + * @return The previous value from + */ +FUNC_NO_FP atomic_val_t atomic_xor(atomic_t *target, atomic_val_t value) +{ + unsigned int key; + atomic_val_t ret; + + key = irq_lock(); + + ret = *target; + *target ^= value; + + irq_unlock(key); + + return ret; +} + +/** + * + * @brief Atomic bitwise AND primitive + * + * This routine provides the atomic bitwise AND operator. The is + * atomically bitwise AND'ed with the value at , placing the result + * at , and the previous value at is returned. + * + * @param target the memory location to be modified + * @param value the value to AND + * + * @return The previous value from + */ +FUNC_NO_FP atomic_val_t atomic_and(atomic_t *target, atomic_val_t value) +{ + unsigned int key; + atomic_val_t ret; + + key = irq_lock(); + + ret = *target; + *target &= value; + + irq_unlock(key); + + return ret; +} + +/** + * + * @brief Atomic bitwise NAND primitive + * + * This routine provides the atomic bitwise NAND operator. The is + * atomically bitwise NAND'ed with the value at , placing the result + * at , and the previous value at is returned. + * + * @param target the memory location to be modified + * @param value the value to NAND + * + * @return The previous value from + */ +FUNC_NO_FP atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value) +{ + unsigned int key; + atomic_val_t ret; + + key = irq_lock(); + + ret = *target; + *target = ~(*target & value); + + irq_unlock(key); + + return ret; +} diff --git a/system/libarc32_arduino101/drivers/bluetooth/att.h b/system/libarc32_arduino101/drivers/bluetooth/att.h new file mode 100644 index 00000000..5752a079 --- /dev/null +++ b/system/libarc32_arduino101/drivers/bluetooth/att.h @@ -0,0 +1,55 @@ +/** @file + * @brief Attribute Protocol handling. + */ + +/* + * 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_ATT_H +#define __BT_ATT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Error codes for Error response PDU */ +#define BT_ATT_ERR_INVALID_HANDLE 0x01 +#define BT_ATT_ERR_READ_NOT_PERMITTED 0x02 +#define BT_ATT_ERR_WRITE_NOT_PERMITTED 0x03 +#define BT_ATT_ERR_INVALID_PDU 0x04 +#define BT_ATT_ERR_AUTHENTICATION 0x05 +#define BT_ATT_ERR_NOT_SUPPORTED 0x06 +#define BT_ATT_ERR_INVALID_OFFSET 0x07 +#define BT_ATT_ERR_AUTHORIZATION 0x08 +#define BT_ATT_ERR_PREPARE_QUEUE_FULL 0x09 +#define BT_ATT_ERR_ATTRIBUTE_NOT_FOUND 0x0a +#define BT_ATT_ERR_ATTRIBUTE_NOT_LONG 0x0b +#define BT_ATT_ERR_ENCRYPTION_KEY_SIZE 0x0c +#define BT_ATT_ERR_INVALID_ATTRIBUTE_LEN 0x0d +#define BT_ATT_ERR_UNLIKELY 0x0e +#define BT_ATT_ERR_INSUFFICIENT_ENCRYPTION 0x0f +#define BT_ATT_ERR_UNSUPPORTED_GROUP_TYPE 0x10 +#define BT_ATT_ERR_INSUFFICIENT_RESOURCES 0x11 + +/* Common Profile Error Codes (from CSS) */ +#define BT_ATT_ERR_CCC_IMPROPER_CONF 0xfd +#define BT_ATT_ERR_PROCEDURE_IN_PROGRESS 0xfe +#define BT_ATT_ERR_OUT_OF_RANGE 0xff + +#ifdef __cplusplus +} +#endif + +#endif /* __BT_ATT_H */ diff --git a/system/libarc32_arduino101/drivers/bluetooth/bluetooth.h b/system/libarc32_arduino101/drivers/bluetooth/bluetooth.h new file mode 100644 index 00000000..e87cf2ab --- /dev/null +++ b/system/libarc32_arduino101/drivers/bluetooth/bluetooth.h @@ -0,0 +1,353 @@ +/** @file + * @brief Bluetooth subsystem core APIs. + */ + +/* + * Copyright (c) 2015 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_BLUETOOTH_H +#define __BT_BLUETOOTH_H + +#include +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Callback for notifying that Bluetooth has been enabled. + * + * @param err zero on success or (negative) error code otherwise. + */ +typedef void (*bt_ready_cb_t)(int err); + +/** @brief Enable Bluetooth + * + * Enable Bluetooth. Must be the called before any calls that + * require communication with the local Bluetooth hardware. + * + * @param cb Callback to notify completion or NULL to perform the + * enabling synchronously. + * + * @return Zero on success or (negative) error code otherwise. + */ +int bt_enable(bt_ready_cb_t cb); + +/* Advertising API */ + +/** Description of different data types that can be encoded into + * advertising data. Used to form arrays that are passed to the + * bt_le_adv_start() function. + */ +struct bt_data { + uint8_t type; + uint8_t data_len; + const uint8_t *data; +}; + +/** @brief Helper to declare elements of bt_data arrays + * + * This macro is mainly for creating an array of struct bt_data + * elements which is then passed to bt_le_adv_start(). + * + * @param _type Type of advertising data field + * @param _data Pointer to the data field payload + * @param _data_len Number of bytes behind the _data pointer + */ +#define BT_DATA(_type, _data, _data_len) \ + { \ + .type = (_type), \ + .data_len = (_data_len), \ + .data = (_data), \ + } + +/** @brief Helper to declare elements of bt_data arrays + * + * This macro is mainly for creating an array of struct bt_data + * elements which is then passed to bt_le_adv_start(). + * + * @param _type Type of advertising data field + * @param _bytes Variable number of single-byte parameters + */ +#define BT_DATA_BYTES(_type, _bytes...) \ + BT_DATA(_type, ((uint8_t []) { _bytes }), \ + sizeof((uint8_t []) { _bytes })) + +/** Local advertising address type */ +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, +}; + +/** 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; + + /** Minimum Advertising Interval (N * 0.625) */ + uint16_t interval_min; + + /** Maximum Advertising Interval (N * 0.625) */ + uint16_t interval_max; +}; + +/** Helper to declare advertising parameters inline + * + * @param _type Advertising Type + * @param _addr_type Local address type to use for advertising + * @param _int_min Minimum advertising interval + * @param _int_max Maximum advertising interval + */ +#define BT_LE_ADV_PARAM(_type, _addr_type, _int_min, _int_max) \ + (&(struct bt_le_adv_param) { \ + .type = (_type), \ + .addr_type = (_addr_type), \ + .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) + +/** @brief Start advertising + * + * Set advertisement data, scan response data, advertisement parameters + * and start advertising. + * + * @param param Advertising parameters. + * @param ad Data to be used in advertisement packets. + * @param ad_len Number of elements in ad + * @param sd Data to be used in scan response packets. + * @param sd_len Number of elements in sd + * + * @return Zero on success or (negative) error code otherwise. + */ +int bt_le_adv_start(const struct bt_le_adv_param *param, + const struct bt_data *ad, size_t ad_len, + const struct bt_data *sd, size_t sd_len); + +/** @brief Stop advertising + * + * Stops ongoing advertising. + * + * @return Zero on success or (negative) error code otherwise. + */ +int bt_le_adv_stop(void); + +/** @brief Define a type allowing user to implement a function that can + * be used to get back active LE scan results. + * + * A function of this type will be called back when user application + * triggers active LE scan. The caller will populate all needed + * parameters based on data coming from scan result. + * Such function can be set by user when LE active scan API is used. + * + * @param addr Advertiser LE address and type. + * @param rssi Strength of advertiser signal. + * @param adv_type Type of advertising response from advertiser. + * @param adv_data Address of buffer containig advertiser data. + * @param len Length of advertiser data contained in buffer. + */ +typedef void bt_le_scan_cb_t(const bt_addr_le_t *addr, int8_t rssi, + uint8_t adv_type, const uint8_t *adv_data, + uint8_t len); + +/** LE scan parameters */ +struct bt_le_scan_param { + /** Scan type (BT_HCI_LE_SCAN_ACTIVE or BT_HCI_LE_SCAN_PASSIVE) */ + uint8_t type; + + /** Duplicate filtering (BT_HCI_LE_SCAN_FILTER_DUP_ENABLE or + * BT_HCI_LE_SCAN_FILTER_DUP_DISABLE) + */ + uint8_t filter_dup; + + /** Scan interval (N * 0.625 ms) */ + uint16_t interval; + + /** Scan window (N * 0.625 ms) */ + uint16_t window; +}; + +/** Helper to declare scan parameters inline + * + * @param _type Scan Type (BT_HCI_LE_SCAN_ACTIVE/BT_HCI_LE_SCAN_PASSIVE) + * @param _filter Filter Duplicates + * @param _interval Scan Interval (N * 0.625 ms) + * @param _window Scan Window (N * 0.625 ms) + */ +#define BT_LE_SCAN_PARAM(_type, _filter, _interval, _window) \ + (&(struct bt_le_scan_param) { \ + .type = (_type), \ + .filter_dup = (_filter), \ + .interval = (_interval), \ + .window = (_window), \ + }) + +/** Helper macro to enable active scanning to discover new devices. */ +#define BT_LE_SCAN_ACTIVE BT_LE_SCAN_PARAM(BT_HCI_LE_SCAN_ACTIVE, \ + BT_HCI_LE_SCAN_FILTER_DUP_ENABLE, \ + BT_GAP_SCAN_FAST_INTERVAL, \ + BT_GAP_SCAN_FAST_WINDOW) + +/** Helper macro to enable passive scanning to discover new devices. + * + * This macro should be used if information required for device identification + * (eg UUID) are known to be placed in Advertising Data. + */ +#define BT_LE_SCAN_PASSIVE BT_LE_SCAN_PARAM(BT_HCI_LE_SCAN_PASSIVE, \ + BT_HCI_LE_SCAN_FILTER_DUP_ENABLE, \ + BT_GAP_SCAN_FAST_INTERVAL, \ + BT_GAP_SCAN_FAST_WINDOW) + +/** @brief Start (LE) scanning + * + * Start LE scanning with and provide results through the specified + * callback. + * + * @param param Scan parameters. + * @param cb Callback to notify scan 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_le_scan_start(const struct bt_le_scan_param *param, bt_le_scan_cb_t cb); + +/** @brief Stop (LE) scanning. + * + * Stops ongoing LE scanning. + * + * @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_le_scan_stop(void); + +/** @def BT_ADDR_STR_LEN + * + * @brief Recommended length of user string buffer for Bluetooth address + * + * @details The recommended length guarantee the output of address + * conversion will not lose valuable information about address being + * processed. + */ +#define BT_ADDR_STR_LEN 18 + +/** @def BT_ADDR_LE_STR_LEN + * + * @brief Recommended length of user string buffer for Bluetooth LE address + * + * @details The recommended length guarantee the output of address + * conversion will not lose valuable information about address being + * processed. + */ +#define BT_ADDR_LE_STR_LEN 27 + +/** @brief Converts binary Bluetooth address to string. + * + * @param addr Address of buffer containing binary Bluetooth address. + * @param str Address of user buffer with enough room to store formatted + * string containing binary address. + * @param len Length of data to be copied to user string buffer. Refer to + * BT_ADDR_STR_LEN about recommended value. + * + * @return Number of successfully formatted bytes from binary address. + */ +static inline int bt_addr_to_str(const bt_addr_t *addr, char *str, size_t len) +{ + return snprintf(str, len, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", + addr->val[5], addr->val[4], addr->val[3], + addr->val[2], addr->val[1], addr->val[0]); +} + +/** @brief Converts binary LE Bluetooth address to string. + * + * @param addr Address of buffer containing binary LE Bluetooth address. + * @param str Address of user buffer with enough room to store + * formatted string containing binary LE address. + * @param len Length of data to be copied to user string buffer. Refer to + * BT_ADDR_LE_STR_LEN about recommended value. + * + * @return Number of successfully formatted bytes from binary address. + */ +static inline int bt_addr_le_to_str(const bt_addr_le_t *addr, char *str, + size_t len) +{ + char type[7]; + + switch (addr->type) { + case BT_ADDR_LE_PUBLIC: + strcpy(type, "public"); + break; + case BT_ADDR_LE_RANDOM: + strcpy(type, "random"); + break; + default: + sprintf(type, "0x%02x", addr->type); + break; + } + + 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); +} + +#if defined(CONFIG_BLUETOOTH_BREDR) +/** @brief Enable/disable set controller in discoverable state. + * + * Allows make local controller to listen on INQUIRY SCAN channel and responds + * to devices making general inquiry. To enable this state it's mandatory + * to first be in connectable state. + * + * @param enable Value allowing/disallowing controller to become discoverable. + * + * @return Negative if fail set to requested state or requested state has been + * already set. Zero if done successfully. + */ +int bt_br_set_discoverable(bool enable); + +/** @brief Enable/disable set controller in connectable state. + * + * Allows make local controller to be connectable. It means the controller + * start listen to devices requests on PAGE SCAN channel. If disabled also + * resets discoverability if was set. + * + * @param enable Value allowing/disallowing controller to be connectable. + * + * @return Negative if fail set to requested state or requested state has been + * already set. Zero if done successfully. + */ +int bt_br_set_connectable(bool enable); +#endif + +void bt_le_set_device_name(char *device_name, int len); + +#ifdef __cplusplus +} +#endif + +#endif /* __BT_BLUETOOTH_H */ diff --git a/system/libarc32_arduino101/drivers/bluetooth/conn.h b/system/libarc32_arduino101/drivers/bluetooth/conn.h new file mode 100644 index 00000000..1b710d6f --- /dev/null +++ b/system/libarc32_arduino101/drivers/bluetooth/conn.h @@ -0,0 +1,399 @@ +/** @file + * @brief Bluetooth connection handling + */ + +/* + * Copyright (c) 2015 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_CONN_H +#define __BT_CONN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(CONFIG_BLUETOOTH_CENTRAL) || defined(CONFIG_BLUETOOTH_PERIPHERAL) +#include + +#include +#include + +/** Opaque type representing a connection to a remote device */ +struct bt_conn; + +/** Connection parameters for LE connections */ +struct bt_le_conn_param { + uint16_t interval_min; + uint16_t interval_max; + uint16_t latency; + uint16_t timeout; +}; + +/** Helper to declare connection parameters inline + * + * @param int_min Minimum Connection Interval (N * 1.25 ms) + * @param int_max Maximum Connection Interval (N * 1.25 ms) + * @param lat Connection Latency + * @param timeout Supervision Timeout (N * 10 ms) + */ +#define BT_LE_CONN_PARAM(int_min, int_max, lat, to) \ + (&(struct bt_le_conn_param) { \ + .interval_min = (int_min), \ + .interval_max = (int_max), \ + .latency = (lat), \ + .timeout = (to), \ + }) + +/** Default LE connection parameters: + * Connection Interval: 30-50 ms + * Latency: 0 + * Timeout: 4 s + */ +#define BT_LE_CONN_PARAM_DEFAULT BT_LE_CONN_PARAM(BT_GAP_INIT_CONN_INT_MIN, \ + BT_GAP_INIT_CONN_INT_MAX, \ + 0, 400) + +/** @brief Increment a connection's reference count. + * + * Increment the reference count of a connection object. + * + * @param conn Connection object. + * + * @return Connection object with incremented reference count. + */ +struct bt_conn *bt_conn_ref(struct bt_conn *conn); + +/** @brief Decrement a connection's reference count. + * + * Decrement the reference count of a connection object. + * + * @param conn Connection object. + */ +void bt_conn_unref(struct bt_conn *conn); + +/** @brief Look up an existing connection by address. + * + * Look up an existing connection based on the remote address. + * + * @param peer Remote address. + * + * @return Connection object or NULL if not found. The caller gets a + * new reference to the connection object which must be released with + * bt_conn_unref() once done using the object. + */ +struct bt_conn *bt_conn_lookup_addr_le(const bt_addr_le_t *peer); + +/** @brief Get destination (peer) address of a connection. + * + * @param conn Connection object. + * + * @return Destination address. + */ +const bt_addr_le_t *bt_conn_get_dst(const struct bt_conn *conn); + +/** Connection Type */ +enum { + BT_CONN_TYPE_LE, /** LE Connection Type */ +#if defined(CONFIG_BLUETOOTH_BREDR) + BT_CONN_TYPE_BR, /** BR/EDR Connection Type */ +#endif +}; + +/** LE Connection Info Structure */ +struct bt_conn_le_info { + const bt_addr_le_t *src; /** Source Address */ + const bt_addr_le_t *dst; /** Destination Address */ + uint16_t interval; /** Connection interval */ + uint16_t latency; /** Connection slave latency */ + uint16_t timeout; /** Connection supervision timeout */ +}; + +#if defined(CONFIG_BLUETOOTH_BREDR) +/** BR/EDR Connection Info Structure */ +struct bt_conn_br_info { + const bt_addr_t *dst; /** Destination BR/EDR address */ +}; +#endif + +/** Connection role (master or slave) */ +enum { + BT_CONN_ROLE_MASTER, + BT_CONN_ROLE_SLAVE, +}; + +/** Connection Info Structure */ +struct bt_conn_info { + /** Connection Type */ + uint8_t type; + + /** Connection Role */ + uint8_t role; + + union { + /** LE Connection specific Info */ + struct bt_conn_le_info le; +#if defined(CONFIG_BLUETOOTH_BREDR) + struct bt_conn_br_info br; +#endif + }; +}; + +/** @brief Get connection info + * + * @param conn Connection object. + * @param info Connection info object. + * + * @return Zero on success or (negative) error code on failure. + */ +int bt_conn_get_info(const struct bt_conn *conn, struct bt_conn_info *info); + +/** @brief Update the connection parameters. + * + * @param conn Connection object. + * @param param Updated connection parameters. + * + * @return Zero on success or (negative) error code on failure. + */ +int bt_conn_le_param_update(struct bt_conn *conn, + const struct bt_le_conn_param *param); + +/** @brief Disconnect from a remote device or cancel pending connection. + * + * Disconnect an active connection with the specified reason code or cancel + * pending outgoing connection. + * + * @param conn Connection to disconnect. + * @param reason Reason code for the disconnection. + * + * @return Zero on success or (negative) error code on failure. + */ +int bt_conn_disconnect(struct bt_conn *conn, uint8_t reason); + +#if defined(CONFIG_BLUETOOTH_CENTRAL) +/** @brief Initiate an LE connection to a remote device. + * + * Allows initiate new LE 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_le(const bt_addr_le_t *peer, + const struct bt_le_conn_param *param); + +/** @brief Automatically connect to remote device if it's in range. + * + * This function enables/disables automatic connection initiation. + * Everytime the device looses the connection with peer, this connection + * will be re-established if connectable advertisement from peer is received. + * + * @param addr Remote Bluetooth address. + * @param param If non-NULL, auto connect is enabled with the given + * parameters. If NULL, auto connect is disabled. + * + * @return Zero on success or error code otherwise. + */ +int bt_le_set_auto_conn(bt_addr_le_t *addr, + const struct bt_le_conn_param *param); +#endif /* CONFIG_BLUETOOTH_CENTRAL */ + +#if defined(CONFIG_BLUETOOTH_PERIPHERAL) +/** @brief Initiate directed advertising to a remote device + * + * Allows initiating a new LE connection to remote peer with the remote + * acting in central role and the local device in peripheral role. + * + * The advertising type must be either BT_LE_ADV_DIRECT_IND or + * BT_LE_ADV_DIRECT_IND_LOW_DUTY. + * + * In case of high duty cycle this will result in a callback with + * connected() with a new connection or with an error. + * + * The advertising may be cancelled with bt_conn_disconnect(). + * + * Returns a new reference that the the caller is responsible for managing. + * + * @param peer Remote address. + * @param param Directed advertising parameters. + * + * @return Valid connection object on success or NULL otherwise. + */ +struct bt_conn *bt_conn_create_slave_le(const bt_addr_le_t *peer, + const struct bt_le_adv_param *param); +#endif /* CONFIG_BLUETOOTH_PERIPHERAL */ + +/** Security level. */ +typedef enum __packed { + BT_SECURITY_LOW, /** No encryption and no authentication. */ + BT_SECURITY_MEDIUM, /** encryption and no authentication (no MITM). */ + BT_SECURITY_HIGH, /** encryption and authentication (MITM). */ + BT_SECURITY_FIPS, /** Authenticated LE Secure Connections and + * encryption. + */ +} bt_security_t; + +#if defined(CONFIG_BLUETOOTH_SMP) +/** @brief Set security level for a connection. + * + * This function enable security (encryption) for a connection. If device is + * already paired with sufficiently strong key encryption will be enabled. If + * link is already encrypted with sufficiently strong key this function does + * nothing. + * + * If device is not paired pairing will be initiated. If device is paired and + * keys are too weak but input output capabilities allow for strong enough keys + * pairing will be initiated. + * + * This function may return error if required level of security is not possible + * to achieve due to local or remote device limitation (eg input output + * capabilities). + * + * @param conn Connection object. + * @param sec Requested security level. + * + * @return 0 on success or negative error + */ +int bt_conn_security(struct bt_conn *conn, bt_security_t sec); + +/** @brief Get encryption key size. + * + * This function gets encryption key size. + * If there is no security (encryption) enabled 0 will be returned. + * + * @param conn Existing connection object. + * + * @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 */ + +/** Connection callback structure */ +struct bt_conn_cb { + void (*connected)(struct bt_conn *conn, uint8_t err); + void (*disconnected)(struct bt_conn *conn, uint8_t reason); + void (*le_param_updated)(struct bt_conn *conn, uint16_t interval, + uint16_t latency, uint16_t timeout); +#if defined(CONFIG_BLUETOOTH_SMP) + void (*identity_resolved)(struct bt_conn *conn, + const bt_addr_le_t *rpa, + const bt_addr_le_t *identity); + void (*security_changed)(struct bt_conn *conn, bt_security_t level); +#endif + struct bt_conn_cb *_next; +}; + +/** @brief Register connection callbacks. + * + * Register callbacks to monitor the state of connections. + * + * @param cb Callback struct. + */ +void bt_conn_cb_register(struct bt_conn_cb *cb); + +#endif /* CONFIG_BLUETOOTH_CENTRAL || CONFIG_BLUETOOTH_PERIPHERAL */ + +#if defined(CONFIG_BLUETOOTH_SMP) || defined(CONFIG_BLUETOOTH_BREDR) +/** Authenticated pairing callback structure */ +struct bt_conn_auth_cb { + void (*passkey_display)(struct bt_conn *conn, unsigned int passkey); + void (*passkey_entry)(struct bt_conn *conn); + void (*passkey_confirm)(struct bt_conn *conn, unsigned int passkey); + void (*cancel)(struct bt_conn *conn); +#if defined(CONFIG_BLUETOOTH_BREDR) + void (*pincode_entry)(struct bt_conn *conn, bool highsec); +#endif +}; + +/** @brief Register authentication callbacks. + * + * Register callbacks to handle authenticated pairing. Passing NULL unregisters + * previous callbacks structure. + * + * @param cb Callback struct. + * + * @return Zero on success or negative error code otherwise + */ +int bt_conn_auth_cb_register(const struct bt_conn_auth_cb *cb); + +/** @brief Reply with entered passkey. + * + * This function should be called only after passkey_entry callback from + * bt_conn_auth_cb structure was called. + * + * @param conn Connection object. + * @param passkey Entered passkey. + * + * @return Zero on success or negative error code otherwise + */ +int bt_conn_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey); + +/** @brief Cancel ongoing authenticated pairing. + * + * This function allows to cancel ongoing authenticated pairing. + * + * @param conn Connection object. + * + * @return Zero on success or negative error code otherwise + */ +int bt_conn_auth_cancel(struct bt_conn *conn); + +/** @brief Reply if passkey was confirmed 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. + * + * @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); + +#if defined(CONFIG_BLUETOOTH_BREDR) +/** @brief Reply with entered PIN code. + * + * This function should be called only after PIN code callback from + * bt_conn_auth_cb structure was called. It's for legacy 2.0 devices. + * + * @param conn Connection object. + * @param pin Entered PIN code. + * + * @return Zero on success or negative error code otherwise + */ +int bt_conn_auth_pincode_entry(struct bt_conn *conn, const char *pin); +#endif /* CONFIG_BLUETOOTH_BREDR */ +#endif /* CONFIG_BLUETOOTH_SMP || CONFIG_BLUETOOTH_BREDR */ + +#ifdef __cplusplus +} +#endif + +#endif /* __BT_CONN_H */ diff --git a/system/libarc32_arduino101/drivers/bluetooth/conn_internal.h b/system/libarc32_arduino101/drivers/bluetooth/conn_internal.h new file mode 100644 index 00000000..04c08839 --- /dev/null +++ b/system/libarc32_arduino101/drivers/bluetooth/conn_internal.h @@ -0,0 +1,125 @@ +/* + * 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. + */ + +typedef enum { + BT_CONN_DISCONNECTED, + BT_CONN_CONNECT_SCAN, + BT_CONN_CONNECT, + BT_CONN_CONNECTED, + BT_CONN_DISCONNECT, +} bt_conn_state_t; + +/* bt_conn flags: the flags defined here represent connection parameters */ +enum { + BT_CONN_AUTO_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; + + uint16_t latency; + uint16_t timeout; +#if 0 + uint8_t features[8]; +#endif +}; + +#if defined(CONFIG_BLUETOOTH_BREDR) +struct bt_conn_br { + bt_addr_t dst; +}; +#endif + +struct bt_conn { + uint16_t handle; + uint8_t type; + uint8_t role; + +#if defined(CONFIG_BLUETOOTH_SMP) + uint8_t encrypt; + bt_security_t sec_level; + bt_security_t required_sec_level; +#endif /* CONFIG_BLUETOOTH_SMP */ + + atomic_t ref; + + /* Connection error or reason for disconnect */ + uint8_t err; + + bt_conn_state_t state; + union { + struct bt_conn_le le; +#if defined(CONFIG_BLUETOOTH_BREDR) + struct bt_conn_br br; +#endif + }; +}; + +/* Add a new LE connection */ +struct bt_conn *bt_conn_add_le(const bt_addr_le_t *peer); + +#if defined(CONFIG_BLUETOOTH_BREDR) +/* Add a new BR/EDR connection */ +struct bt_conn *bt_conn_add_br(const bt_addr_t *peer); + +/* Look up an existing connection by BT address */ +struct bt_conn *bt_conn_lookup_addr_br(const bt_addr_t *peer); +#endif + +/* Look up an existing connection */ +struct bt_conn *bt_conn_lookup_handle(uint16_t handle); + +/* Look up a connection state. For BT_ADDR_LE_ANY, returns the first connection + * with the specific state + */ +struct bt_conn *bt_conn_lookup_state_le(const bt_addr_le_t *peer, + const bt_conn_state_t state); + +/* Set connection object in certain state and perform action related to state */ +void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state); + +void bt_conn_set_param_le(struct bt_conn *conn, + const struct bt_le_conn_param *param); + +int bt_conn_update_param_le(struct bt_conn *conn, + const struct bt_le_conn_param *param); + +int bt_conn_le_conn_update(struct bt_conn *conn, + const struct bt_le_conn_param *param); + +void notify_le_param_updated(struct bt_conn *conn); + +#if defined(CONFIG_BLUETOOTH_SMP) +/* rand and ediv should be in BT order */ +int bt_conn_le_start_encryption(struct bt_conn *conn, uint64_t rand, + uint16_t ediv, const uint8_t *ltk, size_t len); + +/* Notify higher layers that RPA was resolved */ +void bt_conn_identity_resolved(struct bt_conn *conn); + +/* Notify higher layers that connection security changed */ +void bt_conn_security_changed(struct bt_conn *conn); +#endif /* CONFIG_BLUETOOTH_SMP */ +/* Initialize connection management */ +int bt_conn_init(void); diff --git a/system/libarc32_arduino101/drivers/bluetooth/gatt.h b/system/libarc32_arduino101/drivers/bluetooth/gatt.h new file mode 100644 index 00000000..e9eac613 --- /dev/null +++ b/system/libarc32_arduino101/drivers/bluetooth/gatt.h @@ -0,0 +1,1045 @@ +/** @file + * @brief Generic Attribute Profile handling. + */ + +/* + * Copyright (c) 2015 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_GATT_H +#define __BT_GATT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(CONFIG_BLUETOOTH_CENTRAL) || defined(CONFIG_BLUETOOTH_PERIPHERAL) +#include +#include +#include +#include +#include +#include + +/* GATT attribute permission bit field values */ + +/** @def BT_GATT_PERM_READ + * @brief Attribute read permission. + */ +#define BT_GATT_PERM_READ 0x01 +/** @def BT_GATT_PERM_WRITE + * @brief Attribute write permission. + */ +#define BT_GATT_PERM_WRITE 0x02 +/** @def BT_GATT_PERM_READ_ENCRYPT + * @brief Attribute read permission with encryption. + * + * If set, requires encryption for read access. + */ +#define BT_GATT_PERM_READ_ENCRYPT 0x04 +/** @def BT_GATT_PERM_WRITE_ENCRYPT + * @brief Attribute write permission with encryption. + * + * If set, requires encryption for write access. + */ +#define BT_GATT_PERM_WRITE_ENCRYPT 0x08 +/** @def BT_GATT_PERM_READ_AUTHEN + * @brief Attribute read permission with authentication. + * + * If set, requires encryption using authenticated link-key for read access. + */ +#define BT_GATT_PERM_READ_AUTHEN 0x10 +/** @def BT_GATT_PERM_WRITE_AUTHEN + * @brief Attribute write permission with authentication. + * + * 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. + * + * If set, requires authorization for write access. + */ +#define BT_GATT_PERM_WRITE_AUTHOR 0x80 + +/* GATT attribute flush flags */ +/** @def BT_GATT_FLUSH_DISCARD + * @brief Attribute flush discard flag. + */ +#define BT_GATT_FLUSH_DISCARD 0x00 +/** @def BT_GATT_FLUSH_DISCARD + * @brief Attribute flush synchronize flag. + */ +#define BT_GATT_FLUSH_SYNC 0x01 + +/** @def BT_GATT_ERR + * @brief Construct error return value for attribute read, write and + * flush callbacks. + * + * @param _att_err ATT error code + * + * @return Appropriate error code for the attribute callbacks. + * + */ +#define BT_GATT_ERR(_att_err) (-(_att_err)) + +/** @brief GATT Attribute structure. */ +struct bt_gatt_attr { + /** Attribute UUID */ + const struct bt_uuid *uuid; + + /** Attribute read callback + * + * @param conn The connection that is requesting to read + * @param attr The attribute that's being read + * @param buf Buffer to place the read result in + * @param len Length of data to read + * @param offset Offset to start reading from + * + * @return Number fo bytes read, or in case of an error + * BT_GATT_ERR() with a specific ATT error code. + */ + ssize_t (*read)(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + void *buf, uint16_t len, + uint16_t offset); + + /** Attribute write callback + * + * @param conn The connection that is requesting to write + * @param attr The attribute that's being read + * @param buf Buffer with the data to write + * @param len Number of bytes in the buffer + * @param offset Offset to start writing from + * + * @return Number of bytes written, or in case of an error + * BT_GATT_ERR() with a specific ATT error code. + */ + ssize_t (*write)(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + const void *buf, uint16_t len, + uint16_t offset); + + /** Attribute flush callback + * + * If this callback is provided (non-NULL) every write + * operation will be followed by a call to it. The expectation + * is for the attribute implementation to only commit the write + * result once this is called. + * + * @param conn The connection that is requesting to write + * @param attr The attribute that's being read + * @param flags Flags (BT_GATT_FLUSH_*) + * + * @return Number of bytes flushed, or in case of an error + * BT_GATT_ERR() with a specific ATT error code. + */ + ssize_t (*flush)(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + uint8_t flags); + + /** Attribute user data */ + void *user_data; + /** Attribute handle */ + uint16_t handle; + /** Attribute permissions */ + uint8_t perm; +#if defined(CONFIG_BLUETOOTH_GATT_DYNAMIC_DB) + struct bt_gatt_attr *_next; +#endif /* CONFIG_BLUETOOTH_GATT_DYNAMIC_DB */ +}; + +/** @brief Service Attribute Value. */ +struct bt_gatt_service { + /** Service UUID. */ + const struct bt_uuid *uuid; + /** Service end handle. */ + uint16_t end_handle; +}; + +/** @brief Include Attribute Value. */ +struct bt_gatt_include { + /** Service UUID. */ + const struct bt_uuid *uuid; + /** Service start handle. */ + uint16_t start_handle; + /** Service end handle. */ + uint16_t end_handle; +}; + +/* Characteristic Properties Bit field values */ + +/** @def BT_GATT_CHRC_BROADCAST + * @brief Characteristic broadcast property. + * + * If set, permits broadcasts of the Characteristic Value using Server + * Characteristic Configuration Descriptor. + */ +#define BT_GATT_CHRC_BROADCAST 0x01 +/** @def BT_GATT_CHRC_READ + * @brief Characteristic read property. + * + * If set, permits reads of the Characteristic Value. + */ +#define BT_GATT_CHRC_READ 0x02 +/** @def BT_GATT_CHRC_WRITE_WITHOUT_RESP + * @brief Characteristic write without response property. + * + * If set, permits write of the Characteristic Value without response. + */ +#define BT_GATT_CHRC_WRITE_WITHOUT_RESP 0x04 +/** @def BT_GATT_CHRC_WRITE + * @brief Characteristic write with response property. + * + * If set, permits write of the Characteristic Value with response. + */ +#define BT_GATT_CHRC_WRITE 0x08 +/** @def BT_GATT_CHRC_NOTIFY + * @brief Characteristic notify property. + * + * If set, permits notifications of a Characteristic Value without + * acknowledgment. + */ +#define BT_GATT_CHRC_NOTIFY 0x10 +/** @def BT_GATT_CHRC_INDICATE + * @brief Characteristic indicate property. + * + * If set, permits indications of a Characteristic Value with acknowledgment. + */ +#define BT_GATT_CHRC_INDICATE 0x20 +/** @def BT_GATT_CHRC_AUTH + * @brief Characteristic Authenticated Signed Writes property. + * + * If set, permits signed writes to the Characteristic Value. + */ +#define BT_GATT_CHRC_AUTH 0x40 +/** @def BT_GATT_CHRC_EXT_PROP + * @brief Characteristic Extended Properties property. + * + * If set, additional characteristic properties are defined in the + * Characteristic Extended Properties Descriptor. + */ +#define BT_GATT_CHRC_EXT_PROP 0x80 + +/** @brief Characteristic Attribute Value. */ +struct bt_gatt_chrc { + /** Characteristic UUID. */ + const struct bt_uuid *uuid; + /** Characteristic properties. */ + uint8_t properties; +}; + +/* Characteristic Extended Properties Bit field values */ +#define BT_GATT_CEP_RELIABLE_WRITE 0x0001 +#define BT_GATT_CEP_WRITABLE_AUX 0x0002 + +/** @brief Characteristic Extended Properties Attribute Value. */ +struct bt_gatt_cep { + /** Characteristic Extended properties */ + uint16_t properties; +}; + +/* Client Characteristic Configuration Values */ + +/** @def BT_GATT_CCC_NOTIFY + * @brief Client Characteristic Configuration Notification. + * + * If set, changes to Characteristic Value shall be notified. + */ +#define BT_GATT_CCC_NOTIFY 0x0001 +/** @def BT_GATT_CCC_INDICATE + * @brief Client Characteristic Configuration Indication. + * + * If set, changes to Characteristic Value shall be indicated. + */ +#define BT_GATT_CCC_INDICATE 0x0002 + +/* Client Characteristic Configuration Attribute Value */ +struct bt_gatt_ccc { + /** Client Characteristic Configuration flags */ + uint16_t flags; +}; + +/** @brief GATT Characteristic Presentation Format Attribute Value. */ +struct bt_gatt_cpf { + /** Format of the value of the characteristic */ + uint8_t format; + /** Exponent field to determine how the value of this characteristic is further formatted */ + int8_t exponent; + /** Unit of the characteristic */ + uint16_t unit; + /** Name space of the description */ + uint8_t name_space; + /** Description of the characteristic as defined in a higher layer profile */ + uint16_t description; +} __packed; + +/* Server API */ + +/** @brief Register attribute database. + * + * Register GATT attribute database table. Applications can make use of + * macros such as BT_GATT_PRIMARY_SERVICE, BT_GATT_CHARACTERISTIC, + * BT_GATT_DESCRIPTOR, etc. + * + * @param attrs Database table containing the available attributes. + * @param count Size of the database table. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_gatt_register(struct bt_gatt_attr *attrs, size_t count); + +enum { + BT_GATT_ITER_STOP = 0, + BT_GATT_ITER_CONTINUE, +}; + +/** @brief Attribute iterator callback. + * + * @param attr Attribute found. + * @param user_data Data given. + * + * @return BT_GATT_ITER_CONTINUE if should continue to the next attribute + * or BT_GATT_ITER_STOP to stop. + */ +typedef uint8_t (*bt_gatt_attr_func_t)(const struct bt_gatt_attr *attr, + void *user_data); + +/** @brief Attribute iterator. + * + * Iterate attributes in the given range. + * + * @param start_handle Start handle. + * @param end_handle End handle. + * @param func Callback function. + * @param user_data Data to pass to the callback. + */ +void bt_gatt_foreach_attr(uint16_t start_handle, uint16_t end_handle, + bt_gatt_attr_func_t func, void *user_data); + +/** @brief Iterate to the next attribute + * + * Iterate to the next attribute following a given attribute. + * + * @param attr Current Attribute. + * + * @return The next attribute or NULL if it cannot be found. + */ +struct bt_gatt_attr *bt_gatt_attr_next(const struct bt_gatt_attr *attr); + +/** @brief Generic Read Attribute value helper. + * + * Read attribute value storing the result into buffer. + * + * @param conn Connection object. + * @param attr Attribute to read. + * @param buf Buffer to store the value. + * @param buf_len Buffer length. + * @param offset Start offset. + * @param value Attribute value. + * @param value_len Length of the attribute value. + * + * @return int number of bytes read in case of success or negative values in + * case of error. + */ +ssize_t bt_gatt_attr_read(struct bt_conn *conn, const struct bt_gatt_attr *attr, + void *buf, uint16_t buf_len, uint16_t offset, + const void *value, uint16_t value_len); + +/** @brief Read Service Attribute helper. + * + * Read service attribute value storing the result into buffer after + * enconding it. + * NOTE: Only use this with attributes which user_data is a bt_uuid. + * + * @param conn Connection object. + * @param attr Attribute to read. + * @param buf Buffer to store the value read. + * @param len Buffer length. + * @param offset Start offset. + * + * @return int number of bytes read in case of success or negative values in + * case of error. + */ +ssize_t bt_gatt_attr_read_service(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + void *buf, uint16_t len, uint16_t offset); + +/** @def BT_GATT_SERVICE + * @brief Generic Service Declaration Macro. + * + * Helper macro to declare a service attribute. + * + * @param _uuid Service attribute type. + * @param _data Service attribute value. + */ +#define BT_GATT_SERVICE(_uuid, _service) \ +{ \ + .uuid = _uuid, \ + .perm = BT_GATT_PERM_READ, \ + .read = bt_gatt_attr_read_service, \ + .user_data = _service, \ +} + +/** @def BT_GATT_PRIMARY_SERVICE + * @brief Primary Service Declaration Macro. + * + * Helper macro to declare a primary service attribute. + * + * @param _service Service attribute value. + */ +#define BT_GATT_PRIMARY_SERVICE(_service) \ +{ \ + .uuid = BT_UUID_GATT_PRIMARY, \ + .perm = BT_GATT_PERM_READ, \ + .read = bt_gatt_attr_read_service, \ + .user_data = _service, \ +} + +/** @def BT_GATT_SECONDARY_SERVICE + * @brief Secondary Service Declaration Macro. + * + * Helper macro to declare a secondary service attribute. + * + * @param _service Service attribute value. + */ +#define BT_GATT_SECONDARY_SERVICE(_service) \ +{ \ + .uuid = BT_UUID_GATT_SECONDARY, \ + .perm = BT_GATT_PERM_READ, \ + .read = bt_gatt_attr_read_service, \ + .user_data = _service, \ +} + +/** @brief Read Include Attribute helper. + * + * Read include service attribute value storing the result into buffer after + * enconding it. + * NOTE: Only use this with attributes which user_data is a bt_gatt_include. + * + * @param conn Connection object. + * @param attr Attribute to read. + * @param buf Buffer to store the value read. + * @param len Buffer length. + * @param offset Start offset. + * + * @return int number of bytes read in case of success or negative values in + * case of error. + */ +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); + +/** @def BT_GATT_INCLUDE_SERVICE + * @brief Include Service Declaration Macro. + * + * Helper macro to declare a include service attribute. + * + * @param _service Service attribute value. + */ +#define BT_GATT_INCLUDE_SERVICE(_service) \ +{ \ + .uuid = BT_UUID_GATT_INCLUDE, \ + .perm = BT_GATT_PERM_READ, \ + .read = bt_gatt_attr_read_included, \ + .user_data = _service, \ +} + +/** @brief Read Characteristic Attribute helper. + * + * Read characteristic attribute value storing the result into buffer after + * enconding it. + * NOTE: Only use this with attributes which user_data is a bt_gatt_chrc. + * + * @param conn Connection object. + * @param attr Attribute to read. + * @param buf Buffer to store the value read. + * @param len Buffer length. + * @param offset Start offset. + * + * @return number of bytes read in case of success or negative values in + * case of error. + */ +ssize_t bt_gatt_attr_read_chrc(struct bt_conn *conn, + const struct bt_gatt_attr *attr, void *buf, + uint16_t len, uint16_t offset); + +/** @def BT_GATT_CHARACTERISTIC + * @brief Characteristic Declaration Macro. + * + * Helper macro to declare a characteristic attribute. + * + * @param _uuid Characteristic attribute uuid. + * @param _props Characteristic attribute properties. + */ +#define BT_GATT_CHARACTERISTIC(_uuid, _props) \ +{ \ + .uuid = BT_UUID_GATT_CHRC, \ + .perm = BT_GATT_PERM_READ, \ + .read = bt_gatt_attr_read_chrc, \ + .user_data = (&(struct bt_gatt_chrc) { .uuid = _uuid, \ + .properties = _props, }),\ +} + +/** @brief GATT CCC configuration entry. */ +struct bt_gatt_ccc_cfg { + /** Config peer address. */ + bt_addr_le_t peer; + /** Config peer value. */ + uint16_t value; + /** Config valid flag. */ + uint8_t valid; +}; + +/* Internal representation of CCC value */ +struct _bt_gatt_ccc { + struct bt_gatt_ccc_cfg *cfg; + size_t cfg_len; + uint16_t value; + void (*cfg_changed)(uint16_t value); +}; + +/** @brief Read Client Characteristic Configuration Attribute helper. + * + * Read CCC attribute value storing the result into buffer after + * enconding it. + * NOTE: Only use this with attributes which user_data is a _bt_gatt_ccc. + * + * @param conn Connection object. + * @param attr Attribute to read. + * @param buf Buffer to store the value read. + * @param len Buffer length. + * @param offset Start offset. + * + * @return number of bytes read in case of success or negative values in + * case of error. + */ +ssize_t bt_gatt_attr_read_ccc(struct bt_conn *conn, + const struct bt_gatt_attr *attr, void *buf, + uint16_t len, uint16_t offset); + +/** @brief Write Client Characteristic Configuration Attribute helper. + * + * Write value in the buffer into CCC attribute. + * NOTE: Only use this with attributes which user_data is a _bt_gatt_ccc. + * + * @param conn Connection object. + * @param attr Attribute to read. + * @param buf Buffer to store the value read. + * @param len Buffer length. + * @param offset Start offset. + * + * @return number of bytes written in case of success or negative values in + * case of error. + */ +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); + +/** @def BT_GATT_CCC + * @brief Client Characteristic Configuration Declaration Macro. + * + * Helper macro to declare a CCC attribute. + * + * @param _cfg Initial configuration. + * @param _cfg_changed Configuration changed callback. + */ +#define BT_GATT_CCC(_cfg, _cfg_changed) \ +{ \ + .uuid = BT_UUID_GATT_CCC, \ + .perm = BT_GATT_PERM_READ | BT_GATT_PERM_WRITE, \ + .read = bt_gatt_attr_read_ccc, \ + .write = bt_gatt_attr_write_ccc, \ + .user_data = (&(struct _bt_gatt_ccc) { .cfg = _cfg, \ + .cfg_len = ARRAY_SIZE(_cfg), \ + .cfg_changed = _cfg_changed, }),\ +} + +/** @brief Read Characteristic Extended Properties Attribute helper + * + * Read CEP attribute value storing the result into buffer after + * encoding it. + * NOTE: Only use this with attributes which user_data is a bt_gatt_cep. + * + * @param conn Connection object + * @param attr Attribute to read + * @param buf Buffer to store the value read + * @param len Buffer length + * @param offset Start offset + * + * @return number of bytes read in case of success or negative values in + * case of error. + */ +ssize_t bt_gatt_attr_read_cep(struct bt_conn *conn, + const struct bt_gatt_attr *attr, void *buf, + uint16_t len, uint16_t offset); + +/** @def BT_GATT_CEP + * @brief Characteristic Extended Properties Declaration Macro. + * + * Helper macro to declare a CEP attribute. + * + * @param _value Descriptor attribute value. + */ +#define BT_GATT_CEP(_value) \ +{ \ + .uuid = BT_UUID_GATT_CEP, \ + .perm = BT_GATT_PERM_READ, \ + .read = bt_gatt_attr_read_cep, \ + .user_data = _value, \ +} + +/** @brief Read Characteristic User Description Descriptor Attribute helper + * + * Read CUD attribute value storing the result into buffer after + * encoding it. + * NOTE: Only use this with attributes which user_data is a NULL-terminated C string. + * + * @param conn Connection object + * @param attr Attribute to read + * @param buf Buffer to store the value read + * @param len Buffer length + * @param offset Start offset + * + * @return number of bytes read in case of success or negative values in + * case of error. + */ +ssize_t bt_gatt_attr_read_cud(struct bt_conn *conn, + const struct bt_gatt_attr *attr, void *buf, + uint16_t len, uint16_t offset); + +/** @def BT_GATT_CUD + * @brief Characteristic User Format Descriptor Declaration Macro. + * + * Helper macro to declare a CUD attribute. + * + * @param _value User description NULL-terminated C string. + * @param _perm Descriptor attribute access permissions. + */ +#define BT_GATT_CUD(_value, _perm) \ +{ \ + .uuid = BT_UUID_GATT_CUD, \ + .perm = _perm, \ + .read = bt_gatt_attr_read_cud, \ + .user_data = _value, \ +} + +/** @brief Read Characteristic Presentation format Descriptor Attribute helper + * + * Read CPF attribute value storing the result into buffer after + * encoding it. + * NOTE: Only use this with attributes which user_data is a bt_gatt_pf. + * + * @param conn Connection object + * @param attr Attribute to read + * @param buf Buffer to store the value read + * @param len Buffer length + * @param offset Start offset + * + * @return number of bytes read in case of success or negative values in + * case of error. + */ +ssize_t bt_gatt_attr_read_cpf(struct bt_conn *conn, + const struct bt_gatt_attr *attr, void *buf, + uint16_t len, uint16_t offset); + +/** @def BT_GATT_CPF + * @brief Characteristic Presentation Format Descriptor Declaration Macro. + * + * Helper macro to declare a CPF attribute. + * + * @param _value Descriptor attribute value. + */ +#define BT_GATT_CPF(_value) \ +{ \ + .uuid = BT_UUID_GATT_CPF, \ + .perm = BT_GATT_PERM_READ, \ + .read = bt_gatt_attr_read_cpf, \ + .user_data = _value, \ +} + +/** @def BT_GATT_DESCRIPTOR + * @brief Descriptor Declaration Macro. + * + * Helper macro to declare a descriptor attribute. + * + * @param _uuid Descriptor attribute uuid. + * @param _perm Descriptor attribute access permissions. + * @param _read Descriptor attribute read callback. + * @param _write Descriptor attribute write callback. + * @param _value Descriptor attribute value. + */ +#define BT_GATT_DESCRIPTOR(_uuid, _perm, _read, _write, _value) \ +{ \ + .uuid = _uuid, \ + .perm = _perm, \ + .read = _read, \ + .write = _write, \ + .user_data = _value, \ +} + +/** @def BT_GATT_LONG_DESCRIPTOR + * @brief Descriptor Declaration Macro. + * + * Helper macro to declare a descriptor attribute. + * + * @param _uuid Descriptor attribute uuid. + * @param _perm Descriptor attribute access permissions. + * @param _read Descriptor attribute read callback. + * @param _write Descriptor attribute write callback. + * @param _flush Descriptor attribute flush callback. + * @param _value Descriptor attribute value. + */ +#define BT_GATT_LONG_DESCRIPTOR(_uuid, _perm, _read, _write, _flush, _value) \ +{ \ + .uuid = _uuid, \ + .perm = _perm, \ + .read = _read, \ + .write = _write, \ + .flush = _flush, \ + .user_data = _value, \ +} + +/** @brief Notify sent callback + * + * This means that the complete attribute has been sent. This does not mean it + * has been received however (use indicate for this). + * This shall be used to flow control the callee to avoid flooding the ble + * controller. + * + * @param conn Connection object. + * @param attr Attribute object. + * @param err 0 if none + */ +typedef void (*bt_gatt_notify_sent_func_t)(struct bt_conn *conn, struct bt_gatt_attr *attr, + uint8_t err); + +/** @brief Notify attribute value change. + * + * Send notification of attribute value change, if connection is NULL notify + * all peer that have notification enabled via CCC otherwise do a direct + * notification only the given connection. + * + * @param conn Connection object. + * @param attr Attribute object. + * @param value Attribute value. + * @param len Attribute value length. + * @param cb callback function called when send is complete (or NULL) + */ +int bt_gatt_notify(struct bt_conn *conn, const struct bt_gatt_attr *attr, + const void *data, uint16_t len, + bt_gatt_notify_sent_func_t cb); + +/** @brief Indication complete result callback. + * + * @param conn Connection object. + * @param attr Attribute object. + * @param err: 0 success, error in the other case + */ +typedef void (*bt_gatt_indicate_func_t)(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + int err); + +/** @brief GATT Indicate Value parameters */ +struct bt_gatt_indicate_params { + /** Indicate Attribute object*/ + const struct bt_gatt_attr *attr; + /** Indicate Value callback */ + bt_gatt_indicate_func_t func; + /** Indicate Value data*/ + const void *data; + /** Indicate Value length*/ + uint16_t len; +}; + +/** @brief Indicate attribute value change. + * + * Send an indication of attribute value change. + * Note: This function should only be called if CCC is declared with + * BT_GATT_CCC otherwise it cannot find a valid peer configuration. + * + * Note: This procedure is asynchronous therefore the parameters need to + * remains valid while it is active. + * + * @param conn Connection object. + * @param params Indicate parameters. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_gatt_indicate(struct bt_conn *conn, + struct bt_gatt_indicate_params *params); + +#if defined(CONFIG_BLUETOOTH_GATT_CLIENT) +/* Client API */ + +/** @brief Response callback function + * + * @param conn Connection object. + * @param err Error code. + */ +typedef void (*bt_gatt_rsp_func_t)(struct bt_conn *conn, uint8_t err); + +/** @brief Exchange MTU + * + * This client procedure can be used to set the MTU to the maximum possible + * size the buffers can hold. + * NOTE: Shall only be used once per connection. + * + * @param conn Connection object. + * @param func Exchange MTU Response callback function. + */ +int bt_gatt_exchange_mtu(struct bt_conn *conn, bt_gatt_rsp_func_t func); + +struct bt_gatt_discover_params; + +/** @brief Discover attribute callback function. + * + * @param conn Connection object. + * @param attr Attribute found. + * @param params Discovery parameters given. + * + * If discovery procedure has completed this callback will be called with + * attr set to NULL. This will not happen if procedure was stopped by returning + * BT_GATT_ITER_STOP. + * + * @return BT_GATT_ITER_CONTINUE if should continue attribute discovery + * or BT_GATT_ITER_STOP to stop discovery procedure. + */ +typedef uint8_t (*bt_gatt_discover_func_t)(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + struct bt_gatt_discover_params *params); + +enum { + BT_GATT_DISCOVER_PRIMARY, + BT_GATT_DISCOVER_SECONDARY, + BT_GATT_DISCOVER_INCLUDE, + BT_GATT_DISCOVER_CHARACTERISTIC, + BT_GATT_DISCOVER_DESCRIPTOR, +}; + +/** @brief GATT Discover Attributes parameters */ +struct bt_gatt_discover_params { + /** Discover UUID type */ + struct bt_uuid *uuid; + /** Discover attribute callback */ + bt_gatt_discover_func_t func; + /** Discover start handle */ + uint16_t start_handle; + /** Discover end handle */ + uint16_t end_handle; + /** Discover type */ + uint8_t type; +}; + +/** @brief GATT Discover function + * + * This procedure is used by a client to discover attributes on a server. + * + * Primary Service Discovery: Procedure allows to discover specific Primary + * Service based on UUID. + * Include Service Discovery: Procedure allows to discover all Include Services + * within specified range. + * Characteristic Discovery: Procedure allows to discover all characteristics + * within specified handle range as well as + * discover characteristics with specified UUID. + * Descriptors Discovery: Procedure allows to discover all characteristic + * descriptors within specified range. + * + * For each attribute found the callback is called which can then decide + * whether to continue discovering or stop. + * + * Note: This procedure is asynchronous therefore the parameters need to + * remains valid while it is active. + * + * @param conn Connection object. + * @param params Discover parameters. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_gatt_discover(struct bt_conn *conn, + struct bt_gatt_discover_params *params); + +struct bt_gatt_read_params; + +/** @brief Read callback function + * + * @param conn Connection object. + * @param err 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, + struct bt_gatt_read_params *params, + const void *data, uint16_t length); + +/** @brief GATT Read parameters */ +struct bt_gatt_read_params { + /** Read attribute callback */ + bt_gatt_read_func_t func; + /** Handles count. + * If equals to 1 single.handle and single.offset are used. + * If >1 Read Multiple Characteristic Values is performed and handles + * are used. + */ + size_t handle_count; + union { + struct { + /** Attribute handle */ + uint16_t handle; + /** Attribute data offset */ + uint16_t offset; + } single; + /** Handles to read in Read Multiple Characteristic Values */ + uint16_t *handles; + }; +}; + +/** @brief Read Attribute Value by handle + * + * This procedure read the attribute value and return it to the callback. + * + * Note: This procedure is asynchronous therefore the parameters need to + * remains valid while it is active. + * + * @param conn Connection object. + * @param params Read parameters. + * + * @return 0 in case of success or negative value in case of error. + */ +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 Write Attribute Value by handle + * + * This procedure write the attribute value and return the result in the + * callback. + * + * @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. + * + * @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); + +/** @brief Write Attribute Value by handle without response + * + * This procedure write the attribute value without requiring an + * acknowledgement that the write was successfully performed + * + * @param conn Connection object. + * @param handle Attribute handle. + * @param data Data to be written. + * @param length Data length. + * @param sign Whether to sign data + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_gatt_write_without_response(struct bt_conn *conn, uint16_t handle, + const void *data, uint16_t length, + bool sign); + +struct bt_gatt_subscribe_params; + +/** @brief Notification callback function + * + * @param conn Connection object. + * @param params Subscription parameters. + * @param data Attribute value data. If NULL then subscription was removed. + * @param length Attribute value length. + */ +typedef uint8_t (*bt_gatt_notify_func_t)(struct bt_conn *conn, + struct bt_gatt_subscribe_params *params, + const void *data, uint16_t length); + +/** @brief GATT Subscribe parameters */ +struct bt_gatt_subscribe_params { + bt_addr_le_t _peer; + /** Notification value callback */ + bt_gatt_notify_func_t notify; + /** Subscribe value handle */ + uint16_t value_handle; + /** Subscribe CCC handle */ + uint16_t ccc_handle; + /** Subscribe value */ + uint16_t value; + struct bt_gatt_subscribe_params *_next; +}; + +/** @brief Subscribe Attribute Value Notification + * + * This procedure subscribe to value notification using the Client + * Characteristic Configuration handle. + * If notification received subscribe value callback is called to return + * notified value. One may then decide whether to unsubscribe directly from + * this callback. Notification callback with NULL data will not be called if + * subscription was removed by this method. + * + * Note: This procedure is asynchronous therefore the parameters need to + * remains valid while it is active. + * + * @param conn Connection object. + * @param params Subscribe parameters. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_gatt_subscribe(struct bt_conn *conn, + struct bt_gatt_subscribe_params *params); + +/** @brief Unsubscribe Attribute Value Notification + * + * This procedure unsubscribe to value notification using the Client + * Characteristic Configuration handle. Notification callback with NULL data + * will not be called if subscription was removed by this call. + * + * @param conn Connection object. + * @param params Subscribe parameters. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_gatt_unsubscribe(struct bt_conn *conn, + struct bt_gatt_subscribe_params *params); + +/** @brief Cancel GATT pending request + * + * @param conn Connection object. + */ +void bt_gatt_cancel(struct bt_conn *conn); + +#endif /* CONFIG_BLUETOOTH_GATT_CLIENT */ +#endif /* CONFIG_BLUETOOTH_CENTRAL || CONFIG_BLUETOOTH_PERIPHERAL */ + +#ifdef __cplusplus +} +#endif + +#endif /* __BT_GATT_H */ diff --git a/system/libarc32_arduino101/drivers/bluetooth/hci.h b/system/libarc32_arduino101/drivers/bluetooth/hci.h new file mode 100644 index 00000000..f7ff52c1 --- /dev/null +++ b/system/libarc32_arduino101/drivers/bluetooth/hci.h @@ -0,0 +1,683 @@ +/* hci.h - Bluetooth Host Control Interface definitions */ + +/* + * Copyright (c) 2015 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_HCI_H +#define __BT_HCI_H + +//#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define BT_ADDR_LE_PUBLIC 0x00 +#define BT_ADDR_LE_RANDOM 0x01 + +typedef struct { + uint8_t val[6]; +} bt_addr_t; + +typedef struct { + uint8_t type; + uint8_t val[6]; +} 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} }) + +static inline int bt_addr_cmp(const bt_addr_t *a, const bt_addr_t *b) +{ + return memcmp(a, b, sizeof(*a)); +} + +static inline int bt_addr_le_cmp(const bt_addr_le_t *a, const bt_addr_le_t *b) +{ + return memcmp(a, b, sizeof(*a)); +} + +static inline void bt_addr_copy(bt_addr_t *dst, const bt_addr_t *src) +{ + memcpy(dst, src, sizeof(*dst)); +} + +static inline void bt_addr_le_copy(bt_addr_le_t *dst, const bt_addr_le_t *src) +{ + memcpy(dst, src, sizeof(*dst)); +} + +/* HCI Error Codes */ +#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_REMOTE_USER_TERM_CONN 0x13 +#define BT_HCI_ERR_PAIRING_NOT_ALLOWED 0x18 +#define BT_HCI_ERR_UNSUPP_REMOTE_FEATURE 0x1a +#define BT_HCI_ERR_INVALID_LL_PARAMS 0x1e +#define BT_HCI_ERR_UNSPECIFIED 0x1f +#define BT_HCI_ERR_PAIRING_NOT_SUPPORTED 0x29 +#define BT_HCI_ERR_UNACCEPT_CONN_PARAMS 0x3b +#define BT_HCI_ERR_DIRECTED_ADV_TIMEOUT 0x3c + +/* EIR/AD data type definitions */ +#define BT_DATA_FLAGS 0x01 /* AD flags */ +#define BT_DATA_UUID16_SOME 0x02 /* 16-bit UUID, more available */ +#define BT_DATA_UUID16_ALL 0x03 /* 16-bit UUID, all listed */ +#define BT_DATA_UUID32_SOME 0x04 /* 32-bit UUID, more available */ +#define BT_DATA_UUID32_ALL 0x05 /* 32-bit UUID, all listed */ +#define BT_DATA_UUID128_SOME 0x06 /* 128-bit UUID, more available */ +#define BT_DATA_UUID128_ALL 0x07 /* 128-bit UUID, all listed */ +#define BT_DATA_NAME_SHORTENED 0x08 /* Shortened name */ +#define BT_DATA_NAME_COMPLETE 0x09 /* Complete name */ +#define BT_DATA_TX_POWER 0x0a /* Tx Power */ +#define BT_DATA_SOLICIT16 0x14 /* Solicit UUIDs, 16-bit */ +#define BT_DATA_SOLICIT128 0x15 /* Solicit UUIDs, 128-bit */ +#define BT_DATA_SVC_DATA16 0x16 /* Service data, 16-bit UUID */ +#define BT_DATA_GAP_APPEARANCE 0x19 /* GAP appearance */ +#define BT_DATA_SOLICIT32 0x1f /* Solicit UUIDs, 32-bit */ +#define BT_DATA_SVC_DATA32 0x20 /* Service data, 32-bit UUID */ +#define BT_DATA_SVC_DATA128 0x21 /* Service data, 128-bit UUID */ +#define BT_DATA_MANUFACTURER_DATA 0xff /* Manufacturer Specific Data */ + +#define BT_LE_AD_LIMITED 0x01 /* Limited Discoverable */ +#define BT_LE_AD_GENERAL 0x02 /* General Discoverable */ +#define BT_LE_AD_NO_BREDR 0x04 /* BR/EDR not supported */ + +struct bt_hci_evt_hdr { + uint8_t evt; + uint8_t len; +} __packed; + +#define BT_ACL_START_NO_FLUSH 0x00 +#define BT_ACL_CONT 0x01 +#define BT_ACL_START 0x02 + +#define bt_acl_handle(h) ((h) & 0x0fff) +#define bt_acl_flags(h) ((h) >> 12) +#define bt_acl_handle_pack(h, f) ((h) | ((f) << 12)) + +struct bt_hci_acl_hdr { + uint16_t handle; + uint16_t len; +} __packed; + +struct bt_hci_cmd_hdr { + uint16_t opcode; + uint8_t param_len; +} __packed; + +/* LMP features */ +#define BT_LMP_NO_BREDR 0x20 +#define BT_LMP_LE 0x40 + +/* LE features */ +#define BT_HCI_LE_ENCRYPTION 0x01 +#define BT_HCI_LE_CONN_PARAM_REQ_PROC 0x02 +#define BT_HCI_LE_SLAVE_FEATURES 0x08 + +/* Bonding/authentication types */ +#define BT_HCI_NO_BONDING 0x00 +#define BT_HCI_NO_BONDING_MITM 0x01 +#define BT_HCI_DEDICATED_BONDING 0x02 +#define BT_HCI_DEDICATED_BONDING_MITM 0x03 +#define BT_HCI_GENERAL_BONDING 0x04 +#define BT_HCI_GENERAL_BONDING_MITM 0x05 + +/* I/O capabilities */ +#define BT_IO_DISPLAY_ONLY 0x00 +#define BT_IO_DISPLAY_YESNO 0x01 +#define BT_IO_KEYBOARD_ONLY 0x02 +#define BT_IO_NO_INPUT_OUTPUT 0x03 + +/* Defined GAP timers */ +#define BT_GAP_SCAN_FAST_INTERVAL 0x0060 /* 60 ms */ +#define BT_GAP_SCAN_FAST_WINDOW 0x0030 /* 30 ms */ +#define BT_GAP_SCAN_SLOW_INTERVAL_1 0x0800 /* 1.28 s */ +#define BT_GAP_SCAN_SLOW_WINDOW_1 0x0012 /* 11.25 ms */ +#define BT_GAP_SCAN_SLOW_INTERVAL_2 0x1000 /* 2.56 s */ +#define BT_GAP_SCAN_SLOW_WINDOW_2 0x0012 /* 11.25 ms */ +#define BT_GAP_ADV_FAST_INT_MIN_1 0x0030 /* 30 ms */ +#define BT_GAP_ADV_FAST_INT_MAX_1 0x0060 /* 60 ms */ +#define BT_GAP_ADV_FAST_INT_MIN_2 0x00a0 /* 100 ms */ +#define BT_GAP_ADV_FAST_INT_MAX_2 0x00f0 /* 150 ms */ +#define BT_GAP_ADV_SLOW_INT_MIN 0x0640 /* 1 s */ +#define BT_GAP_ADV_SLOW_INT_MAX 0x0780 /* 1.2 s */ +#define BT_GAP_INIT_CONN_INT_MIN 0x0018 /* 30 ms */ +#define BT_GAP_INIT_CONN_INT_MAX 0x0028 /* 50 ms */ + +/* HCI BR/EDR link types */ +#define BT_HCI_SCO 0x00 +#define BT_HCI_ACL 0x01 +#define BT_HCI_ESCO 0x02 + +/* OpCode Group Fields */ +#define BT_OGF_LINK_CTRL 0x01 +#define BT_OGF_BASEBAND 0x03 +#define BT_OGF_INFO 0x04 +#define BT_OGF_LE 0x08 + +/* Construct OpCode from OGF and OCF */ +#define BT_OP(ogf, ocf) ((ocf) | ((ogf) << 10)) + +#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_ACCEPT_CONN_REQ BT_OP(BT_OGF_LINK_CTRL, 0x0009) +struct bt_hci_cp_accept_conn_req { + bt_addr_t bdaddr; + uint8_t role; +} __packed; + +#define BT_HCI_OP_REJECT_CONN_REQ BT_OP(BT_OGF_LINK_CTRL, 0x000a) +struct bt_hci_cp_reject_conn_req { + bt_addr_t bdaddr; + uint8_t reason; +} __packed; + +#define BT_HCI_OP_LINK_KEY_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x000b) +struct bt_hci_cp_link_key_reply { + bt_addr_t bdaddr; + uint8_t link_key[16]; +} __packed; + +#define BT_HCI_OP_LINK_KEY_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x000c) +struct bt_hci_cp_link_key_neg_reply { + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_PIN_CODE_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x000d) +struct bt_hci_cp_pin_code_reply { + bt_addr_t bdaddr; + uint8_t pin_len; + uint8_t pin_code[16]; +} __packed; +struct bt_hci_rp_pin_code_reply { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_PIN_CODE_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x000e) +struct bt_hci_cp_pin_code_neg_reply { + bt_addr_t bdaddr; +} __packed; +struct bt_hci_rp_pin_code_neg_reply { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_IO_CAPABILITY_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x002b) +struct bt_hci_cp_io_capability_reply { + bt_addr_t bdaddr; + uint8_t capability; + uint8_t oob_data; + uint8_t authentication; +} __packed; + +#define BT_HCI_OP_IO_CAPABILITY_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x0034) +struct bt_hci_cp_io_capability_neg_reply { + bt_addr_t bdaddr; + uint8_t reason; +} __packed; + +#define BT_HCI_OP_SET_EVENT_MASK BT_OP(BT_OGF_BASEBAND, 0x0001) +struct bt_hci_cp_set_event_mask { + uint8_t events[8]; +} __packed; + +#define BT_HCI_OP_RESET BT_OP(BT_OGF_BASEBAND, 0x0003) + +#define BT_HCI_OP_WRITE_SCAN_ENABLE BT_OP(BT_OGF_BASEBAND, 0x001a) +#define BT_BREDR_SCAN_DISABLED 0x00 +#define BT_BREDR_SCAN_INQUIRY 0x01 +#define BT_BREDR_SCAN_PAGE 0x02 + +#define BT_HCI_CTL_TO_HOST_FLOW_ENABLE 0x01 +#define BT_HCI_OP_SET_CTL_TO_HOST_FLOW BT_OP(BT_OGF_BASEBAND, 0x0031) + +#define BT_HCI_OP_HOST_BUFFER_SIZE BT_OP(BT_OGF_BASEBAND, 0x0033) +struct bt_hci_cp_host_buffer_size { + uint16_t acl_mtu; + uint8_t sco_mtu; + uint16_t acl_pkts; + uint16_t sco_pkts; +} __packed; + +struct bt_hci_handle_count { + uint16_t handle; + uint16_t count; +} __packed; + +#define BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS BT_OP(BT_OGF_BASEBAND, 0x0035) +struct bt_hci_cp_host_num_completed_packets { + uint8_t num_handles; + struct bt_hci_handle_count h[0]; +} __packed; + +#define BT_HCI_OP_WRITE_SSP_MODE BT_OP(BT_OGF_BASEBAND, 0x0056) +struct bt_hci_cp_write_ssp_mode { + uint8_t mode; +} __packed; + +#define BT_HCI_OP_LE_WRITE_LE_HOST_SUPP BT_OP(BT_OGF_BASEBAND, 0x006d) +struct bt_hci_cp_write_le_host_supp { + uint8_t le; + uint8_t simul; +} __packed; + +#define BT_HCI_OP_READ_LOCAL_VERSION_INFO BT_OP(BT_OGF_INFO, 0x0001) +struct bt_hci_rp_read_local_version_info { + uint8_t status; + uint8_t hci_version; + uint16_t hci_revision; + uint8_t lmp_version; + uint16_t manufacturer; + uint16_t lmp_subversion; +} __packed; + +#define BT_HCI_OP_READ_SUPPORTED_COMMANDS BT_OP(BT_OGF_INFO, 0x0002) +struct bt_hci_rp_read_supported_commands { + uint8_t status; + uint8_t commands[36]; +} __packed; + +#define BT_HCI_OP_READ_LOCAL_FEATURES BT_OP(BT_OGF_INFO, 0x0003) +struct bt_hci_rp_read_local_features { + uint8_t status; + uint8_t features[8]; +} __packed; + +#define BT_HCI_OP_READ_BUFFER_SIZE BT_OP(BT_OGF_INFO, 0x0005) +struct bt_hci_rp_read_buffer_size { + uint8_t status; + uint16_t acl_max_len; + uint8_t sco_max_len; + uint16_t acl_max_num; + uint16_t sco_max_num; +} __packed; + +#define BT_HCI_OP_READ_BD_ADDR BT_OP(BT_OGF_INFO, 0x0009) +struct bt_hci_rp_read_bd_addr { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_LE_SET_EVENT_MASK BT_OP(BT_OGF_LE, 0x0001) +struct bt_hci_cp_le_set_event_mask { + uint8_t events[8]; +} __packed; +struct bt_hci_rp_le_set_event_mask { + uint8_t status; +} __packed; + +#define BT_HCI_OP_LE_READ_BUFFER_SIZE BT_OP(BT_OGF_LE, 0x0002) +struct bt_hci_rp_le_read_buffer_size { + uint8_t status; + uint16_t le_max_len; + uint8_t le_max_num; +} __packed; + +#define BT_HCI_OP_LE_READ_LOCAL_FEATURES BT_OP(BT_OGF_LE, 0x0003) +struct bt_hci_rp_le_read_local_features { + uint8_t status; + uint8_t features[8]; +} __packed; + +#define BT_HCI_OP_LE_SET_RANDOM_ADDRESS BT_OP(BT_OGF_LE, 0x0005) + +/* Advertising types */ +#define BT_LE_ADV_IND 0x00 +#define BT_LE_ADV_DIRECT_IND 0x01 +#define BT_LE_ADV_SCAN_IND 0x02 +#define BT_LE_ADV_NONCONN_IND 0x03 +#define BT_LE_ADV_DIRECT_IND_LOW_DUTY 0x04 +/* 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 { + uint16_t min_interval; + uint16_t max_interval; + uint8_t type; + uint8_t own_addr_type; + bt_addr_le_t direct_addr; + uint8_t channel_map; + uint8_t filter_policy; +} __packed; + +#define BT_HCI_OP_LE_SET_ADV_DATA BT_OP(BT_OGF_LE, 0x0008) +struct bt_hci_cp_le_set_adv_data { + uint8_t len; + uint8_t data[31]; +} __packed; + +#define BT_HCI_OP_LE_SET_SCAN_RSP_DATA BT_OP(BT_OGF_LE, 0x0009) +struct bt_hci_cp_le_set_scan_rsp_data { + uint8_t len; + uint8_t data[31]; +} __packed; + +#define BT_HCI_LE_ADV_DISABLE 0x00 +#define BT_HCI_LE_ADV_ENABLE 0x01 + +#define BT_HCI_OP_LE_SET_ADV_ENABLE BT_OP(BT_OGF_LE, 0x000a) +struct bt_hci_cp_le_set_adv_enable { + uint8_t enable; +} __packed; + +/* Scan types */ +#define BT_HCI_OP_LE_SET_SCAN_PARAMS BT_OP(BT_OGF_LE, 0x000b) +#define BT_HCI_LE_SCAN_PASSIVE 0x00 +#define BT_HCI_LE_SCAN_ACTIVE 0x01 + +struct bt_hci_cp_le_set_scan_params { + uint8_t scan_type; + uint16_t interval; + uint16_t window; + uint8_t addr_type; + uint8_t filter_policy; +} __packed; + +#define BT_HCI_OP_LE_SET_SCAN_ENABLE BT_OP(BT_OGF_LE, 0x000c) + +#define BT_HCI_LE_SCAN_DISABLE 0x00 +#define BT_HCI_LE_SCAN_ENABLE 0x01 + +#define BT_HCI_LE_SCAN_FILTER_DUP_DISABLE 0x00 +#define BT_HCI_LE_SCAN_FILTER_DUP_ENABLE 0x01 + +struct bt_hci_cp_le_set_scan_enable { + uint8_t enable; + uint8_t filter_dup; +} __packed; + +#define BT_HCI_OP_LE_CREATE_CONN BT_OP(BT_OGF_LE, 0x000d) +struct bt_hci_cp_le_create_conn { + uint16_t scan_interval; + uint16_t scan_window; + uint8_t filter_policy; + bt_addr_le_t peer_addr; + uint8_t own_addr_type; + uint16_t conn_interval_min; + uint16_t conn_interval_max; + uint16_t conn_latency; + uint16_t supervision_timeout; + uint16_t min_ce_len; + uint16_t max_ce_len; +} __packed; + +#define BT_HCI_OP_LE_CREATE_CONN_CANCEL BT_OP(BT_OGF_LE, 0x000e) + +#define BT_HCI_OP_LE_CONN_UPDATE BT_OP(BT_OGF_LE, 0x0013) +struct hci_cp_le_conn_update { + uint16_t handle; + uint16_t conn_interval_min; + uint16_t conn_interval_max; + uint16_t conn_latency; + uint16_t supervision_timeout; + uint16_t min_ce_len; + uint16_t max_ce_len; +} __packed; + +#define BT_HCI_OP_LE_READ_REMOTE_FEATURES BT_OP(BT_OGF_LE, 0x0016) +struct bt_hci_cp_le_read_remote_features { + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_ENCRYPT BT_OP(BT_OGF_LE, 0x0017) +struct bt_hci_cp_le_encrypt { + uint8_t key[16]; + uint8_t plaintext[16]; +} __packed; +struct bt_hci_rp_le_encrypt { + uint8_t status; + uint8_t enc_data[16]; +} __packed; + +#define BT_HCI_OP_LE_RAND BT_OP(BT_OGF_LE, 0x0018) +struct bt_hci_rp_le_rand { + uint8_t status; + uint8_t rand[8]; +} __packed; + +#define BT_HCI_OP_LE_START_ENCRYPTION BT_OP(BT_OGF_LE, 0x0019) +struct bt_hci_cp_le_start_encryption { + uint16_t handle; + uint64_t rand; + uint16_t ediv; + uint8_t ltk[16]; +} __packed; + +#define BT_HCI_OP_LE_LTK_REQ_REPLY BT_OP(BT_OGF_LE, 0x001a) +struct bt_hci_cp_le_ltk_req_reply { + uint16_t handle; + uint8_t ltk[16]; +} __packed; + +#define BT_HCI_OP_LE_LTK_REQ_NEG_REPLY BT_OP(BT_OGF_LE, 0x001b) +struct bt_hci_cp_le_ltk_req_neg_reply { + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_CONN_PARAM_REQ_REPLY BT_OP(BT_OGF_LE, 0x0020) +struct bt_hci_cp_le_conn_param_req_reply { + uint16_t handle; + uint16_t interval_min; + uint16_t interval_max; + uint16_t latency; + uint16_t timeout; + uint16_t min_ce_len; + uint16_t max_ce_len; +} __packed; + +#define BT_HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY BT_OP(BT_OGF_LE, 0x0021) +struct bt_hci_cp_le_conn_param_req_neg_reply { + uint16_t handle; + uint8_t reason; +} __packed; + +#define BT_HCI_OP_LE_P256_PUBLIC_KEY BT_OP(BT_OGF_LE, 0x0025) + +#define BT_HCI_OP_LE_GENERATE_DHKEY BT_OP(BT_OGF_LE, 0x0026) +struct bt_hci_cp_le_generate_dhkey { + uint8_t key[64]; +} __packed; + +/* Event definitions */ + +#define BT_HCI_EVT_CONN_COMPLETE 0x03 +struct bt_hci_evt_conn_complete { + uint8_t status; + uint16_t handle; + bt_addr_t bdaddr; + uint8_t link_type; + uint8_t encr_enabled; +} __packed; + +#define BT_HCI_EVT_CONN_REQUEST 0x04 +struct bt_hci_evt_conn_request { + bt_addr_t bdaddr; + uint8_t dev_class[3]; + uint8_t link_type; +} __packed; + +#define BT_HCI_EVT_DISCONN_COMPLETE 0x05 +struct bt_hci_evt_disconn_complete { + uint8_t status; + uint16_t handle; + uint8_t reason; +} __packed; + +#define BT_HCI_EVT_ENCRYPT_CHANGE 0x08 +struct bt_hci_evt_encrypt_change { + uint8_t status; + uint16_t handle; + uint8_t encrypt; +} __packed; + +#define BT_HCI_EVT_CMD_COMPLETE 0x0e +struct hci_evt_cmd_complete { + uint8_t ncmd; + uint16_t opcode; +} __packed; + +#define BT_HCI_EVT_CMD_STATUS 0x0f +struct bt_hci_evt_cmd_status { + uint8_t status; + uint8_t ncmd; + uint16_t opcode; +} __packed; + +#define BT_HCI_EVT_NUM_COMPLETED_PACKETS 0x13 +struct bt_hci_evt_num_completed_packets { + uint8_t num_handles; + struct bt_hci_handle_count h[0]; +} __packed; + +#define BT_HCI_EVT_PIN_CODE_REQ 0x16 +struct bt_hci_evt_pin_code_req { + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_EVT_LINK_KEY_REQ 0x17 +struct bt_hci_evt_link_key_req { + bt_addr_t bdaddr; +} __packed; + +/* Link Key types */ +#define BT_LK_COMBINATION 0x00 +#define BT_LK_LOCAL_UNIT 0x01 +#define BT_LK_REMOTE_UNIT 0x02 +#define BT_LK_DEBUG_COMBINATION 0x03 +#define BT_LK_UNAUTH_COMBINATION_P192 0x04 +#define BT_LK_AUTH_COMBINATION_P192 0x05 +#define BT_LK_CHANGED_COMBINATION 0x06 +#define BT_LK_UNAUTH_COMBINATION_P256 0x07 +#define BT_LK_AUTH_COMBINATION_P256 0x08 + +#define BT_HCI_EVT_LINK_KEY_NOTIFY 0x18 +struct bt_hci_ev_link_key_notify { + bt_addr_t bdaddr; + uint8_t link_key[16]; + uint8_t key_type; +} __packed; + +#define BT_HCI_EVT_ENCRYPT_KEY_REFRESH_COMPLETE 0x30 +struct bt_hci_evt_encrypt_key_refresh_complete { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_EVT_IO_CAPA_REQ 0x31 +struct bt_hci_evt_io_capa_req { + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_EVT_IO_CAPA_RESP 0x32 +struct bt_hci_evt_io_capa_resp { + bt_addr_t bdaddr; + uint8_t capability; + uint8_t oob_data; + uint8_t authentication; +} __packed; + +#define BT_HCI_EVT_SSP_COMPLETE 0x36 +struct bt_hci_evt_ssp_complete { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_EVT_LE_META_EVENT 0x3e +struct bt_hci_evt_le_meta_event { + uint8_t subevent; +} __packed; + +#define BT_HCI_ROLE_MASTER 0x00 +#define BT_HCI_ROLE_SLAVE 0x01 + +#define BT_HCI_EVT_LE_CONN_COMPLETE 0x01 +struct bt_hci_evt_le_conn_complete { + uint8_t status; + uint16_t handle; + uint8_t role; + bt_addr_le_t peer_addr; + uint16_t interval; + uint16_t latency; + uint16_t supv_timeout; + uint8_t clock_accuracy; +} __packed; + +#define BT_HCI_EVT_LE_ADVERTISING_REPORT 0x02 +struct bt_hci_ev_le_advertising_info { + uint8_t evt_type; + bt_addr_le_t addr; + uint8_t length; + uint8_t data[0]; +} __packed; + +#define BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE 0x03 +struct bt_hci_evt_le_conn_update_complete { + uint8_t status; + uint16_t handle; + uint16_t interval; + uint16_t latency; + uint16_t supv_timeout; +} __packed; + +#define BT_HCI_EV_LE_REMOTE_FEAT_COMPLETE 0x04 +struct bt_hci_ev_le_remote_feat_complete { + uint8_t status; + uint16_t handle; + uint8_t features[8]; +} __packed; + +#define BT_HCI_EVT_LE_LTK_REQUEST 0x05 +struct bt_hci_evt_le_ltk_request { + uint16_t handle; + uint64_t rand; + uint16_t ediv; +} __packed; + +#define BT_HCI_EVT_LE_CONN_PARAM_REQ 0x06 +struct bt_hci_evt_le_conn_param_req { + uint16_t handle; + uint16_t interval_min; + uint16_t interval_max; + uint16_t latency; + uint16_t timeout; +} __packed; + +#define BT_HCI_EVT_LE_P256_PUBLIC_KEY_COMPLETE 0x08 +struct bt_hci_evt_le_p256_public_key_complete { + uint8_t status; + uint8_t key[64]; +} __packed; + +#define BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE 0x09 +struct bt_hci_evt_le_generate_dhkey_complete { + uint8_t status; + uint8_t dhkey[32]; +} __packed; + +#ifdef __cplusplus +} +#endif + +#endif /* __BT_HCI_H */ diff --git a/system/libarc32_arduino101/drivers/bluetooth/uuid.h b/system/libarc32_arduino101/drivers/bluetooth/uuid.h new file mode 100644 index 00000000..a54108ba --- /dev/null +++ b/system/libarc32_arduino101/drivers/bluetooth/uuid.h @@ -0,0 +1,463 @@ +/** @file + * @brief Bluetooth UUID handling + */ + +/* + * Copyright (c) 2015 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_UUID_H +#define __BT_UUID_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Bluetooth UUID types */ +enum { + BT_UUID_TYPE_16, + BT_UUID_TYPE_128, +}; + +/** @brief This is a 'tentative' type and should be used as a pointer only */ +struct bt_uuid { + uint8_t type; +}; + +struct bt_uuid_16 { + struct bt_uuid uuid; + uint16_t val; +}; + +struct bt_uuid_128 { + struct bt_uuid uuid; + uint8_t val[16]; +}; + +#define BT_UUID_INIT_16(value) \ +{ \ + .uuid.type = BT_UUID_TYPE_16, \ + .val = (value), \ +} + +#define BT_UUID_INIT_128(value...) \ +{ \ + .uuid.type = BT_UUID_TYPE_128, \ + .val = { value }, \ +} + +#define BT_UUID_DECLARE_16(value) \ + ((struct bt_uuid *) (&(struct bt_uuid_16) BT_UUID_INIT_16(value))) +#define BT_UUID_DECLARE_128(value...) \ + ((struct bt_uuid *) (&(struct bt_uuid_128) BT_UUID_INIT_128(value))) + +#define BT_UUID_16(__u) CONTAINER_OF(__u, struct bt_uuid_16, uuid) +#define BT_UUID_128(__u) CONTAINER_OF(__u, struct bt_uuid_128, uuid) + +/** @def BT_UUID_GAP + * @brief Generic Access + */ +#define BT_UUID_GAP BT_UUID_DECLARE_16(0x1800) +#define BT_UUID_GAP_VAL 0x1800 +/** @def BT_UUID_GATT + * @brief Generic Attribute + */ +#define BT_UUID_GATT BT_UUID_DECLARE_16(0x1801) +#define BT_UUID_GATT_VAL 0x1801 +/** @def BT_UUID_CTS + * @brief Current Time Service + */ +#define BT_UUID_CTS BT_UUID_DECLARE_16(0x1805) +#define BT_UUID_CTS_VAL 0x1805 +/** @def BT_UUID_DIS + * @brief Device Information Service + */ +#define BT_UUID_DIS BT_UUID_DECLARE_16(0x180a) +#define BT_UUID_DIS_VAL 0x180a +/** @def BT_UUID_HRS + * @brief Heart Rate Service + */ +#define BT_UUID_HRS BT_UUID_DECLARE_16(0x180d) +#define BT_UUID_HRS_VAL 0x180d +/** @def BT_UUID_BAS + * @brief Battery Service + */ +#define BT_UUID_BAS BT_UUID_DECLARE_16(0x180f) +#define BT_UUID_BAS_VAL 0x180f +/** @def BT_UUID_RSCS + * @brief Running Speed and Cadence Service + */ +#define BT_UUID_RSCS BT_UUID_DECLARE_16(0x1814) +#define BT_UUID_RSCS_VAL 0x1814 +/** @def BT_UUID_CSC + * @brief Cycling Speed and Cadence Service + */ +#define BT_UUID_CSC BT_UUID_DECLARE_16(0x1816) +#define BT_UUID_CSC_VAL 0x1816 +/** @def BT_UUID_ESS + * @brief Environmental Sensing Service + */ +#define BT_UUID_ESS BT_UUID_DECLARE_16(0x181a) +#define BT_UUID_ESS_VAL 0x181a +/** @def BT_UUID_IPSS + * @brief IP Support Service + */ +#define BT_UUID_IPSS BT_UUID_DECLARE_16(0x1820) +#define BT_UUID_IPSS_VAL 0x1820 +/** @def BT_UUID_LNS + * @brief Location and Navigation Support Service + */ +#define BT_UUID_LNS BT_UUID_DECLARE_16(0x1819) +#define BT_UUID_LNS_VAL 0x1819 +/** @def BT_UUID_GATT_PRIMARY + * @brief GATT Primary Service + */ +#define BT_UUID_GATT_PRIMARY BT_UUID_DECLARE_16(0x2800) +#define BT_UUID_GATT_PRIMARY_VAL 0x2800 +/** @def BT_UUID_GATT_SECONDARY + * @brief GATT Secondary Service + */ +#define BT_UUID_GATT_SECONDARY BT_UUID_DECLARE_16(0x2801) +#define BT_UUID_GATT_SECONDARY_VAL 0x2801 +/** @def BT_UUID_GATT_INCLUDE + * @brief GATT Include Service + */ +#define BT_UUID_GATT_INCLUDE BT_UUID_DECLARE_16(0x2802) +#define BT_UUID_GATT_INCLUDE_VAL 0x2802 +/** @def BT_UUID_GATT_CHRC + * @brief GATT Characteristic + */ +#define BT_UUID_GATT_CHRC BT_UUID_DECLARE_16(0x2803) +#define BT_UUID_GATT_CHRC_VAL 0x2803 +/** @def BT_UUID_GATT_CEP + * @brief GATT Characteristic Extended Properties + */ +#define BT_UUID_GATT_CEP BT_UUID_DECLARE_16(0x2900) +#define BT_UUID_GATT_CEP_VAL 0x2900 +/** @def BT_UUID_GATT_CUD + * @brief GATT Characteristic User Description + */ +#define BT_UUID_GATT_CUD BT_UUID_DECLARE_16(0x2901) +#define BT_UUID_GATT_CUD_VAL 0x2901 +/** @def BT_UUID_GATT_CCC + * @brief GATT Client Characteristic Configuration + */ +#define BT_UUID_GATT_CCC BT_UUID_DECLARE_16(0x2902) +#define BT_UUID_GATT_CCC_VAL 0x2902 +/** @def BT_UUID_GATT_SCC + * @brief GATT Server Characteristic Configuration + */ +#define BT_UUID_GATT_SCC BT_UUID_DECLARE_16(0x2903) +#define BT_UUID_GATT_SCC_VAL 0x2903 +/** @def BT_UUID_GATT_CPF + * @brief GATT Characteristic Presentation Format + */ +#define BT_UUID_GATT_CPF BT_UUID_DECLARE_16(0x2904) +#define BT_UUID_GATT_CPF_VAL 0x2904 +/** @def BT_UUID_VALID_RANGE + * @brief Valid Range Descriptor + */ +#define BT_UUID_VALID_RANGE BT_UUID_DECLARE_16(0x2906) +#define BT_UUID_VALID_RANGE_VAL 0x2906 +/** @def BT_UUID_ES_CONFIGURATION + * @brief Environmental Sensing Configuration Descriptor + */ +#define BT_UUID_ES_CONFIGURATION BT_UUID_DECLARE_16(0x290b) +#define BT_UUID_ES_CONFIGURATION_VAL 0x290b +/** @def BT_UUID_ES_MEASUREMENT + * @brief Environmental Sensing Measurement Descriptor + */ +#define BT_UUID_ES_MEASUREMENT BT_UUID_DECLARE_16(0x290c) +#define BT_UUID_ES_MEASUREMENT_VAL 0x290c +/** @def BT_UUID_ES_TRIGGER_SETTING + * @brief Environmental Sensing Trigger Setting Descriptor + */ +#define BT_UUID_ES_TRIGGER_SETTING BT_UUID_DECLARE_16(0x290d) +#define BT_UUID_ES_TRIGGER_SETTING_VAL 0x290d +/** @def BT_UUID_GAP_DEVICE_NAME + * @brief GAP Characteristic Device Name + */ +#define BT_UUID_GAP_DEVICE_NAME BT_UUID_DECLARE_16(0x2a00) +#define BT_UUID_GAP_DEVICE_NAME_VAL 0x2a00 +/** @def BT_UUID_GAP_APPEARANCE + * @brief GAP Characteristic Appearance + */ +#define BT_UUID_GAP_APPEARANCE BT_UUID_DECLARE_16(0x2a01) +#define BT_UUID_GAP_APPEARANCE_VAL 0x2a01 +/** @def BT_UUID_GAP_PPCP + * @brief GAP Characteristic Peripheral Preferred Connection Parameters + */ +#define BT_UUID_GAP_PPCP BT_UUID_DECLARE_16(0x2a04) +#define BT_UUID_GAP_PPCP_VAL 0x2a04 +/** @def BT_UUID_BAS_BATTERY_LEVEL + * @brief BAS Characteristic Battery Level + */ +#define BT_UUID_BAS_BATTERY_LEVEL BT_UUID_DECLARE_16(0x2a19) +#define BT_UUID_BAS_BATTERY_LEVEL_VAL 0x2a19 +/** @def BT_UUID_DIS_SYSTEM_ID + * @brief DIS Characteristic System ID + */ +#define BT_UUID_DIS_SYSTEM_ID BT_UUID_DECLARE_16(0x2a23) +#define BT_UUID_DIS_SYSTEM_ID_VAL 0x2a23 +/** @def BT_UUID_DIS_MODEL_NUMBER + * @brief DIS Characteristic Model Number String + */ +#define BT_UUID_DIS_MODEL_NUMBER BT_UUID_DECLARE_16(0x2a24) +#define BT_UUID_DIS_MODEL_NUMBER_VAL 0x2a24 +/** @def BT_UUID_DIS_SERIAL_NUMBER + * @brief DIS Characteristic Serial Number String + */ +#define BT_UUID_DIS_SERIAL_NUMBER BT_UUID_DECLARE_16(0x2a25) +#define BT_UUID_DIS_SERIAL_NUMBER_VAL 0x2a25 +/** @def BT_UUID_DIS_FIRMWARE_REVISION + * @brief DIS Characteristic Firmware Revision String + */ +#define BT_UUID_DIS_FIRMWARE_REVISION BT_UUID_DECLARE_16(0x2a26) +#define BT_UUID_DIS_FIRMWARE_REVISION_VAL 0x2a26 +/** @def BT_UUID_DIS_HARDWARE_REVISION + * @brief DIS Characteristic Hardware Revision String + */ +#define BT_UUID_DIS_HARDWARE_REVISION BT_UUID_DECLARE_16(0x2a27) +#define BT_UUID_DIS_HARDWARE_REVISION_VAL 0x2a27 +/** @def BT_UUID_DIS_SOFTWARE_REVISION + * @brief DIS Characteristic Software Revision String + */ +#define BT_UUID_DIS_SOFTWARE_REVISION BT_UUID_DECLARE_16(0x2a28) +#define BT_UUID_DIS_SOFTWARE_REVISION_VAL 0x2a28 +/** @def BT_UUID_DIS_MANUFACTURER_NAME + * @brief DIS Characteristic Manufacturer Name String + */ +#define BT_UUID_DIS_MANUFACTURER_NAME BT_UUID_DECLARE_16(0x2a29) +#define BT_UUID_DIS_MANUFACTURER_NAME_VAL 0x2a29 +/** @def BT_UUID_DIS_PNP_ID + * @brief DIS Characteristic PnP ID + */ +#define BT_UUID_DIS_PNP_ID BT_UUID_DECLARE_16(0x2a50) +#define BT_UUID_DIS_PNP_ID_VAL 0x2a50 +/** @def BT_UUID_RSC_MEASUREMENT + * @brief RSC Characteristic measurement ID + */ +#define BT_UUID_RSC_MEASUREMENT BT_UUID_DECLARE_16(0x2a53) +#define BT_UUID_RSC_MEASUREMENT_VAL 0x2a53 +/** @def BT_UUID_RSC_FEATURE + * @brief RSC Characteristic feature ID + */ +#define BT_UUID_RSC_FEATURE BT_UUID_DECLARE_16(0x2a54) +#define BT_UUID_RSC_FEATURE_VAL 0x2a54 +/** @def BT_UUID_CTS_CURRENT_TIME + * @brief CTS Characteristic Current Time + */ +#define BT_UUID_CTS_CURRENT_TIME BT_UUID_DECLARE_16(0x2a2b) +#define BT_UUID_CTS_CURRENT_TIME_VAL 0x2a2b +/** @def BT_UUID_MAGN_DECLINATION + * @brief Magnetic Declination Characteristic + */ +#define BT_UUID_MAGN_DECLINATION BT_UUID_DECLARE_16(0x2a2c) +#define BT_UUID_MAGN_DECLINATION_VAL 0x2a2c +/** @def BT_UUID_HRS_MEASUREMENT + * @brief HRS Characteristic Measurement Interval + */ +#define BT_UUID_HRS_MEASUREMENT BT_UUID_DECLARE_16(0x2a37) +#define BT_UUID_HRS_MEASUREMENT_VAL 0x2a37 +/** @def BT_UUID_HRS_BODY_SENSOR + * @brief HRS Characteristic Body Sensor Location + */ +#define BT_UUID_HRS_BODY_SENSOR BT_UUID_DECLARE_16(0x2a38) +#define BT_UUID_HRS_BODY_SENSOR_VAL 0x2a38 +/** @def BT_UUID_HRS_CONTROL_POINT + * @brief HRS Characteristic Control Point + */ +#define BT_UUID_HRS_CONTROL_POINT BT_UUID_DECLARE_16(0x2a39) +#define BT_UUID_HRS_CONTROL_POINT_VAL 0x2a39 +/** @def BT_UUID_CSC_MEASUREMENT + * @brief CSC Measurement Characteristic + */ +#define BT_UUID_CSC_MEASUREMENT BT_UUID_DECLARE_16(0x2a5b) +#define BT_UUID_CSC_MEASUREMENT_VAL 0x2a5b +/** @def BT_UUID_CSC_FEATURE + * @brief CSC Feature Characteristic + */ +#define BT_UUID_CSC_FEATURE BT_UUID_DECLARE_16(0x2a5c) +#define BT_UUID_CSC_FEATURE_VAL 0x2a5c +/** @def BT_UUID_SENSOR_LOCATION + * @brief Sensor Location Characteristic + */ +#define BT_UUID_SENSOR_LOCATION BT_UUID_DECLARE_16(0x2a5d) +#define BT_UUID_SENSOR_LOCATION_VAL 0x2a5d +/** @def BT_UUID_SC_CONTROL_POINT + * @brief SC Control Point Characteristic + */ +#define BT_UUID_SC_CONTROL_POINT BT_UUID_DECLARE_16(0x2a55) +#define BT_UUID_SC_CONTROL_POINT_VAl 0x2a55 +/** @def BT_UUID_LNS_CONTROL_POINT + * @brief LNS Control Point Characteristic + */ +#define BT_UUID_LNS_CONTROL_POINT BT_UUID_DECLARE_16(0x2a6B) +#define BT_UUID_LNS_CONTROL_POINT_VAL 0x2a6B +/** @def BT_UUID_LNS_LOCATION_SPEED + * @brief LNS Characteristic Location and Speed + */ +#define BT_UUID_LNS_LOCATION_SPEED BT_UUID_DECLARE_16(0x2a67) +#define BT_UUID_LNS_LOCATION_SPEED_VAL 0x2a67 +/** @def BT_UUID_LNS_FEATURE + * @brief LNS Characteristic Feature + */ +#define BT_UUID_LNS_FEATURE BT_UUID_DECLARE_16(0x2a6a) +#define BT_UUID_LNS_FEATURE_VAL 0x2a6a +/** @def BT_UUID_ELEVATION + * @brief Elevation Characteristic + */ +#define BT_UUID_ELEVATION BT_UUID_DECLARE_16(0x2a6c) +#define BT_UUID_ELEVATION_VAL 0x2a6c +/** @def BT_UUID_PRESSURE + * @brief Pressure Characteristic + */ +#define BT_UUID_PRESSURE BT_UUID_DECLARE_16(0x2a6d) +#define BT_UUID_PRESSURE_VAL 0x2a6d +/** @def BT_UUID_TEMPERATURE + * @brief Temperature Characteristic + */ +#define BT_UUID_TEMPERATURE BT_UUID_DECLARE_16(0x2a6e) +#define BT_UUID_TEMPERATURE_VAL 0x2a6e +/** @def BT_UUID_HUMIDITY + * @brief Humidity Characteristic + */ +#define BT_UUID_HUMIDITY BT_UUID_DECLARE_16(0x2a6f) +#define BT_UUID_HUMIDITY_VAL 0x2a6f +/** @def BT_UUID_TRUE_WIND_SPEED + * @brief True Wind Speed Characteristic + */ +#define BT_UUID_TRUE_WIND_SPEED BT_UUID_DECLARE_16(0x2a70) +#define BT_UUID_TRUE_WIND_SPEED_VAL 0x2a70 +/** @def BT_UUID_TRUE_WIND_DIR + * @brief True Wind Direction Characteristic + */ +#define BT_UUID_TRUE_WIND_DIR BT_UUID_DECLARE_16(0x2a71) +#define BT_UUID_TRUE_WIND_DIR_VAL 0x2a71 +/** @def BT_UUID_APPARENT_WIND_SPEED + * @brief Apparent Wind Speed Characteristic + */ +#define BT_UUID_APPARENT_WIND_SPEED BT_UUID_DECLARE_16(0x2a72) +#define BT_UUID_APPARENT_WIND_SPEED_VAL 0x2a72 +/** @def BT_UUID_APPARENT_WIND_DIR + * @brief Apparent Wind Direction Characteristic + */ +#define BT_UUID_APPARENT_WIND_DIR BT_UUID_DECLARE_16(0x2a73) +#define BT_UUID_APPARENT_WIND_DIR_VAL 0x2a73 +/** @def BT_UUID_GUST_FACTOR + * @brief Gust Factor Characteristic + */ +#define BT_UUID_GUST_FACTOR BT_UUID_DECLARE_16(0x2a74) +#define BT_UUID_GUST_FACTOR_VAL 0x2a74 +/** @def BT_UUID_POLLEN_CONCENTRATION + * @brief Pollen Concentration Characteristic + */ +#define BT_UUID_POLLEN_CONCENTRATION BT_UUID_DECLARE_16(0x2a75) +#define BT_UUID_POLLEN_CONCENTRATION_VAL 0x2a75 +/** @def BT_UUID_UV_INDEX + * @brief UV Index Characteristic + */ +#define BT_UUID_UV_INDEX BT_UUID_DECLARE_16(0x2a76) +#define BT_UUID_UV_INDEX_VAL 0x2a76 +/** @def BT_UUID_IRRADIANCE + * @brief Irradiance Characteristic + */ +#define BT_UUID_IRRADIANCE BT_UUID_DECLARE_16(0x2a77) +#define BT_UUID_IRRADIANCE_VAL 0x2a77 +/** @def BT_UUID_RAINFALL + * @brief Rainfall Characteristic + */ +#define BT_UUID_RAINFALL BT_UUID_DECLARE_16(0x2a78) +#define BT_UUID_RAINFALL_VAL 0x2a78 +/** @def BT_UUID_WIND_CHILL + * @brief Wind Chill Characteristic + */ +#define BT_UUID_WIND_CHILL BT_UUID_DECLARE_16(0x2a79) +#define BT_UUID_WIND_CHILL_VAL 0x2a79 +/** @def BT_UUID_HEAT_INDEX + * @brief Heat Index Characteristic + */ +#define BT_UUID_HEAT_INDEX BT_UUID_DECLARE_16(0x2a7a) +#define BT_UUID_HEAT_INDEX_VAL 0x2a7a +/** @def BT_UUID_DEW_POINT + * @brief Dew Point Characteristic + */ +#define BT_UUID_DEW_POINT BT_UUID_DECLARE_16(0x2a7b) +#define BT_UUID_DEW_POINT_VAL 0x2a7b +/** @def BT_UUID_DESC_VALUE_CHANGED + * @brief Descriptor Value Changed Characteristic + */ +#define BT_UUID_DESC_VALUE_CHANGED BT_UUID_DECLARE_16(0x2a7d) +#define BT_UUID_DESC_VALUE_CHANGED_VAL 0x2a7d +/** @def BT_UUID_MAGN_FLUX_DENSITY_2D + * @brief Magnetic Flux Density - 2D Characteristic + */ +#define BT_UUID_MAGN_FLUX_DENSITY_2D BT_UUID_DECLARE_16(0x2aa0) +#define BT_UUID_MAGN_FLUX_DENSITY_2D_VAL 0x2aa0 +/** @def BT_UUID_MAGN_FLUX_DENSITY_3D + * @brief Magnetic Flux Density - 3D Characteristic + */ +#define BT_UUID_MAGN_FLUX_DENSITY_3D BT_UUID_DECLARE_16(0x2aa1) +#define BT_UUID_MAGN_FLUX_DENSITY_3D_VAL 0x2aa1 +/** @def BT_UUID_BAR_PRESSURE_TREND + * @brief Barometric Pressure Trend Characteristic + */ +#define BT_UUID_BAR_PRESSURE_TREND BT_UUID_DECLARE_16(0x2aa3) +#define BT_UUID_BAR_PRESSURE_TREND_VAL 0x2aa3 + +/** @brief Compare Bluetooth UUIDs. + * + * Compares 2 Bluetooth UUIDs, if the types are different both UUIDs are + * first converted to 128 bits format before comparing. + * + * @param u1 First Bluetooth UUID to compare + * @param u2 Second Bluetooth UUID to compare + * + * @return negative value if @a u1 < @a u2, 0 if @a u1 == @a u2, else positive + */ +int bt_uuid_cmp(const struct bt_uuid *u1, const struct bt_uuid *u2); + +#if defined(CONFIG_BLUETOOTH_DEBUG) +/** @brief Convert Bluetooth UUID to string. + * + * Converts Bluetooth UUID to string. UUID has to be in 16 bits or 128 bits + * format. + * + * @param uuid Bluetooth UUID + * @param str pointer where to put converted string + * @param len length of str + * + * @return N/A + */ +void bt_uuid_to_str(const struct bt_uuid *uuid, char *str, size_t len); + +/** @brief Convert Bluetooth UUID to string in place. + * + * Converts Bluetooth UUID to string in place. UUID has to be in 16 bits or + * 128 bits format. + * + * @param uuid Bluetooth UUID + * + * @return String representation of the UUID given + */ +const char *bt_uuid_str(const struct bt_uuid *uuid); +#endif /* CONFIG_BLUETOOTH_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __BT_UUID_H */ diff --git a/system/libarc32_arduino101/drivers/ipc_uart_ns16550.c b/system/libarc32_arduino101/drivers/ipc_uart_ns16550.c index a497b6cf..b2f6c08f 100644 --- a/system/libarc32_arduino101/drivers/ipc_uart_ns16550.c +++ b/system/libarc32_arduino101/drivers/ipc_uart_ns16550.c @@ -49,14 +49,38 @@ #define IPC_UART_HDR_REQUEST_LEN (IPC_HEADER_LEN+sizeof(uint32_t)) /* ipc header + request len */ -struct ipc_uart_channels channels[IPC_UART_MAX_CHANNEL] = { {0, 0, NULL},}; -static uint16_t send_counter = 0; -static uint16_t received_counter = 0; -static uint8_t * ipc_uart_tx = NULL; -static uint8_t * ipc_uart_rx = NULL; -static uint8_t ipc_uart_tx_state = 0; +enum { + STATUS_TX_IDLE = 0, + STATUS_TX_BUSY, + STATUS_TX_DONE, +}; + +enum { + STATUS_RX_IDLE = 0, + STATUS_RX_HDR, + STATUS_RX_DATA +}; + +struct ipc_uart { + uint8_t *tx_data; + uint8_t *rx_ptr; + struct ipc_uart_channels channels[IPC_UART_MAX_CHANNEL]; + struct ipc_uart_header tx_hdr; + struct ipc_uart_header rx_hdr; + uint16_t send_counter; + uint16_t rx_size; + uint8_t tx_state; + uint8_t rx_state; + uint8_t uart_enabled; + /* protect against multiple wakelock and wake assert calls */ + uint8_t tx_wakelock_acquired; + /* TODO: remove once IRQ will take a parameter */ + //struct td_device *device; + void (*tx_cb)(bool wake_state, void *); /*!< Callback to be called to set wake state when TX is starting or ending */ + void *tx_cb_param; /*!< tx_cb function parameter */ +}; -static void * ble_cfw_channel; +static struct ipc_uart ipc = {}; static const struct uart_init_info uart_dev_info[] = { { @@ -79,187 +103,246 @@ static const struct uart_init_info uart_dev_info[] = { }, }; -void uart_ipc_close_channel(int channel_id) +void ipc_uart_close_channel(int channel_id) { - channels[channel_id].state = IPC_CHANNEL_STATE_CLOSED; - channels[channel_id].cb = NULL; - channels[channel_id].index = channel_id; + ipc.channels[channel_id].state = IPC_CHANNEL_STATE_CLOSED; + ipc.channels[channel_id].cb = NULL; + ipc.channels[channel_id].index = channel_id; + + ipc.uart_enabled = 0; + ipc.tx_wakelock_acquired = 0; } -void uart_ipc_disable(int num) +void ipc_uart_ns16550_disable(int num) { int i; for (i = 0; i < IPC_UART_MAX_CHANNEL; i++) - uart_ipc_close_channel(i); + ipc_uart_close_channel(i); + if (ipc.tx_cb) + ipc.tx_cb(0, ipc.tx_cb_param); + UART_IRQ_TX_DISABLE(num); UART_IRQ_RX_DISABLE(num); } -void uart_ipc_init(int num) +void ipc_uart_init(int num) { int i; (void)num; - uint8_t c; for (i = 0; i < IPC_UART_MAX_CHANNEL; i++) - uart_ipc_close_channel(i); + ipc_uart_close_channel(i); - pr_info(LOG_MODULE_IPC, "uart_ipc_init(nr: %d), baudrate %d, options:" - "0x%x, irq: %d",IPC_UART, + pr_info(LOG_MODULE_IPC, "%s(nr: %d), baudrate %d, options:" + "0x%x, irq: %d",__FUNCTION__, IPC_UART, uart_dev_info[IPC_UART].baud_rate, uart_dev_info[IPC_UART].options, uart_dev_info[IPC_UART].irq); uart_init(IPC_UART, &uart_dev_info[IPC_UART]); - /* Drain RX FIFOs (no need to disable IRQ at this stage) */ - while (uart_poll_in(IPC_UART, &c) != -1); - uart_int_connect(IPC_UART, uart_ipc_isr, NULL, NULL); - - UART_IRQ_RX_ENABLE(IPC_UART); + + ipc.uart_enabled = 0; + ipc.tx_wakelock_acquired = 0; + + /* Initialize the reception pointer */ + ipc.rx_size = sizeof(ipc.rx_hdr); + ipc.rx_ptr = (uint8_t *)&ipc.rx_hdr; + ipc.rx_state = STATUS_RX_IDLE; } -void uart_ipc_set_channel(void * ipc_channel) +static void ipc_uart_push_frame(uint16_t len, uint8_t *p_data) { - ble_cfw_channel = ipc_channel; -} - -void * uart_ipc_get_channel(void) -{ - return ble_cfw_channel; -} - -void uart_ipc_push_frame(void) { - void * frame; - OS_ERR_TYPE error = E_OS_OK; - - if (NULL == ipc_uart_rx) - return; - int len = IPC_FRAME_GET_LEN(ipc_uart_rx); - int channel = IPC_FRAME_GET_CHANNEL(ipc_uart_rx); - uint8_t cpu_id = IPC_FRAME_GET_SRC(ipc_uart_rx); - - pr_debug(LOG_MODULE_IPC, "%s: received frame: len %d, channel %d, src " - "%d", __func__, len, channel, cpu_id); - - if (channels[channel].cb != NULL) { - frame = balloc(len, &error); - if (error != E_OS_OK) { - pr_error(LOG_MODULE_IPC, "NO MEM: error: %d size: %d", - error, len); - } else { - memcpy(frame, &ipc_uart_rx[IPC_HEADER_LEN], len); - - channels[channel].cb(cpu_id, channel, len, frame); - } + //pr_debug(LOG_MODULE_IPC, "push_frame: received:frame len: %d, p_data: " + // "len %d, src %d, channel %d", ipc.rx_hdr.len, len, + // ipc.rx_hdr.src_cpu_id, + // ipc.rx_hdr.channel); + pr_debug(LOG_MODULE_IPC,"data[0 - 1]: %x-%x", p_data[0], p_data[1]); + + if ((ipc.rx_hdr.channel < IPC_UART_MAX_CHANNEL) && + (ipc.channels[ipc.rx_hdr.channel].cb != NULL)) { + ipc.channels[ipc.rx_hdr.channel].cb(ipc.rx_hdr.channel, + IPC_MSG_TYPE_MESSAGE, + len, + p_data); + } else { + bfree(p_data); + pr_error(LOG_MODULE_IPC, "uart_ipc: bad channel %d", + ipc.rx_hdr.channel); } - if (ipc_uart_rx) - bfree(ipc_uart_rx); - ipc_uart_rx = NULL; } -void uart_ipc_isr() +void ipc_uart_isr() { - uint8_t *p_rx; + /* TODO: remove once IRQ supports parameter */ uint8_t *p_tx; - while (UART_IRQ_HW_UPDATE(IPC_UART) && UART_IRQ_IS_PENDING(IPC_UART)) { - if (UART_IRQ_ERR_DETECTED(IPC_UART)) { + while (UART_IRQ_HW_UPDATE(IPC_UART) && + UART_IRQ_IS_PENDING(IPC_UART)) { + if (UART_IRQ_ERR_DETECTED(IPC_UART)) + { uint8_t c; - if (UART_BREAK_CHECK(IPC_UART)){ - panic(); + if (UART_BREAK_CHECK(IPC_UART)) { + panic(-1); } UART_POLL_IN(IPC_UART, &c); - } else if (UART_IRQ_RX_READY(IPC_UART)) { - int received; - if (received_counter < 2) { - if (NULL == ipc_uart_rx) - ipc_uart_rx = - balloc(IPC_UART_MAX_PAYLOAD, NULL); - p_rx = ipc_uart_rx; - received = UART_FIFO_READ(IPC_UART, - &p_rx[received_counter], - 1); - received_counter += received; - } else { - p_rx = ipc_uart_rx; - received = UART_FIFO_READ(IPC_UART, - &p_rx[received_counter], - IPC_FRAME_GET_LEN(p_rx) + - IPC_HEADER_LEN - - received_counter); - received_counter += received; - if (received_counter == IPC_FRAME_GET_LEN(p_rx) - + IPC_HEADER_LEN) { + } + if (UART_IRQ_RX_READY(IPC_UART)) { + int rx_cnt; + + while ((rx_cnt = + UART_FIFO_READ(IPC_UART, + ipc.rx_ptr, + ipc.rx_size)) != 0) + { + if ((ipc.uart_enabled) && + (ipc.rx_state == STATUS_RX_IDLE)) { + /* acquire wakelock until frame is fully received */ + //pm_wakelock_acquire(&info->rx_wl); + ipc.rx_state = STATUS_RX_HDR; + } + + /* Until UART has enabled at least one channel, data should be discarded */ + if (ipc.uart_enabled) { + ipc.rx_size -= rx_cnt; + ipc.rx_ptr += rx_cnt; + } + + if (ipc.rx_size == 0) { + if (ipc.rx_state == STATUS_RX_HDR) { + pr_error(0, "%s-%d", __FUNCTION__, ipc.rx_hdr.len); + ipc.rx_ptr = balloc( + ipc.rx_hdr.len, NULL); + + //pr_debug( + // LOG_MODULE_IPC, + // "ipc_uart_isr: rx_ptr is %p", + // ipc.rx_ptr); + ipc.rx_size = ipc.rx_hdr.len; + ipc.rx_state = STATUS_RX_DATA; + } else { #ifdef IPC_UART_DBG_RX - for(int i = 0; i < received_counter; i++) { - pr_debug(LOG_MODULE_IPC, "%s: %d byte is %d", __func__, i, p_rx[i]); - } + uint8_t *p_rx = ipc.rx_ptr - + ipc.rx_hdr.len; + for (int i = 0; + i < ipc.rx_hdr.len; + i++) { + pr_debug( + LOG_MODULE_IPC, + "ipc_uart_isr: %d byte is %d", + i, p_rx[i]); + } #endif - received_counter = 0; - uart_ipc_push_frame(); + + ipc_uart_push_frame( + ipc.rx_hdr.len, + ipc.rx_ptr - + ipc.rx_hdr.len); + ipc.rx_size = sizeof(ipc.rx_hdr); + ipc.rx_ptr = + (uint8_t *)&ipc.rx_hdr; + ipc.rx_state = STATUS_RX_IDLE; + } } } - } else if (UART_IRQ_TX_READY(IPC_UART)) { - int transmitted; - if (ipc_uart_tx_state == STATUS_TX_IDLE) { + } + if (UART_IRQ_TX_READY(IPC_UART)) { + int tx_len; + + if (ipc.tx_state == STATUS_TX_DONE) { uint8_t lsr = UART_LINE_STATUS(IPC_UART); + ipc.tx_state = STATUS_TX_IDLE; UART_IRQ_TX_DISABLE(IPC_UART); - - pr_debug(LOG_MODULE_IPC, "ipc_isr_tx: disable TXint, LSR: 0x%2x\n", - lsr); + /* wait for FIFO AND THR being empty! */ while ((lsr & BOTH_EMPTY) != BOTH_EMPTY) { lsr = UART_LINE_STATUS(IPC_UART); } + + /* No more TX activity, send event and release wakelock */ + if (ipc.tx_cb) { + ipc.tx_cb(0, ipc.tx_cb_param); + } + //pm_wakelock_release(&info->tx_wl); + ipc.tx_wakelock_acquired = 0; return; } - if(NULL == ipc_uart_tx){ - pr_warning(LOG_MODULE_IPC, "%s: Bad Tx data",__func__); + if (NULL == ipc.tx_data) { + pr_warning(LOG_MODULE_IPC, + "ipc_uart_isr: Bad Tx data"); return; } - p_tx = ipc_uart_tx; - transmitted = UART_FIFO_FILL(IPC_UART, &p_tx[send_counter], - IPC_FRAME_GET_LEN(p_tx) + - IPC_HEADER_LEN - send_counter); - send_counter += transmitted; - if (send_counter == IPC_FRAME_GET_LEN(p_tx) + - IPC_HEADER_LEN) { - send_counter = 0; -#ifdef IPC_UART_DBG_TX - pr_debug(LOG_MODULE_IPC, "%s: sent IPC FRAME " - "len %d", __func__, - IPC_FRAME_GET_LEN(p_tx)); - for (int i = 0; i < send_counter; i++) { - pr_debug(LOG_MODULE_IPC, "%s: %d sent " - "byte is %d", - __func__, i, p_tx[i]); + + if (!ipc.tx_wakelock_acquired) { + ipc.tx_wakelock_acquired = 1; + /* Starting TX activity, send wake assert event and acquire wakelock */ + if (ipc.tx_cb) { + ipc.tx_cb(1, ipc.tx_cb_param); } + //pm_wakelock_acquire(&info->tx_wl); + } + if (ipc.send_counter < sizeof(ipc.tx_hdr)) { + p_tx = (uint8_t *)&ipc.tx_hdr + + ipc.send_counter; + tx_len = sizeof(ipc.tx_hdr) - ipc.send_counter; + } else { + p_tx = ipc.tx_data + + (ipc.send_counter - sizeof(ipc.tx_hdr)); + tx_len = ipc.tx_hdr.len - + (ipc.send_counter - sizeof(ipc.tx_hdr)); + } + ipc.send_counter += UART_FIFO_FILL(IPC_UART, + p_tx, + tx_len); + + if (ipc.send_counter == + (ipc.tx_hdr.len + sizeof(ipc.tx_hdr))) { + ipc.send_counter = 0; +#ifdef IPC_UART_DBG_TX + pr_debug( + LOG_MODULE_IPC, + "ipc_uart_isr: sent IPC FRAME " + "len %d", ipc.tx_hdr.len); #endif - bfree(ipc_uart_tx); - ipc_uart_tx = NULL; - ipc_uart_tx_state = STATUS_TX_IDLE; + p_tx = ipc.tx_data; + ipc.tx_data = NULL; + ipc.tx_state = STATUS_TX_DONE; + + /* free sent message and pull send next frame one in the queue */ + if (ipc.channels[ipc.tx_hdr.channel].cb) + { + ipc.channels[ipc.tx_hdr.channel].cb( + ipc.tx_hdr.channel, + IPC_MSG_TYPE_FREE, + ipc.tx_hdr.len, + p_tx); + } + else + { + bfree(p_tx); + } + #ifdef IPC_UART_DBG_TX - uint8_t lsr = UART_LINE_STATUS(IPC_UART); - pr_info(LOG_MODULE_IPC, "ipc_isr_tx: tx_idle LSR: 0x%2x\n", - lsr); + uint8_t lsr = UART_LINE_STATUS(IPC_UART);//(info->uart_num); + pr_debug(LOG_MODULE_IPC, + "ipc_isr_tx: tx_idle LSR: 0x%2x\n", + lsr); #endif } - } else { - pr_warning(LOG_MODULE_IPC, "%s: Unknown ISR src", - __func__); } + } } -void *uart_ipc_channel_open(int channel_id, - void (*cb) (uint8_t, int, int, void *)) +void *ipc_uart_channel_open(int channel_id, + int (*cb)(int, int, int, void *)) { struct ipc_uart_channels *chan; + uint8_t c; - if (channel_id > IPC_UART_MAX_CHANNEL - 1) + if (channel_id > (IPC_UART_MAX_CHANNEL - 1)) return NULL; - chan = &channels[channel_id]; + chan = &ipc.channels[channel_id]; if (chan->state != IPC_CHANNEL_STATE_CLOSED) return NULL; @@ -267,74 +350,48 @@ void *uart_ipc_channel_open(int channel_id, chan->state = IPC_CHANNEL_STATE_OPEN; chan->cb = cb; + ipc.uart_enabled = 1; + ipc.tx_wakelock_acquired = 0; + + pr_debug(LOG_MODULE_IPC, "%s: open chan success", __FUNCTION__); + + /* Drain RX FIFOs (no need to disable IRQ at this stage) */ + while (uart_poll_in(IPC_UART, &c) != -1); + uart_int_connect(IPC_UART, ipc_uart_isr, NULL, NULL); + + UART_IRQ_RX_ENABLE(IPC_UART); + return chan; } -int uart_ipc_send_message(void *handle, int len, void *p_data) +int ipc_uart_ns16550_send_pdu(void *handle, int len, void *p_data) { - struct ipc_uart_channels *chan = (struct ipc_uart_channels *) handle; - - int flags = interrupt_lock(); - if (ipc_uart_tx_state == STATUS_TX_BUSY) { - interrupt_unlock(flags); - return IPC_UART_ERROR_WRONG_STATE; - } - ipc_uart_tx_state = STATUS_TX_BUSY; - interrupt_unlock(flags); - - uint8_t *p_tx = ipc_uart_tx = balloc(len + IPC_UART_HDR_REQUEST_LEN, - NULL); + struct ipc_uart_channels *chan = (struct ipc_uart_channels *)handle; - /* Adding size of the message request field*/ - int size = len + sizeof(uint32_t); + pr_debug(LOG_MODULE_IPC, "%s: %d", __FUNCTION__, ipc.tx_state); - /* length = cfw_message size + message request field*/ - IPC_FRAME_SET_LEN(p_tx, size); - IPC_FRAME_SET_CHANNEL(p_tx, chan->index); - IPC_FRAME_SET_SRC(p_tx, get_cpu_id()); - IPC_FRAME_SET_REQUEST(p_tx, IPC_MSG_TYPE_MESSAGE); - - /* IPC_HEADER + request_ID + cfw_message */ - /* copy cfw_message within IPC frame*/ - memcpy(IPC_FRAME_DATA(p_tx), p_data, len); + if (ipc.tx_state == STATUS_TX_BUSY) { + return IPC_UART_TX_BUSY; + } + + /* It is eventually possible to be in DONE state (sending last bytes of previous message), + * so we move immediately to BUSY and configure the next frame */ + ipc.tx_state = STATUS_TX_BUSY; - pr_debug(LOG_MODULE_IPC, "%s: tx: channel %d, len %d, request 0x%x", - __func__, p_tx[2], len, p_tx[4]); + ipc.tx_hdr.len = len; + ipc.tx_hdr.channel = chan->index; + ipc.tx_hdr.src_cpu_id = 0; + ipc.tx_data = p_data; + /* Enable the interrupt (ready will expire if it was disabled) */ UART_IRQ_TX_ENABLE(IPC_UART); return IPC_UART_ERROR_OK; } -int uart_ipc_send_sync_resp(int channel, int request_id, int param1, int param2, - void * ptr) +void ipc_uart_ns16550_set_tx_cb(void (*cb)(bool, void *), void *param) { - if (ipc_uart_tx_state == STATUS_TX_BUSY) - return IPC_UART_ERROR_WRONG_STATE; - ipc_uart_tx_state = STATUS_TX_BUSY; - - uint8_t *p_tx = ipc_uart_tx = balloc(IPC_UART_HDR_REQUEST_LEN + 12, - NULL); - - IPC_FRAME_SET_LEN(p_tx, 16); - IPC_FRAME_SET_CHANNEL(p_tx, channel); - IPC_FRAME_SET_SRC(ipc_uart_tx, get_cpu_id()); - - IPC_FRAME_SET_REQUEST(p_tx, request_id); - SYNC_FRAME_SET_PARAM1(p_tx, param1); - SYNC_FRAME_SET_PARAM2(p_tx, param2); - SYNC_FRAME_SET_PTR(p_tx, ptr); - -#ifdef IPC_UART_DBG_SYNC_RESP - for (int i = 0; i < 20; i++) { - pr_debug(LOG_MODULE_IPC, "%s: IPC sync resp %d byte : %d", - __func__,i, p_tx[i]); - } - pr_debug(LOG_MODULE_IPC, "%s: tx: channel %d, request %xh", __func__, - p_tx[2], p_tx[4]); -#endif - - UART_IRQ_TX_ENABLE(IPC_UART); - - return IPC_UART_ERROR_OK; + ipc.tx_cb = cb; + ipc.tx_cb_param = param; } + diff --git a/system/libarc32_arduino101/drivers/ipc_uart_ns16550.h b/system/libarc32_arduino101/drivers/ipc_uart_ns16550.h index 7fc04670..d71a61b9 100644 --- a/system/libarc32_arduino101/drivers/ipc_uart_ns16550.h +++ b/system/libarc32_arduino101/drivers/ipc_uart_ns16550.h @@ -33,19 +33,71 @@ #define IPC_UART 0 -enum { - STATUS_TX_IDLE = 0, - STATUS_TX_BUSY, -}; -enum { +/** IPC UART return codes */ +enum IPC_UART_RESULT_CODES { IPC_UART_ERROR_OK = 0, - IPC_UART_ERROR_WRONG_STATE, IPC_UART_ERROR_DATA_TO_BIG, + IPC_UART_TX_BUSY /**< A transmission is already ongoing, message is NOT sent */ +}; + + +/** + * Channel list + */ +enum ipc_channels { + RPC_CHANNEL=0, /**< RPC channel */ + IPC_UART_MAX_CHANNEL = 4 +}; + +/** + * Channel state + */ +enum ipc_channel_state { + IPC_CHANNEL_STATE_CLOSED = 0, + IPC_CHANNEL_STATE_OPEN +}; + +/** + * Definitions valid for NONE sync IPC UART headers + * |len|channel|cpu_id|request|payload| + * + * len = len(request)+len(payload) + */ + +/** + * @note this structure must be self-aligned and self-packed + */ +struct ipc_uart_header { + uint16_t len; /**< Length of IPC message, (request + payload) */ + uint8_t channel; /**< Channel number of IPC message. */ + uint8_t src_cpu_id; /**< CPU id of IPC sender. */ }; -void uart_ipc_isr(); -void uart_ipc_push_frame(void); -void uart_ipc_close_channel(int channel_id); +/** + * IPC channel description + */ +struct ipc_uart_channels { + uint16_t index; /**< Channel number */ + uint16_t state; /**< @ref ipc_channel_state */ + int (*cb)(int chan, int request, int len, void *data); + /**< Callback of the channel. + * @param chan Channel index used + * @param request Request id (defined in ipc_requests.h) + * @param len Payload size + * @param data Pointer to data + */ +}; + +void ipc_uart_init(int num); +void ipc_uart_isr(); +//static void ipc_uart_push_frame(uint16_t len, uint8_t *p_data); +void ipc_uart_ns16550_disable(int num); +void ipc_uart_close_channel(int channel_id); +void ipc_uart_ns16550_set_tx_cb(void (*cb)(bool, void *), void *param); +int ipc_uart_ns16550_send_pdu(void *handle, int len, void *p_data); +void *ipc_uart_channel_open(int channel_id, + int (*cb)(int, int, int, void *)); + #endif /* _IPC_UART_NS16550_H_ */ diff --git a/system/libarc32_arduino101/drivers/rpc/rpc.h b/system/libarc32_arduino101/drivers/rpc/rpc.h new file mode 100644 index 00000000..5d45d463 --- /dev/null +++ b/system/libarc32_arduino101/drivers/rpc/rpc.h @@ -0,0 +1,152 @@ +/* + * 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 RPC_H_ +#define RPC_H_ + +#include + +/** Identifiers of the signature supported by the RPC */ +enum { + SIG_TYPE_NONE = 1, + 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 +}; + +/** + * 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. + * + * @param length Length of the buffer to allocate + * + * @return Pointer to the allocated buffer, the allocation shall not fail, error must + * be handled internally + */ +uint8_t * rpc_alloc_cb(uint16_t length); + +/** + * RPC transmission function, must be implemented by the user of the RPC. + * + * @param p_buf Pointer to the buffer allocated for transmission by @ref rpc_alloc_cb + * @param length Length of the buffer to transmit + */ +void rpc_transmit_cb(uint8_t * p_buf, uint16_t length); + +/** + * RPC serialization function to serialize a function that does not require any parameter. + * + * @param fn_index Index of the function + */ +void rpc_serialize_none(uint8_t fn_index); + +/** + * RPC serialization function to serialize a function that expects a structure 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 + */ +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 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 p_priv Pointer to serialize + */ +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 pointer as 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); + +/** + * RPC serialization function to serialize a function that expects a structure + * and a buffer 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 + */ +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 serialization function to serialize a function that expects a structure + * and a buffer as parameters. + * + * @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); + +/** + * RPC serialization function to serialize a function that expects a structure + * and a buffer 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); + +/** + * RPC serialization function to serialize a function that expects a structure + * and a buffer 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 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 + */ +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); + +/** 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); + +#endif /* RPC_H_*/ diff --git a/system/libarc32_arduino101/drivers/rpc/rpc_deserialize.c b/system/libarc32_arduino101/drivers/rpc/rpc_deserialize.c new file mode 100644 index 00000000..e3f568d0 --- /dev/null +++ b/system/libarc32_arduino101/drivers/rpc/rpc_deserialize.c @@ -0,0 +1,457 @@ +/* + * 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 "rpc.h" + +extern void panic(int err); + +/* Include the functions offered */ +#if defined(CONFIG_QUARK_SE_BLE_CORE) +#include "rpc_functions_to_ble_core.h" +#elif defined(CONFIG_SOC_QUARK_SE) +#include "rpc_functions_to_quark.h" +#elif defined(LINUX_HOST_RUNTIME) +// for the host compilation (to simulate connection to BLE controller) +#include "rpc_functions_to_ble_core.h" +#else +#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); +LIST_FN_SIG_NONE +#undef FN_SIG_NONE + +#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); +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); +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); +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_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_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)), + +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) + +/* 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) + +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; + + struct_length = *p++; + *pp_struct = p; + *p_struct_length = struct_length; + + return p + struct_length; +} + +static const uint8_t * deserialize_buf(const uint8_t *p, const uint8_t **pp_buf, uint16_t *p_buflen) { + uint8_t b; + uint16_t buflen; + + /* Get the current byte */ + b = *p++; + buflen = b & 0x7F; + if (b & 0x80) { + /* Get the current byte */ + b = *p++; + buflen += (uint16_t)b << 7; + } + + /* Return the values */ + *pp_buf = p; + *p_buflen = buflen; + p += buflen; + return p; +} + +static void deserialize_none(uint8_t fn_index, const uint8_t * p_buf, uint16_t length) { + (void)p_buf; + if (length != 0) + panic(-1); + 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; + uint8_t struct_length; + const uint8_t *p; + + p = deserialize_struct(p_buf, &p_struct_data, &struct_length); + + if ((length != (p - 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))]; + + memcpy(struct_data, p_struct_data, struct_length); + + 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; + + if (length != 4) + panic(-1); + + /* little endian conversion */ + p_priv = p_buf[0] | (p_buf[1] << 8) | (p_buf[2] << 16) | (p_buf[3] << 24); + + m_fct_p[fn_index]((void *)p_priv); +} + +static void deserialize_s_b(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_vbuf; + uint16_t vbuf_length; + const uint8_t *p; + + p = deserialize_struct(p_buf, &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])) + 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; + } + + 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; + + /* 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); + } +} + +static void deserialize_s_p(uint8_t fn_index, const uint8_t * p_buf, uint16_t length) +{ + const uint8_t *p_struct_data; + uint8_t struct_length; + uintptr_t p_priv; + const uint8_t *p; + + p = deserialize_struct(p_buf, &p_struct_data, &struct_length); + p += 4; + + if ((length != (p - 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))]; + + 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); + } +} + +static void deserialize_s_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_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; + + memcpy(struct_data, p_struct_data, struct_length); + + 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; + + /* 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); + } +} + +void rpc_deserialize(const uint8_t * p_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; + } + } +} 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 new file mode 100644 index 00000000..5f742208 --- /dev/null +++ b/system/libarc32_arduino101/drivers/rpc/rpc_functions_to_ble_core.h @@ -0,0 +1,106 @@ +/* + * 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 RPC_FUNCTIONS_TO_BLE_CORE_H_ +#define RPC_FUNCTIONS_TO_BLE_CORE_H_ + +#include "gap_internal.h" +#include "gatt_internal.h" + +/* declare the list of functions sorted by signature */ +#define LIST_FN_SIG_NONE \ + FN_SIG_NONE(nble_gap_start_adv_req) \ + FN_SIG_NONE(nble_gap_stop_scan_req) + +#define LIST_FN_SIG_S \ + FN_SIG_S(nble_gap_set_adv_data_req, \ + struct nble_gap_ad_data_params *) \ + FN_SIG_S(nble_gap_set_adv_params_req, \ + struct nble_gap_adv_params *) \ + 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 *) \ + FN_SIG_S(nble_gap_conn_update_req, \ + const struct nble_gap_connect_update_params *) \ + 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 *) \ + 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 *) \ + FN_SIG_S(nble_gap_disconnect_req, \ + const struct nble_gap_disconnect_req_params *) \ + 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 *) + +#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 *) + +#define LIST_FN_SIG_S_B \ + FN_SIG_S_B(nble_gatt_register_req, \ + const struct nble_gatt_register_req *, \ + uint8_t *, uint16_t) \ + FN_SIG_S_B(nble_gatt_send_notif_req, \ + const struct nble_gatt_send_notif_params *, \ + const uint8_t *, uint16_t) \ + FN_SIG_S_B(nble_gatt_send_ind_req, \ + const struct nble_gatt_send_ind_params *, \ + const uint8_t *, uint8_t) \ + FN_SIG_S_B(nble_gatts_rd_reply_req, \ + const struct nble_gatts_rd_reply_params *, \ + uint8_t *, uint16_t) \ + FN_SIG_S_B(nble_gattc_write_req, \ + const struct ble_gattc_write_params *, \ + 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 + +#define LIST_FN_SIG_S_P \ + FN_SIG_S_P(nble_gap_connect_req, \ + const struct nble_gap_connect_req_params *, 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 + +#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 new file mode 100644 index 00000000..b08005e6 --- /dev/null +++ b/system/libarc32_arduino101/drivers/rpc/rpc_functions_to_quark.h @@ -0,0 +1,124 @@ +/* + * 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 RPC_FUNCTIONS_TO_QUARK_H_ +#define RPC_FUNCTIONS_TO_QUARK_H_ + +#include "gap_internal.h" +#include "gatt_internal.h" +#include "gap_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_S \ + FN_SIG_S(on_nble_get_version_rsp, \ + const struct nble_version_response *) \ + 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_gap_rssi_evt, \ + const struct nble_gap_rssi_evt *) \ + FN_SIG_S(on_nble_common_rsp, \ + const struct nble_response *) \ + FN_SIG_S(on_nble_gap_connect_rsp, \ + const struct nble_response *) \ + 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 *) \ + 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 *) \ + 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_gap_scan_start_stop_rsp, \ + const struct nble_response *) \ + FN_SIG_S(on_nble_gatts_read_evt, \ + const struct nble_gatt_rd_evt *) \ + FN_SIG_S(on_nble_gatts_write_exec_evt, \ + const struct nble_gatt_wr_exec_evt *) \ + FN_SIG_S(on_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 *) + +#define LIST_FN_SIG_P \ + FN_SIG_P(on_nble_gap_dtm_init_rsp, void *) + +#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 *, \ + uint8_t *, uint8_t) \ + FN_SIG_S_B(on_nble_gatts_write_evt, \ + const struct nble_gatt_wr_evt *, \ + const uint8_t *, uint8_t) \ + FN_SIG_S_B(on_nble_gatt_register_rsp, \ + const struct nble_gatt_register_rsp *, \ + const struct nble_gatt_attr_handles *, \ + uint8_t) \ + FN_SIG_S_B(on_nble_gattc_discover_rsp, \ + const struct nble_gattc_discover_rsp *, \ + const uint8_t *, uint8_t) \ + 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*, \ + 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 + +#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 new file mode 100644 index 00000000..e2144ee3 --- /dev/null +++ b/system/libarc32_arduino101/drivers/rpc/rpc_serialize.c @@ -0,0 +1,323 @@ +/* + * 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 "rpc.h" + +/* Include the functions called */ +#if defined(CONFIG_QUARK_SE_BLE_CORE) +#include "rpc_functions_to_quark.h" +#elif defined(CONFIG_SOC_QUARK_SE) +#include "rpc_functions_to_ble_core.h" +#elif defined(LINUX_HOST_RUNTIME) +// for the host compilation (to simulate connection to BLE controller) +#include "rpc_functions_to_ble_core.h" +#else +#error "File is compiled but should not" +#endif + +/* 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 */ +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); \ + } \ + + +/* 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 + +static void _send(uint8_t *buf, uint16_t length) { + rpc_transmit_cb(buf, length); +} + +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) { + *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) + return 1; + else { + 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) { + uint16_t varint; + + if (NULL == buf) + buflen = 0; + + varint = buflen; + + *p = varint & 0x7F; + if (varint >= (1 << 7)) { + *p |= 0x80; + p++; + *p = varint >> 7; + } + p++; + memcpy(p, buf, buflen); + p += buflen; + return p; +} + +static uint8_t *serialize_p(uint8_t *p, uintptr_t priv) { + *p++ = priv; + *p++ = (priv >> 8); + *p++ = (priv >> 16); + *p++ = (priv >> 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; + + p = buf = rpc_alloc_cb(length); + + *p++ = SIG_TYPE_NONE; + *p = fn_index; + + _send(buf, length); +} + +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; + + length = SIG_TYPE_SIZE + FN_INDEX_SIZE + encoded_structlen(struct_length); + + p = buf = rpc_alloc_cb(length); + + *p++ = SIG_TYPE_S; + *p++ = fn_index; + p = serialize_struct(p, struct_data, struct_length); + + _send(buf, length); +} + + +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); + + *p++ = SIG_TYPE_P; + *p++ = fn_index; + p = serialize_p(p, priv); + + _send(buf, 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) { + 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); + + p = buf = rpc_alloc_cb(length); + + *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); +} + +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; + + length = SIG_TYPE_SIZE + FN_INDEX_SIZE + encoded_structlen(struct_length) + + POINTER_SIZE; + + p = buf = rpc_alloc_cb(length); + + *p++ = SIG_TYPE_S_P; + *p++ = fn_index; + p = serialize_struct(p, struct_data, struct_length); + p = serialize_p(p, priv); + + _send(buf, length); +} + +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); +} diff --git a/system/libarc32_arduino101/framework/include/cfw/cfw.h b/system/libarc32_arduino101/framework/include/cfw/cfw.h index 9c9f040f..311dcf7b 100644 --- a/system/libarc32_arduino101/framework/include/cfw/cfw.h +++ b/system/libarc32_arduino101/framework/include/cfw/cfw.h @@ -113,7 +113,7 @@ typedef struct svc_client_handle_ { * Passed in the conn field of struct cfw_message for request messages */ void * server_handle; -} svc_client_handle_t; +} svc_client_handle_t, cfw_service_conn_t; struct cfw_message * cfw_alloc_message(int size, OS_ERR_TYPE * err); diff --git a/system/libarc32_arduino101/framework/include/cfw/cfw_client.h b/system/libarc32_arduino101/framework/include/cfw/cfw_client.h index 2a1ae2ba..2154208f 100644 --- a/system/libarc32_arduino101/framework/include/cfw/cfw_client.h +++ b/system/libarc32_arduino101/framework/include/cfw/cfw_client.h @@ -40,22 +40,6 @@ * @{ */ -/** - * Create a handle to the component framework. - * This handle is to be used for all other requests - * to the component framework - * - * Implementation is different in the master and the slave contexts. - * The master context will be pseudo-synchronous, while the slave - * implementation will actually pass a message to the master context - * in order to register a new client. - * - * \param queue pointer to service queue - * \param cb the callback that will be called for each message reception - * \param param the param passed along with the message to the callback - */ -cfw_handle_t cfw_init(void * queue, handle_msg_cb_t cb, void * param); - /** * Allocate a request message for a service. diff --git a/system/libarc32_arduino101/framework/include/cfw_platform.h b/system/libarc32_arduino101/framework/include/cfw_platform.h index 4e361961..aa5cb29e 100644 --- a/system/libarc32_arduino101/framework/include/cfw_platform.h +++ b/system/libarc32_arduino101/framework/include/cfw_platform.h @@ -39,7 +39,6 @@ extern "C" { #endif void cfw_platform_init(void); -void cfw_platform_nordic_init(void); T_QUEUE cfw_get_service_queue(void); #ifdef __cplusplus diff --git a/system/libarc32_arduino101/framework/include/infra/ipc_uart.h b/system/libarc32_arduino101/framework/include/infra/ipc_uart.h index 5f5cbe76..6c8eab4f 100644 --- a/system/libarc32_arduino101/framework/include/infra/ipc_uart.h +++ b/system/libarc32_arduino101/framework/include/infra/ipc_uart.h @@ -78,25 +78,6 @@ /* optional sync frame payload */ #define SYNC_FRAME_DATA(_frame_) ((unsigned char *)&(_frame_)[20]) -#define IPC_CHANNEL_STATE_CLOSED 0 -#define IPC_CHANNEL_STATE_OPEN 1 - -#define IPC_UART_MAX_CHANNEL 4 - -struct ipc_uart_channels { - uint16_t index; - uint16_t state; - void (*cb) (uint8_t cpu_id, int chan, int len, void * data); -}; - -void * uart_ipc_channel_open(int channel, void(*cb)(uint8_t cpu_id, int chan, int len, void * data)); -int uart_ipc_send_message(void * handle, int len, void *p_data); -void uart_ipc_set_channel(void * ipc_channel); -void * uart_ipc_get_channel(void); -int uart_ipc_send_sync_resp(int channel, int request_id, int param1, int param2, void * ptr); -void uart_ipc_init(int num); -void uart_ipc_disable(int num); - /** @} */ #endif /* _IPC_UART_H_ */ diff --git a/system/libarc32_arduino101/framework/include/infra/log.h b/system/libarc32_arduino101/framework/include/infra/log.h index 528b0d99..07848310 100644 --- a/system/libarc32_arduino101/framework/include/infra/log.h +++ b/system/libarc32_arduino101/framework/include/infra/log.h @@ -36,6 +36,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /** * @defgroup infra_log Log * @ingroup infra @@ -260,7 +264,11 @@ void log_resume(); * @param module the ID of the log module related to this message * @param format the printf-like string format */ -#define pr_debug(module, format,...) pr_debug_ ## module(format, ##__VA_ARGS__) +#define pr_debug(module, format,...) log_printk(LOG_LEVEL_DEBUG, module, format, ##__VA_ARGS__) + +#ifdef __cplusplus +} +#endif /** @} */ diff --git a/system/libarc32_arduino101/framework/include/log_modules b/system/libarc32_arduino101/framework/include/log_modules index c7246635..401bbae9 100644 --- a/system/libarc32_arduino101/framework/include/log_modules +++ b/system/libarc32_arduino101/framework/include/log_modules @@ -25,3 +25,4 @@ DEFINE_LOGGER_MODULE(LOG_MODULE_DRV, "DRV", 0) DEFINE_LOGGER_MODULE(LOG_MODULE_CUNIT, "CUNIT", 0) DEFINE_LOGGER_MODULE(LOG_MODULE_CFW, "CFW", 0) DEFINE_LOGGER_MODULE(LOG_MODULE_GPIO_SVC, "GPIO_SVC", 0) +DEFINE_LOGGER_MODULE(LOG_MODULE_APP, "APP", 0) diff --git a/system/libarc32_arduino101/framework/include/panic_api.h b/system/libarc32_arduino101/framework/include/panic_api.h index 70aea89c..5a579280 100644 --- a/system/libarc32_arduino101/framework/include/panic_api.h +++ b/system/libarc32_arduino101/framework/include/panic_api.h @@ -29,5 +29,5 @@ */ // TODO - replace with a proper implementation of panic() -#define panic(x) _do_fault(); +//#define panic(x) _do_fault(); #define force_panic() panic(-1) 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 fa14941b..8917e61c 100644 --- a/system/libarc32_arduino101/framework/include/services/ble/ble_service.h +++ b/system/libarc32_arduino101/framework/include/services/ble/ble_service.h @@ -33,29 +33,205 @@ #include +/* For MSG_ID_BLE_SERVICE_BASE */ +#include "services/services_ids.h" + +/* For bt_uuid */ +#include "bluetooth/gatt.h" + +#include "bluetooth/bluetooth.h" + +#include "cfw/cfw.h" + +/* Forward declarations */ +struct _ble_service_cb; +struct bt_conn; + /** - * @addtogroup ble_service + * @cond + * @defgroup ble_service BLE Service + * + * Bluetooth Low Energy (BLE) application level service. + * + * This service provides BLE service, abstracting most of the complexity of the underlying BLE services/profiles. + * + * @ingroup services + * * @{ + */ + +/* + * CFW Message ID base definitions for BLE services. + */ + +/* BLE Service Message ID definitions. */ +#define MSG_ID_BLE_SERVICE_RSP (MSG_ID_BLE_SERVICE_BASE + 0x40) +#define MSG_ID_BLE_SERVICE_EVT (MSG_ID_BLE_SERVICE_BASE + 0x80) + +/** BLE High level Message IDs used for request, response, events. */ +enum BLE_MSG_ID { + MSG_ID_BLE_ENABLE_RSP = MSG_ID_BLE_SERVICE_RSP, /**< Message ID for enable response, of type @ref ble_enable_rsp */ + MSG_ID_BLE_INIT_SVC_RSP, /**< Message ID for init service response, of type @ref ble_init_svc_rsp */ + + /* BLE direct test mode command */ + MSG_ID_BLE_DBG_RSP, /**< Message ID for DTM command response, of type @ref ble_dbg_req_rsp */ + + MSG_ID_BLE_SERVICE_RSP_LAST, + + /* events */ + MSG_ID_BLE_ADV_TO_EVT = MSG_ID_BLE_SERVICE_EVT, /**< Message ID for struct @ref ble_adv_to_evt */ + MSG_ID_BLE_SERVICE_EVT_LAST +}; + +/** Macro to convert milliseconds to a specific unit */ +#define MSEC_TO_1_25_MS_UNITS(TIME) (((TIME) * 1000) / 1250) +#define MSEC_TO_10_MS_UNITS(TIME) ((TIME) / 10) + +#define BLE_GAP_SEC_RAND_LEN 8 /**< Random Security number length (64 bits) */ +#define BLE_GAP_SEC_MAX_KEY_LEN 16 /**< Maximum security key len (LTK, CSRK) */ + +/** + * Advertisement options. + */ +enum BLE_GAP_ADV_OPTIONS { + BLE_GAP_OPT_ADV_DEFAULT = 0, /**< no specific option */ + BLE_GAP_OPT_ADV_WHITE_LISTED = 0x02 /**< use white list and only report whitelisted devices */ +}; + +/** + * LE security modes. * + * see BT spec PART C, 10.2 + * + * - Security mode 1 + * - Level 1: No security at all (service may use data signing) + * - Level 2: Unauthenticated (no MITM protection pairing with encryption + * - Level 3: Authenticated (MITM protection) pairing with encryption + * - Level 4: Authenticated (MITM protection) LE Secure Connection wi + * + * - Security mode 2 (data signing) + * - Level 1: Unauthenticated pairing with data signing + * - Level 2: Authenticated (MITM protection) with data signing */ +enum BLE_GAP_SEC_MODES { + GAP_SEC_NO_PERMISSION = 0, /**< No access permitted. */ + GAP_SEC_LEVEL_1, + GAP_SEC_LEVEL_2, + GAP_SEC_LEVEL_3, + GAP_SEC_LEVEL_4, + GAP_SEC_MODE_1 = 0x10, + GAP_SEC_MODE_2 = 0x20 /**< only used for data signing, level 1 or 2 */ +}; -/** BLE response/event status codes. */ -enum BLE_STATUS { - BLE_STATUS_SUCCESS = 0, /**< General BLE Success code */ - BLE_STATUS_PENDING, /**< Request received and execution started, response pending */ - BLE_STATUS_TIMEOUT, /**< Request timed out */ - BLE_STATUS_NOT_SUPPORTED, /**< Request/feature/parameter not supported */ - BLE_STATUS_NOT_ALLOWED, /**< Request not allowed */ - BLE_STATUS_LINK_TIMEOUT, /**< Link timeout (link loss) */ - BLE_STATUS_NOT_ENABLED, /**< BLE not enabled, @ref ble_enable */ - BLE_STATUS_ERROR, /**< Generic Error */ - BLE_STATUS_ALREADY_REGISTERED, /**< BLE service already registered */ - BLE_STATUS_WRONG_STATE, /**< Wrong state for request */ - BLE_STATUS_ERROR_PARAMETER, /**< Parameter in request is wrong */ - BLE_STATUS_GAP_BASE = 0x100, /**< GAP specific error base */ - BLE_STATUS_GATT_BASE = 0x200, /**< GATT specific Error base */ +/** + * Security manager passkey type. + */ +enum BLE_GAP_SM_PASSKEY_TYPE { + BLE_GAP_SM_PK_NONE = 0, /**< No key (may be used to reject). */ + BLE_GAP_SM_PK_PASSKEY, /**< Security data is a 6-digit passkey. */ + BLE_GAP_SM_PK_OOB, /**< Security data is 16 bytes of OOB data */ }; -typedef uint16_t ble_status_t; /**< Response and event BLE service status type @ref BLE_STATUS */ +/** + * Connection Parameter update request event. + */ +struct ble_gap_conn_param_update_req_evt { + struct bt_le_conn_param param; +}; + +/* - BLE_SERVICE_GAP_API.H */ + + +/** Generic BLE status response message. */ +struct ble_rsp { + struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ + int status; /**< Response status */ +}; + +/** Generic BLE response with connection reference and status. */ +struct ble_conn_rsp { + struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ + struct bt_conn *conn; /**< Connection reference */ + int status; /**< Status */ +}; + +/** BLE Enable configuration options. */ +struct ble_enable_config { + bt_addr_le_t * p_bda; /**< Optional BT device address. If NULL, internal unique static random will be used */ + struct bt_le_conn_param central_conn_params; /**< Central supported range */ +}; + +/** Parameters of MSG_ID_BLE_ENABLE_RSP. */ +struct ble_enable_rsp { + struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ + int status; /**< Response status */ + uint8_t enable; /**< Enable state: 0:Disabled, 1:Enabled */ + bt_addr_le_t bd_addr; +}; + +/** + * Attribute handle range definition. + */ +struct ble_gatt_handle_range { + uint16_t start_handle; + uint16_t end_handle; +}; + +/** Parameters of the current connection. */ +struct ble_connection_values { + uint16_t interval; /**< Connection interval (unit 1.25 ms) */ + uint16_t latency; /**< Connection latency (unit interval) */ + uint16_t supervision_to; /**< Connection supervision timeout (unit 10ms)*/ +}; + +/** Parameters for @ref MSG_ID_BLE_INIT_SVC_RSP. */ +struct ble_init_svc_rsp { + struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ + int status; +}; + +/** Authentication data. */ +struct ble_auth_data { + union { + uint8_t passkey[6]; /**< 6 digit key (000000 - 999999) */ + uint8_t obb_data[16]; /**< 16 byte of OBB data */ + }; + uint8_t type; /**< @ref BLE_GAP_SM_PASSKEY_TYPE */ +}; + +/** Parameters for @ref MSG_ID_BLE_ADV_TO_EVT. */ +struct ble_adv_to_evt { + struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ +}; + +/** + * BLE debug rsp message. + */ + +/* + * BLE debug req message. + */ +struct ble_dbg_req_rsp { + struct cfw_message header; + uint32_t u0; + 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); + +/** @endcond */ /** @}*/ #endif diff --git a/system/libarc32_arduino101/framework/include/services/ble/ble_service_gap_api.h b/system/libarc32_arduino101/framework/include/services/ble/ble_service_gap_api.h deleted file mode 100644 index 6fd62cec..00000000 --- a/system/libarc32_arduino101/framework/include/services/ble/ble_service_gap_api.h +++ /dev/null @@ -1,1036 +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. - */ - -#ifndef __BLE_SERVICE_GAP_H__ -#define __BLE_SERVICE_GAP_H__ - -#include "cfw/cfw.h" -#include "cfw/cfw_client.h" -#include "infra/version.h" -#include "ble_service_msg.h" -#include "ble_service.h" - -/** - * @defgroup ble_core_service BLE Core Service GAP/GATT APIs - * - * BLE Core service GAP/GATT APIs used by BLE service. - * - * @ingroup ble_service - * @{ - */ - -/** Macro to convert milliseconds to a specific unit */ -#define MSEC_TO_0_625_MS_UNITS(TIME) (((TIME) * 1000) / 625) -#define MSEC_TO_1_25_MS_UNITS(TIME) (((TIME) * 1000) / 1250) -#define MSEC_TO_10_MS_UNITS(TIME) ((TIME) / 10) - -/** - * BLE GAP Status return codes. - */ -enum BLE_SVC_GAP_STATUS_CODES { - BLE_SVC_GAP_STATUS_SUCCESS = BLE_STATUS_SUCCESS, /**< GAP success */ - BLE_SVC_GAP_STATUS_ERROR = BLE_STATUS_GATT_BASE, /**< Generic GAP error */ - BLE_SVC_GAP_STATUS_INVALID_UUID_LIST, /**< Invalid UUID list provided (e.g. advertisement) */ - /* TODO: add more status codes */ -}; - -/** - * BLE GAP addr types. - * - * BLE GAP supported address types - */ -enum BLE_ADDR_TYPES { - BLE_ADDR_PUBLIC = 0, /**< BD address assigned by IEEE */ - BLE_ADDR_PRIVATE_RANDOM_STATIC, /**< Random address */ - BLE_ADDR_RRIVATE_RANDOM_PRIVATE_RESOLVABLE, /**< Resolvable Private Random address */ - BLE_ADDR_PRIVATE_RANDOM_PRIVATE_NONRESOLVABLE /**< Non-resolvable Private Random address */ -}; - -/** - * BT/BLE address Length. - */ -#define BLE_ADDR_LEN 6 - -#define BLE_GAP_SEC_RAND_LEN 8 /**< Random Security number length (64 bits) */ -#define BLE_GAP_SEC_MAX_KEY_LEN 16 /**< Maximum security key len (LTK, CSRK) */ - -#define BLE_SVC_GAP_HANDLE_INVALID 0xffff /**< Invalid GAP connection handle */ - -/** - * Device GAP name characteristic write permission. - * - * If the characteristic shall be writable, use a combination of the values - * defined in @ref BLE_GAP_SEC_MODES - */ -#define BLE_DEVICE_NAME_WRITE_PERM GAP_SEC_NO_PERMISSION - -typedef struct { - uint8_t type; /**< BLE Address type @ref BLE_ADDR_TYPES */ - uint8_t addr[BLE_ADDR_LEN]; - /**< BD address, little endian format */ -} ble_addr_t; - -/** - * GAP device roles. - */ -enum BLE_ROLES { - BLE_ROLE_INVALID = 0, - BLE_ROLE_PERIPHERAL = 0x01, - BLE_ROLE_CENTRAL = 0x02 -}; - -typedef uint8_t ble_role_t; - -/** - * BLE core (GAP, GATT) Message IDs used for request, response, events and indications. - */ -enum BLE_GAP_MSG_ID { - MSG_ID_BLE_GAP_WR_CONF_REQ = MSG_ID_BLE_GAP_BASE, - MSG_ID_BLE_GAP_RD_BDA_REQ, - MSG_ID_BLE_GAP_WR_ADV_DATA_REQ, - MSG_ID_BLE_GAP_WR_WHITE_LIST_REQ, - MSG_ID_BLE_GAP_CLR_WHITE_LIST_REQ, - MSG_ID_BLE_GAP_ENABLE_ADV_REQ, - MSG_ID_BLE_GAP_DISABLE_ADV_REQ, - MSG_ID_BLE_GAP_CONN_UPDATE_REQ, - MSG_ID_BLE_GAP_DISCONNECT_REQ, - MSG_ID_BLE_GAP_SERVICE_WRITE_REQ, - MSG_ID_BLE_GAP_SERVICE_READ_REQ, - MSG_ID_BLE_GAP_SM_CONFIG_REQ, - MSG_ID_BLE_GAP_SM_PAIRING_REQ, - MSG_ID_BLE_GAP_SM_PASSKEY_REQ, - MSG_ID_BLE_GAP_SET_RSSI_REPORT_REQ, - MSG_ID_BLE_GAP_SCAN_START_REQ, - MSG_ID_BLE_GAP_SCAN_STOP_REQ, - MSG_ID_BLE_GAP_CONNECT_REQ, - MSG_ID_BLE_GAP_CONNECT_CANCEL_REQ, - MSG_ID_BLE_GAP_SET_OPTIONS_REQ, - MSG_ID_BLE_GAP_GENERIC_CMD_REQ, - MSG_ID_BLE_GAP_GET_VERSION_REQ, - MSG_ID_BLE_GAP_DTM_INIT_REQ, - MSG_ID_BLE_CTRL_LOG_REQ, - MSG_ID_BLE_GAP_REQ_LAST, - - /** BLE GAP Response Messages IDs. */ - MSG_ID_BLE_GAP_WR_CONF_RSP = MSG_ID_BLE_GAP_RSP, - /**< Write controller config: own Bluetooth Device Address, tx power */ - MSG_ID_BLE_GAP_RD_BDA_RSP, /**< Read own Bluetooth Device Address */ - MSG_ID_BLE_GAP_WR_ADV_DATA_RSP, /**< Write Advertising Data and Scan response data */ - MSG_ID_BLE_GAP_WR_WHITE_LIST_RSP, /**< Write white list to controller */ - MSG_ID_BLE_GAP_CLR_WHITE_LIST_RSP, /**< Clear current white list */ - MSG_ID_BLE_GAP_ENABLE_ADV_RSP, /**< Enable Advertising */ - MSG_ID_BLE_GAP_DISABLE_ADV_RSP, /**< Disable Advertising */ - MSG_ID_BLE_GAP_CONN_UPDATE_RSP, /**< Update Connection */ - MSG_ID_BLE_GAP_DISCONNECT_RSP, /**< Disconnect */ - MSG_ID_BLE_GAP_SERVICE_WRITE_RSP, /**< Write GAP Service specific like device name, appearance and PPCPparameters */ - MSG_ID_BLE_GAP_SERVICE_READ_RSP, /**< Read GAP Service specific like device name, appearance and PPCPparameters */ - MSG_ID_BLE_GAP_SM_CONFIG_RSP, /**< Response to @ref ble_gap_sm_config */ - MSG_ID_BLE_GAP_SM_PAIRING_RSP, /**< Response to @ref ble_gap_sm_pairing_req */ - MSG_ID_BLE_GAP_SM_PASSKEY_RSP, /**< Response to @ref ble_gap_sm_passkey_reply */ - MSG_ID_BLE_GAP_SET_RSSI_REPORT_RSP, /**< Enable/Disable reporting of changes in RSSI */ - MSG_ID_BLE_GAP_SCAN_START_RSP, /**< Start Scanning */ - MSG_ID_BLE_GAP_SCAN_STOP_RSP, /**< Stop Scanning */ - MSG_ID_BLE_GAP_CONNECT_RSP, /**< Start Connection procedure */ - MSG_ID_BLE_GAP_CONNECT_CANCEL_RSP, /**< Cancel ongoing connection procedure */ - MSG_ID_BLE_GAP_SET_OPTIONS_RSP, /**< Set gap options (e.g. co-ex, master/central role) */ - MSG_ID_BLE_GAP_GENERIC_CMD_RSP, /**< Generic non connection related requests */ - MSG_ID_BLE_GAP_GET_VERSION_RSP, - MSG_ID_BLE_GAP_DTM_INIT_RSP, - MSG_ID_BLE_CTRL_LOG_RSP, /**< BLE controller logging message */ - MSG_ID_BLE_GAP_RSP_LAST, - - /** GAP related events. */ - MSG_ID_BLE_GAP_CONNECT_EVT = MSG_ID_BLE_GAP_EVT, /**< Connection established */ - MSG_ID_BLE_GAP_DISCONNECT_EVT, /**< Disconnect from peer */ - MSG_ID_BLE_GAP_CONN_UPDATE_EVT, /**< Connection Parameters update event (in central, they have been updated, in peripheral, also includes the status of the request) */ - MSG_ID_BLE_GAP_SM_PAIRING_STATUS_EVT, /**< Pairing request status event */ - MSG_ID_BLE_GAP_SM_PASSKEY_REQ_EVT, /**< Pairing passkey request (6 digits or 16 byte OOB data) */ - MSG_ID_BLE_GAP_TO_EVT, /**< GAP Timeout event */ - MSG_ID_BLE_GAP_ADV_DATA_EVT, /**< Advertising raw data event (central role) */ - MSG_ID_BLE_GAP_RSSI_EVT, /**< Signal strength change event */ - MSG_ID_BLE_GAP_GENERIC_CMD_EVT, /**< Generic command request event */ - MSG_ID_BLE_CTRL_LOG_EVT, /**< BLE Controller Logging Events */ - MSG_ID_BLE_GAP_EVT_LAST, -}; - -/** - * Generic BLE Status Response. - * Short status response for commands not returning any additional data - */ -struct ble_rsp { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; /**< Response status @ref BLE_STATUS */ -}; - -/** - * Connection requested parameters. - */ -struct ble_gap_connection_params { - uint16_t interval_min; /**< minimal connection interval: range 0x0006 to 0x0c80 (unit 1.25ms) */ - uint16_t interval_max; /**< maximum connection interval: range 0x0006 to 0x0c80 must be bigger then min! */ - uint16_t slave_latency; /**< maximum connection slave latency: 0x0000 to 0x01f3 */ - uint16_t link_sup_to; /**< link supervision timeout: 0x000a to 0x0c80 (unit 10ms) */ -}; - -/** - * Connection values. - */ -struct ble_gap_connection_values { - uint16_t interval; /**< Connection interval (unit 1.25 ms) */ - uint16_t latency; /**< Connection latency (unit interval) */ - uint16_t supervision_to; /**< Connection supervision timeout (unit 10ms)*/ -}; - -/** - * Initial GAP configuration - */ -struct ble_wr_config { - ble_addr_t *p_bda; - uint8_t *p_name; /**< GAP Device name, NULL terminated! */ - uint16_t appearance; /**< see BLE spec */ - int8_t tx_power; - struct ble_gap_connection_params peripheral_conn_params; /**< Peripheral preferred */ - struct ble_gap_connection_params central_conn_params; /**< Central supported range */ -}; - -/** Read BD address response. */ -typedef struct { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; /**< Response status @ref BLE_STATUS */ - ble_addr_t bd; /**< if status ok @ref ble_addr_t */ -} ble_bda_rd_rsp_t; - -struct ble_gap_adv_rsp_data { - uint8_t *p_data; /**< max 31 bytes! */ - uint8_t len; -}; - -/** - * Advertising types, see BT spec vol 6, Part B, chapter 2.3. - */ -enum GAP_ADV_TYPES { - ADV_IND = 0x00, /**< Connectable undirected advertising */ - ADV_DIRECT_IND = 0x01, /**< Connectable high duty cycle advertising */ - ADV_NONCONN_IND = 0x02, /**< Non connectable undirected advertising */ - ADV_SCAN_IND = 0x06, /**< Scannable undirected advertising */ - ADV_SCAN_RSP = 0x81, /**< Scan response, only a return value in @ref ble_gap_adv_data_evt_t */ - ADV_RESERVED /* keep last */ -}; - -typedef struct { - uint8_t irk[BLE_GAP_SEC_MAX_KEY_LEN]; - /**< Identity Resolving Key (IRK) */ -} ble_gap_irk_info_t; - -struct ble_gap_whitelist_info { - ble_addr_t **pp_bd; /**< list of bd addresses */ - ble_gap_irk_info_t **pp_key; /**< list of irk keys (for address resolution offload) */ - uint8_t bd_count; /**< number of bd addresses */ - uint8_t key_count; /**< number of keys */ -}; - -/** - * Advertisement options. - */ -enum BLE_GAP_ADV_OPTIONS { - BLE_GAP_OPT_ADV_DEFAULT = 0, /**< no specific option */ - BLE_GAP_OPT_ADV_WHITE_LISTED = 0x02 /**< use white list and only report whitelisted devices */ -}; - -/** - * Advertisement parameters. - */ -typedef struct { - uint16_t timeout; - uint16_t interval_min; /**< min interval 0xffff: use default 0x0800 */ - uint16_t interval_max; /**< max interval 0xffff: use default 0x0800 */ - uint8_t type; /**< advertisement types @ref GAP_ADV_TYPES */ - uint8_t filter_policy; /**< filter policy to apply with white list */ - ble_addr_t *p_peer_bda; /**< bd address of peer device in case of directed advertisement */ - uint8_t options; /**< options see @ref BLE_GAP_ADV_OPTIONS (to be ORed) */ -} ble_gap_adv_param_t; - -/** - * Generic BLE Status. Response - * Short status response for commands not returning any additional data - */ -typedef struct { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; /**< Response status @ref BLE_STATUS */ - uint32_t wl_handle; /**< reference handle. to be used for clearing it later */ -} ble_gap_wr_white_list_rsp_t; - - -/** - * Appearance read response message. - */ -typedef struct { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; /**< Response status @ref BLE_STATUS */ - uint16_t uuid; /**< value of GAP appearance characteristic */ -} ble_rd_appearance_rsp_t; - -/** - * LE security modes. - * - * see BT spec PART C, 10.2 - * - * - Security mode 1 - * - Level 1: No security at all (service may use data signing) - * - Level 2: Unauthenticated (no MITM protection pairing with encryption - * - Level 3: Authenticated (MITM protection) pairing with encryption - * - Level 4: Authenticated (MITM protection) LE Secure Connection wi - * - * - Security mode 2 (data signing) - * - Level 1: Unauthenticated pairing with data signing - * - Level 2: Authenticated (MITM protection) with data signing - */ -enum BLE_GAP_SEC_MODES { - GAP_SEC_NO_PERMISSION = 0, /**< No access permitted. */ - GAP_SEC_LEVEL_1, - GAP_SEC_LEVEL_2, - GAP_SEC_LEVEL_3, - GAP_SEC_LEVEL_4, - GAP_SEC_MODE_1 = 0x10, - GAP_SEC_MODE_2 = 0x20 /**< only used for data signing, level 1 or 2 */ -}; - -struct ble_gap_svc_local_name { - uint8_t sec_mode; /**< security mode for writing device name, @ref BLE_GAP_SEC_MODES */ - uint8_t authorization; /**< 0: no authorization, 1: authorization required */ - uint8_t len; /**< device name length (0-248) */ - const uint8_t *p_name; /**< name to to write */ -}; - -enum BLE_GAP_SVC_ATTR_TYPE { - GAP_SVC_ATTR_NAME = 0, /**< Device Name, UUID 0x2a00 */ - GAP_SVC_ATTR_APPEARANCE, /**< Appearance, UUID 0x2a01 */ - GAP_SVC_ATTR_PPCP = 4, /**< Peripheral Preferred Connection Parameters (PPCP), UUID 0x2a04 */ - GAP_SVC_ATTR_CAR = 0xa6, /**< Central Address Resolution (CAR), UUID 0x2aa6, BT 4.2 */ -}; - -struct ble_gap_service_write_params { - uint16_t attr_type; /**< GAP Characteristics attribute type @ref BLE_GAP_SVC_ATTR_TYPE */ - union { - struct ble_gap_svc_local_name name; - uint16_t appearance; /**< Appearance UUID */ - struct ble_gap_connection_params conn_params; - /**< Preferred Peripheral Connection Parameters */ - uint8_t car; /**< Central Address Resolution support 0: no, 1: yes */ - }; -}; - -struct ble_gap_service_read_rsp { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; /**< status of read operation @ref BLE_STATUS, in case failure union shall be empty */ - uint16_t attr_type; /**< type of attribute returned (valid even in failure case! */ - union { - struct ble_gap_svc_local_name name; - uint16_t appearance; /**< Appearance UUID */ - struct ble_gap_connection_params conn_params; /**< Preferred Peripheral Connection Parameters */ - uint8_t car; /** Central Address Resolution support 0: no, 1: yes */ - }; -}; - -/** - * GAP security manager options for bonding/authentication procedures, see Vol 3: Part H, 3.5. - */ -enum BLE_GAP_SM_OPTIONS { - BLE_GAP_BONDING = 0x01, /**< SMP supports bonding */ - BLE_GAP_MITM = 0x04, /**< SMP requires Man In The Middle protection */ - BLE_GAP_OOB = 0x08 /**< SMP supports Out Of Band data */ -}; - -/** - * IO capabilities, see Vol 3: PART H, 3.5. - */ -enum BLE_GAP_IO_CAPABILITIES { - BLE_GAP_IO_DISPLAY_ONLY = 0, - BLE_GAP_IO_DISPLAY_YESNO = 1, - BLE_GAP_IO_KEYBOARD_ONLY = 2, - BLE_GAP_IO_NO_INPUT_NO_OUTPUT = 3, - BLE_GAP_IO_KEYBOARD_DISPLAY = 4 -}; - -/** - * Security manager configuration parameters. - * - * options and io_caps will define there will be a passkey request or not. - * It is assumed that io_caps and options are compatible. - */ -struct ble_gap_sm_config_params { - uint8_t options; /**< Security options (@ref BLE_GAP_SM_OPTIONS) */ - uint8_t io_caps; /**< I/O Capabilities to allow passkey exchange (@ref BLE_GAP_IO_CAPABILITIES) */ - uint8_t key_size; /**< Maximum encryption key size (7-16) */ -}; - -/** - * Security manager pairing parameters. - */ -struct ble_gap_sm_pairing_params { - uint8_t auth_level; /**< authentication level see @ref BLE_GAP_SM_OPTIONS */ -}; - -/** - * Security manager passkey type. - */ -enum BLE_GAP_SM_PASSKEY_TYPE { - BLE_GAP_SM_PASSKEY = 0, /**< Security data is a passkey. */ - BLE_GAP_SM_OBB, /**< Security data is 16 bytes of OOB data */ -}; -/** - * Security reply to incoming security request. - */ -struct ble_gap_sm_passkey { - uint8_t type; /**< Security data type in this reply @ref BLE_GAP_SM_PASSKEY_TYPE */ - union { - uint8_t passkey[6]; /**< 6 digits (string) */ - uint8_t oob[16]; /**< 16 bytes of OOB security data */ - }; -}; - -/** - * RSSI operation definition. - */ -enum BLE_GAP_RSSI_OPS { - BLE_GAP_RSSI_DISABLE_REPORT = 0, - BLE_GAP_RSSI_ENABLE_REPORT -}; - -enum BLE_GAP_SCAN_OPTIONS { - BLE_GAP_SCAN_DEFAULT = 0, /**< no specific option */ - BLE_GAP_SCAN_ACTIVE = 0x01, /**< do an active scan (request scan response */ - BLE_GAP_SCAN_WHITE_LISTED = 0x02 /**< Use white list and only report whitelisted devices */ -}; - -enum BLE_GAP_SET_OPTIONS { - BLE_GAP_SET_CH_MAP = 0, /**< Set channel map */ -}; - -typedef struct { - uint16_t conn_handle; /**< connection on which to change channel map */ - uint8_t map[5]; /**< 37 bits are used of the 40 bits (LSB) */ -} ble_gap_channel_map_t; - -/** - * GAP option data structure. - */ -typedef union { - ble_gap_channel_map_t ch_map; /**< BLE channel map to set see BT spec */ -} ble_gap_option_t; - -/** - * Scan parameters. - * - * @note Check BT core spec for high low duty cycle interval & window size! - */ -typedef struct { - uint16_t timeout; /**< scan timeout in s, 0 never */ - uint16_t interval; /**< interval: 0x4 - 0x4000. (unit: 0.625ms), use default: 0xffff (0x0010) */ - uint16_t window; /**< Window: 0x4 - 0x4000. (unit: 0.625ms), use default 0xffff (= 0x0010) */ - uint8_t options; /**< scan options, ORed options from @ref BLE_GAP_SCAN_OPTIONS */ -} ble_gap_scan_param_t; - -/** - * Connect event @ref MSG_ID_BLE_GAP_CONNECT_EVT. - */ -struct ble_gap_connect_evt { - struct ble_gap_connection_values conn_values; /**< Connection values */ - uint8_t role; /**< role in this connection @ref */ - ble_addr_t peer_bda; /**< address of peer device */ -}; - -/** - * Disconnect event @ref MSG_ID_BLE_GAP_DISCONNECT_EVT. - */ -struct ble_gap_disconnected_evt { - uint8_t hci_reason; /**< HCI disconnect reason */ -}; - -/** - * Updated connection event @ref MSG_ID_BLE_GAP_CONN_UPDATE_EVT. - */ -struct ble_gap_conn_update_evt { - struct ble_gap_connection_values conn_values; -}; - -/** - * Security manager pairing status event @ref MSG_ID_BLE_GAP_SM_PAIRING_STATUS_EVT. - */ -struct ble_gap_sm_pairing_status_evt { - uint16_t conn_handle; - uint16_t status; -}; - -/** - * Security manager passkey request event @ref MSG_ID_BLE_GAP_SM_PASSKEY_REQ_EVT. - */ -struct ble_gap_sm_passkey_req_evt { - uint8_t dummy; -}; - -/** - * GAP/SMP security result status code. - * see Vol 3: Part H, chapter 3.5.5. - */ -enum BLE_GAP_SEC_RESULT_STATUS { - BLE_GAP_SEC_STATUS_SUCCESS = 0, - /**< bonding/pairing completed successfully */ - BLE_GAP_SEC_STATUS_PASSKEY_ENTRY_FAILED,/**< passkey entry failed */ - BLE_GAP_SEC_STATUS_OOB_NOT_AVAILABLE, /**< Out of Band data is not available */ - BLE_GAP_SEC_STATUS_AUTH_REQUIREMENTS, /**< Authentication requirements not met due to IO cap */ - BLE_GAP_SEC_STATUS_CONFIRM_VALUE, /**< Confirm value does not match calculated value */ - BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPPORTED, - /**< Pairing not supported by the device */ - BLE_GAP_SEC_STATUS_ENC_KEY_SIZE, /**< Encryption key size insufficient */ - BLE_GAP_SEC_STATUS_SMP_CMD_UNSUPPORTED, /**< Unsupported SMP command on this device */ - BLE_GAP_SEC_STATUS_UNSPECIFIED, /**< Failure due to unspecified reason */ - BLE_GAP_SEC_STATUS_REPEATED_ATTEMPTS, /**< Pairing/authent disallowed due to too little time elapsed since last attempt */ - BLE_GAP_SEC_STATUS_INVALID_PARAMS, /**< Invalid parameters due to length or parameters */ - /* 4.2 spec only ? */ - BLE_GAP_SEC_STATUS_DHKEY_CHECK_FAILED, /**< Remote device indicates that DHKey does not match local calculated key */ - BLE_GAP_SEC_STATUS_NUMERIC_COMP_FAILED, /**< values in numeric key comparison protocol do not match */ - BLE_GAP_SEC_STATUS_BREDR_PAIRING_INPROGRESS,/**< Failure due to BR/EDR pairing request */ - BLE_GAP_SEC_STATUS_CROSS_TSPRT_KEY_GEN_DIS, - /**< BR/EDR link key generation can not be use for LE keys handling */ -}; - -enum BLE_SVC_GAP_TIMEOUT_REASON { - BLE_SVC_GAP_TO_ADV, /**< Advertisement Stopped. */ - BLE_SVC_GAP_TO_SEC_REQ, /**< Security Request took too long. */ - BLE_SVC_GAP_TO_SCAN, /**< Scanning stopped. */ - BLE_SVC_GAP_TO_CONN, /**< Connection Link timeout. */ -}; - -/** - * GAP timeout event (e.g. protocol error) MSG_ID_BLE_GAP_TO_EVT. - */ -struct ble_gap_timout_evt { - int reason; /**< reason for timeout @ref BLE_SVC_GAP_TIMEOUT_REASON */ -}; - -/** - * Advertisement data structure (central role) @ref MSG_ID_BLE_GAP_ADV_DATA_EVT. - */ -struct ble_gap_adv_data_evt { - ble_addr_t remote_bda; /**< address of remote device */ - int8_t rssi; /**< signal strength compared to 0 dBm */ - uint8_t type; /**< type of advertisement data or scan response @ref GAP_ADV_TYPES */ - uint8_t len; /**< length of advertisement data or scap response data */ - uint8_t data[]; /**< Advertisement or scan response data */ -}; - -/** - * Connection Parameter update request event @ref MSG_ID_BLE_GAP_CONN_PARAM_UPDATE_REQ_EVT. - * - * @note reply with @ref ble_gap_conn_update_params - */ -struct ble_gap_conn_param_update_req_evt { - struct ble_gap_connection_params param; -}; - -/** - * RSSI signal strength event @ref MSG_ID_BLE_GAP_RSSI_EVT. - */ -struct ble_gap_rssi_evt { - int8_t rssi_lvl; /**< RSSI level (compared to 0 dBm) */ -}; - -/** - * RSSI report parameters @ref MSG_ID_BLE_GAP_SET_RSSI_REPORT_REQ. - */ -struct rssi_report_params { - uint16_t conn_hdl; /**< Connection handle */ - uint8_t op; /**< RSSI operation @ref BLE_GAP_RSSI_OPS */ - uint8_t delta_dBm; /**< minimum RSSI dBm change to report a new RSSI value */ - uint8_t min_count; /**< number of delta_dBm changes before sending a new RSSI report */ -}; - -/** Test Mode opcodes. */ -enum TEST_OPCODE { - BLE_TEST_INIT_DTM = 0x01, /**< Put BLE controller in HCI UART DTM test mode */ - BLE_TEST_START_DTM_RX = 0x1d, /**< LE receiver test HCI opcode */ - BLE_TEST_START_DTM_TX = 0x1e, /**< LE transmitter test HCI opcode */ - BLE_TEST_END_DTM = 0x1f, /**< End LE DTM TEST */ - /* vendor specific commands start at 0x80 */ - BLE_TEST_SET_TXPOWER = 0x80, /**< Set Tx power. To be called before start of tx test */ - BLE_TEST_START_TX_CARRIER, /**< Start Tx Carrier Test */ -}; - -/** - * Rx direct test mode data structure. - */ -struct ble_dtm_rx_test { - uint8_t freq; /**< rf channel 0x00 - 0x27, resulting F = 2402 MHz + [freq * 2 MHz] */ -}; - -/** - * Tx direct test mode data structure - */ -struct ble_dtm_tx_test { - uint8_t freq; /**< rf channel 0x00 - 0x27 where resulting F = 2402 + [freq * 2 MHz] */ - uint8_t len; /**< length of test data payload for each packet */ - uint8_t pattern; /**< packet payload pattern type, 0x00 - 0x02 mandatory */ -}; - -/** - * Tx power settings data structure. - */ -struct ble_set_txpower { - int8_t dbm; /**< Tx power level to set (e.g. -30: -30 dBm). Depends on BLE Controller */ -}; - -/** - * RX test result data. - */ -struct ble_dtm_test_result { - uint16_t mode; - uint16_t nb; -}; - -/** - * Direct Test mode command params - */ -struct ble_test_cmd { - uint8_t mode; /**< test mode to execute @ref TEST_OPCODE */ - union { - struct ble_dtm_rx_test rx; - struct ble_dtm_tx_test tx; - struct ble_set_txpower tx_pwr; /**< Tx power to use for Tx tests. */ - }; -}; - -/** - * BLE GAP event structure. - */ -struct ble_gap_event { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - uint16_t conn_handle; /**< connection handle */ - union { - struct ble_gap_connect_evt connected; /**< connected event parameters */ - struct ble_gap_disconnected_evt disconnected; /**< disconnected reason */ - struct ble_gap_conn_update_evt conn_updated; /**< connection updated */ - struct ble_gap_sm_pairing_status_evt sm_pairing_status; /**< Security Manager pairing status */ - struct ble_gap_sm_passkey_req_evt sm_passkey_req; /**< Security Manager passkey request */ - /**< connection related security update */ - struct ble_gap_timout_evt timeout; /**< gap timeout occurred */ - struct ble_gap_adv_data_evt adv_data; /**< advertisement data */ - struct ble_gap_conn_param_update_req_evt conn_param_req; - /**< update request from remote for connection parameters */ - struct ble_gap_rssi_evt rssi; /**< new rssi level if rssi reporting is enabled */ - }; -}; - -/** Generic request op codes. - * This allows to access some non connection related commands like DTM. - */ -enum BLE_GAP_GEN_OPS { - DUMMY_VALUE = 0, /**< Not used now. */ -}; - -/** - * Generic command parameters. - * - * @note Independent of connection! - */ -struct ble_gap_gen_cmd_params { - uint8_t op_code; /**< @ref BLE_GAP_GEN_OPS */ -}; - -struct ble_version_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; - struct version_header version; /**< Nordic version header */ -}; - -struct ble_dtm_init_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; -}; - -struct ble_dtm_result_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; - struct ble_dtm_test_result result; /**< Result data of DTM RX test */ -}; - -/** - * Generic request message response or event. - */ -struct ble_generic_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; - uint8_t op_code; /**< Opcode to which this message is applicable @ref BLE_GAP_GEN_OPS */ -}; - -/** - * Set Enable configuration parameters (BD address, etc). - * - * This shall put the controller stack into a usable (enabled) state. - * Hence this should be called first! - * - * @param p_svc_handle service handle - * @param p_config BLE write configuration - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG_ID_BLE_GAP_WR_CONF_RSP @ref ble_rsp, TODO: return maybe more info? - */ -int ble_gap_set_enable_config(svc_client_handle_t * p_svc_handle, - const struct ble_wr_config * p_config, void *p_priv); - -/** - * Read BD address from Controller. - * - * - * @param p_svc_handle service handle - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: @ref MSG_ID_BLE_GAP_RD_BDA_RSP @ref ble_bda_rd_rsp_t - */ -int ble_gap_read_bda(svc_client_handle_t * p_svc_handle, void *p_priv); - -/** - * Write Advertisement data to BLE controller. - * - * Store advertisement data in BLE controller. It needs to be done BEFORE starting advertisement - * - * @param p_svc_handle service handle - * @param p_adv_data adv data to store in BLE controller - * @param p_scan_data scan response data to store in controller, can be NULL - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_WR_ADV_DATA_RSP @ref ble_rsp - */ -int ble_gap_wr_adv_data(svc_client_handle_t * p_svc_handle, - const struct ble_gap_adv_rsp_data * p_adv_data, - const struct ble_gap_adv_rsp_data * p_scan_data, - void *p_priv); - -/** - * Write white list to the BLE controller. - * - * Store white in BLE controller. It needs to be done BEFORE starting advertisement or - * start scanning - * - * @param p_svc_handle service handle - * @param p_white_list white list to store in the controller - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_WR_WHITE_LIST @ref ble_gap_wr_white_list_rsp_t - */ -int ble_gap_wr_white_list(svc_client_handle_t * p_svc_handle, - const struct ble_gap_whitelist_info * p_white_list, - void *p_priv); - -/** - * Clear previously stored white list. - * - * @param p_svc_handle service handle - * @param wl_handle handle to the white list previously stored - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GAP_CLR_WHITE_LIST @ref ble_rsp - */ -int ble_gap_clr_white_list(svc_client_handle_t * p_svc_handle, - uint32_t wl_handle, void *p_priv); - -/** - * Start advertising. - * - * @param p_svc_handle service handle - * @param p_adv_param advertisement - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GAP_ENABLE_ADV @ref ble_rsp - */ -int ble_gap_start_advertise(svc_client_handle_t * p_svc_handle, - const ble_gap_adv_param_t * p_adv_param, - void *p_priv); - -/** - * Stop advertising. - * - * @param p_svc_handle service handle - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GAP_DISABLE_ADV @ref ble_rsp - */ -int ble_gap_stop_advertise(svc_client_handle_t * p_svc_handle, void *p_priv); - -/** - * Update connection. - * - * This function's behavior depends on the role of the connection: - * - in peripheral mode, it sends an L2CAP signaling connection parameter - * update request based the values in @ref p_conn_param - * and the action can be taken by the central at link layer - * - in central mode, it will send a link layer command to change the - * connection values based on the values in @ref p_conn_param where the - * connection interval is interval_min - * - * When the connection is updated, the event @ref MSG_ID_BLE_GAP_CONN_UPDATE_EVT will - * be received. - * - * @param conn_handle Connection handle - * @param p_conn_param Connection parameters - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: @ref MSG_ID_BLE_GAP_CONN_UPDATE_RSP @ref ble_rsp - */ -int ble_gap_conn_update(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const struct ble_gap_connection_params * p_conn_param, - void *p_priv); - -/** - * Disconnect connection (peripheral or central role). - * - * @param p_svc_handle service handle - * @param conn_hhdl connection to terminate - * @param reason HCI reason for connection termination, most often 0x16 (connection terminated by local host) - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GAP_DISCONNECT @ref ble_rsp, MSG_ID_BLE_GAP_DISCONNECT_EVT @ref ble_gap_disconnected_evt_t - */ -int ble_gap_disconnect(svc_client_handle_t * p_svc_handle, - uint16_t conn_hhdl, uint8_t reason, - void *p_priv); -/** - * Write GAP Service Attribute Characteristics. - * - * @param p_svc_handle service handle - * @param p_params data of characteristic to write - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GAP_SERVICE_WRITE_RSP @ref ble_rsp - */ -int ble_gap_service_write(svc_client_handle_t * p_svc_handle, - const struct ble_gap_service_write_params * p_params, - void *p_priv); - -/** - * Read GAP Service Characteristics. - * - * @param p_svc_handle service handle - * @param type type of GAP service data characteristic to read @ref BLE_GAP_SVC_ATTR_TYPE - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_SERVICE_READ_RSP @ref ble_gap_service_read_rsp - */ -int ble_gap_service_read(svc_client_handle_t * p_svc_handle, - uint16_t type, void * p_priv); - -/** - * Function for configuring the security manager. - * - * @param h Service client - * @param p_params local authentication/bonding parameters - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * - * @note Upon completion of the procedure, the client will receive - * a message @ref MSG_ID_BLE_GAP_SM_CONFIG_RSP - */ -int ble_gap_sm_config(const svc_client_handle_t * h, - const struct ble_gap_sm_config_params * p_params, - void *p_priv); - -/** - * Initiate the bonding procedure (central). - * - * @param h Service client - * @param conn_handle connection on which bonding procedure is executed - * @param p_params local authentication/bonding parameters - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * - * @note Upon completion of the procedure, the client receives - * @ref MSG_ID_BLE_GAP_SM_PAIRING_RSP - */ -int ble_gap_sm_pairing_req(const svc_client_handle_t * h, - uint16_t conn_handle, - const struct ble_gap_sm_pairing_params * p_params, - void *p_priv); - -/** - * Reply to an incoming passkey request event (@ref MSG_ID_BLE_GAP_SM_PASSKEY_REQ_EVT). - * - * @param p_svc_handle service handle - * @param conn_handle connection on which bonding is going on - * @param p_params bonding security reply - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * - * @note Upon completion of the procedure, the client receives - * @ref MSG_ID_BLE_GAP_SM_PASSKEY_RSP - */ -int ble_gap_sm_passkey_reply(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const struct ble_gap_sm_passkey * p_params, - void *p_priv); - -/** - * Enable disable the reporting of the RSSI value. - * - * @param p_svc_handle service handle - * @param conf RSSI report parameters @ref MSG_ID_BLE_GAP_SET_RSSI_REPORT_REQ - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_SET_RSSI_REPORT_RSP @ref ble_rsp - */ -int ble_gap_set_rssi_report(svc_client_handle_t * p_svc_handle, - const struct rssi_report_params *params, - void *p_priv); - -/** - * Start scanning for BLE devices doing advertisement. - * - * @param p_svc_handle service handle - * @param p_scan_params scan parameters to use @ref ble_gap_scan_param_t - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_SCAN_START_RSP @ref ble_rsp - */ -int ble_gap_start_scan(svc_client_handle_t * p_svc_handle, - const ble_gap_scan_param_t * p_scan_params, - void *p_priv); - -/** - * Stop scanning. - * - * @param p_svc_handle service handle - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_STOP_START_RSP @ref ble_rsp - */ -int ble_gap_stop_scan(svc_client_handle_t * p_svc_handle, void *p_priv); - -/** - * Connect to a Remote Device. - * - * @param p_svc_handle service handle - * @param p_bd bd to connect to. shall be null if BLE_GAP_SCAN_WHITE_LISTED option is set in @ref ble_gap_scan_param_t - * @param p_scan_params scan parameters - * @param p_conn_params connection parameters - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_CONNECT_RSP @ref ble_rsp, - * @return MSG: MSG_ID_BLE_GAP_CONNECT_EVT @ref ble_gap_connect_evt_t - */ -int ble_gap_connect(svc_client_handle_t * p_svc_handle, const ble_addr_t * p_bd, - const ble_gap_scan_param_t * p_scan_params, - const struct ble_gap_connection_params * p_conn_params, - void *p_priv); - -/** - * Cancel an ongoing connection attempt. - * - * @param p_svc_handle service handle - * @param p_bd bd address of device for which the connection shall be canceled - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_CONNECT @ref ble_rsp - */ -int ble_gap_cancel_connect(svc_client_handle_t * p_svc_handle, - const ble_addr_t * p_bd, void *p_priv); - -/** - * Set a gap option (channel map etc) on a connection. - * - * @param p_svc_handle service handle - * @param op option to set @ref BLE_GAP_SET_OPTIONS - * @param p_opt bd address of device for which the connection shall be canceled ble_gap_option_t - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_SET_OPTIONS @ref ble_rsp - */ -int ble_gap_set_option(svc_client_handle_t * p_svc_handle, uint8_t op, - const ble_gap_option_t * p_opt, void *p_priv); - -/** - * Set a gap option (channel map etc) on a connection. - * - * @param p_svc_handle service handle - * @param p_params bd address of device for which the connection shall be canceled ble_gap_option_t - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_GENERIC_CMD_RSP @ref ble_rsp or @ref ble_generic_msg - */ -int ble_gap_generic_cmd_req(svc_client_handle_t * p_svc_handle, - const struct ble_gap_gen_cmd_params *p_params, - void *p_priv); - -/** - * Get nordic version. - * - * @param p_svc_handle service handle - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_GET_VERSION_RSP @ref ble_rsp or @ref ble_generic_msg - */ -int ble_gap_get_version_req(svc_client_handle_t * p_svc_handle, - void *p_priv); - -/** - * Init dtm mode. - * - * @param p_svc_handle service handle - * @param p_params bd address of device for which the connection shall be canceled ble_gap_option_t - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GAP_DTM_INIT_RSP @ref ble_rsp or @ref ble_generic_msg - */ -int ble_gap_dtm_init_req(svc_client_handle_t * p_svc_handle, - void *p_priv); -/** @} */ - -#endif /* __BLE_SVC_API_H__ */ diff --git a/system/libarc32_arduino101/framework/include/services/ble/ble_service_gatt.h b/system/libarc32_arduino101/framework/include/services/ble/ble_service_gatt.h deleted file mode 100644 index 23c65b73..00000000 --- a/system/libarc32_arduino101/framework/include/services/ble/ble_service_gatt.h +++ /dev/null @@ -1,325 +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. - */ - -#ifndef __BLE_SERVICE_GATT_H__ -#define __BLE_SERVICE_GATT_H__ - -#include "ble_service.h" -#include "ble_service_gap_api.h" - -/** GATT common definitions. - * - * @ingroup ble_core_service - * - * @addtogroup ble_core_service_gatt BLE core service common GATT definitions - * @{ - */ - -/** - * GATT Success code and error codes. - */ -enum BLE_SVC_GATT_STATUS_CODES { - BLE_SVC_GATT_STATUS_SUCCESS = BLE_STATUS_SUCCESS, /**< GATT success @ref BLE_STATUS_SUCCESS */ - BLE_SVC_GATT_STATUS_ENCRYPTED_MITM = BLE_SVC_GATT_STATUS_SUCCESS, - BLE_SVC_GATT_STATUS_INVALID_HANDLE = BLE_STATUS_GATT_BASE + 0x01,/**< 0x01 see BT Spec Vol 3: Part F (ATT), chapter 3.4.1.1 */ - BLE_SVC_GATT_STATUS_READ_NOT_PERMIT, - BLE_SVC_GATT_STATUS_WRITE_NOT_PERMIT, - BLE_SVC_GATT_STATUS_INVALID_PDU, - BLE_SVC_GATT_STATUS_INSUF_AUTHENTICATION, - BLE_SVC_GATT_STATUS_REQ_NOT_SUPPORTED, - BLE_SVC_GATT_STATUS_INVALID_OFFSET, - BLE_SVC_GATT_STATUS_INSUF_AUTHORIZATION, - BLE_SVC_GATT_STATUS_PREPARE_Q_FULL, - BLE_SVC_GATT_STATUS_NOT_FOUND, - BLE_SVC_GATT_STATUS_NOT_LONG, - BLE_SVC_GATT_STATUS_INSUF_KEY_SIZE, - BLE_SVC_GATT_STATUS_INVALID_ATTR_LEN, - BLE_SVC_GATT_STATUS_ERR_UNLIKELY, - BLE_SVC_GATT_STATUS_INSUF_ENCRYPTION, - BLE_SVC_GATT_STATUS_UNSUPPORT_GRP_TYPE, - BLE_SVC_GATT_STATUS_INSUF_RESOURCE, - - /**< TODO: maybe be not needed, to be covered by generic GAP status */ - BLE_SVC_GATT_STATUS_NO_RESOURCES = BLE_STATUS_GATT_BASE | 0x80, - BLE_SVC_GATT_STATUS_INTERNAL_ERROR, - BLE_SVC_GATT_STATUS_WRONG_STATE, - BLE_SVC_GATT_STATUS_DB_FULL, - BLE_SVC_GATT_STATUS_BUSY, - BLE_SVC_GATT_STATUS_ERROR, - BLE_SVC_GATT_STATUS_CMD_STARTED, - BLE_SVC_GATT_STATUS_ILLEGAL_PARAMETER, - BLE_SVC_GATT_STATUS_PENDING, - BLE_SVC_GATT_STATUS_AUTH_FAIL, - BLE_SVC_GATT_STATUS_MORE, - BLE_SVC_GATT_STATUS_INVALID_CFG, - BLE_SVC_GATT_STATUS_SERVICE_STARTED, - BLE_SVC_GATT_STATUS_ENCRYPTED_NO_MITM, - BLE_SVC_GATT_STATUS_NOT_ENCRYPTED, - BLE_SVC_GATT_STATUS_CONGESTED, -}; - -/** - * GATT Server Message ID definitions. - */ -enum BLE_GATTS_MSG_ID { - /**< GATT Server Requests */ - MSG_ID_BLE_GATTS_ADD_SERVICE_REQ = MSG_ID_BLE_GAP_REQ_LAST, - MSG_ID_BLE_GATTS_ADD_INCL_SVC_REQ, - MSG_ID_BLE_GATTS_ADD_CHARACTERISTIC_REQ, - MSG_ID_BLE_GATTS_ADD_DESCRIPTOR_REQ, - MSG_ID_BLE_GATTS_START_SERVICE_REQ, - MSG_ID_BLE_GATTS_REMOVE_SERVICE_REQ, - MSG_ID_BLE_GATTS_INDICATE_SERVICE_CHANGE_REQ, - MSG_ID_BLE_GATTS_SET_ATTRIBUTE_VALUE_REQ, - MSG_ID_BLE_GATTS_GET_ATTRIBUTE_VALUE_REQ, - MSG_ID_BLE_GATTS_SEND_NOTIF_REQ, - MSG_ID_BLE_GATTS_SEND_IND_REQ, - MSG_ID_BLE_GATTS_SEND_RW_AUTHORIZATION_REQ, - MSG_ID_BLE_GATTS_WR_CONN_ATTRIBUTES_REQ, - MSG_ID_BLE_GATTS_RD_CONN_ATTRIBUTES_REQ /* 37 */ , - MSG_ID_BLE_GATTS_REQ_LAST, - - /**< GATT Server Requests */ - MSG_ID_BLE_GATTS_ADD_SERVICE_RSP = MSG_ID_BLE_GAP_RSP_LAST, - /**< create new service */ - MSG_ID_BLE_GATTS_ADD_INCL_SVC_RSP, - MSG_ID_BLE_GATTS_ADD_CHARACTERISTIC_RSP, - MSG_ID_BLE_GATTS_ADD_DESCRIPTOR_RSP, - MSG_ID_BLE_GATTS_START_SERVICE_RSP, /**< enable created service */ - MSG_ID_BLE_GATTS_REMOVE_SERVICE_RSP, /**< stop and remove service */ - MSG_ID_BLE_GATTS_INDICATE_SERVICE_CHANGE_RSP, /**< indicate a service change */ - MSG_ID_BLE_GATTS_SET_ATTRIBUTE_VALUE_RSP, - MSG_ID_BLE_GATTS_GET_ATTRIBUTE_VALUE_RSP, - MSG_ID_BLE_GATTS_SEND_NOTIF_RSP, /**< send notification */ - MSG_ID_BLE_GATTS_SEND_IND_RSP, /**< send indication */ - MSG_ID_BLE_GATTS_SEND_RW_AUTHORIZATION_RSP, /**< authorize a R/W request from remote */ - MSG_ID_BLE_GATTS_WR_CONN_ATTRIBUTES_RSP, /**< write connection related attributes (previously bonded!) */ - MSG_ID_BLE_GATTS_RD_CONN_ATTRIBUTES_RSP /* 37 */ , /**< read connection related attributes (only for bonded connections!*/ - MSG_ID_BLE_GATTS_RSP_LAST, - - /**< GATT Server Events */ - MSG_ID_BLE_GATTS_WRITE_EVT = MSG_ID_BLE_GAP_EVT_LAST, /**< remote client write happened */ - MSG_ID_BLE_GATTS_RW_AUTHORIZATION_REQ_EVT, /**< remote client R/W authorization request */ - MSG_ID_BLE_GATTS_CONN_ATTRIB_MISSING_EVT, /**< connection related attributes have not been set, access pending */ - MSG_ID_BLE_GATTS_INDICATION_CONF_EVT, /**< indication confirmation event */ - MSG_ID_BLE_GATTS_SVC_CHG_CONF_EVT, /**< confirmation of service change indication (no params) */ - MSG_ID_BLE_GATTS_TO_EVT, /**< GATTS timeout indication */ - MSG_ID_BLE_GATTS_EVT_LAST -}; - -/** - * GATT Client Message ID definitions. - */ -enum BLE_GATTC_MSG_ID { - /**< GATT Client Requests, responses, events and indications */ - MSG_ID_BLE_GATTC_DISCOVER_PRIMARY_SERVICE_REQ = - MSG_ID_BLE_GATTS_REQ_LAST, - MSG_ID_BLE_GATTC_DISCOVER_INCLUDED_SERVICES_REQ, - MSG_ID_BLE_GATTC_DISCOVER_CHAR_REQ, - MSG_ID_BLE_GATTC_DISCOVER_DESCRIPTOR_REQ, - MSG_ID_BLE_GATTC_RD_CHARS_REQ, - MSG_ID_BLE_GATTC_WR_OP_REQ, - MSG_ID_BLE_GATTC_SEND_HANDLE_VALUE_REQ /* 44 */ , - - /** GATT Client Requests, responses, events and indications */ - MSG_ID_BLE_GATTC_DISCOVER_PRIMARY_SERVICE_RSP = MSG_ID_BLE_GATTS_RSP_LAST, /**< discover primary service */ - MSG_ID_BLE_GATTC_DISCOVER_INCLUDED_SERVICES_RSP,/**< find included service procedure */ - MSG_ID_BLE_GATTC_DISCOVER_CHAR_RSP, /**< discover characteristics of a service */ - MSG_ID_BLE_GATTC_DISCOVER_DESCRIPTOR_RSP, /**< discover descriptor of a characteristic */ - MSG_ID_BLE_GATTC_RD_CHARS_RSP, /**< read characteristic or long characteristics */ - MSG_ID_BLE_GATTC_WR_OP_RSP, /**< different types of write operations */ - MSG_ID_BLE_GATTC_SEND_HANDLE_VALUE_RSP /* 44 */ , /**< send attribute handle to server */ - - /** GATT Client Events */ - MSG_ID_BLE_GATTC_DISC_PRIM_SVC_EVT = MSG_ID_BLE_GATTS_EVT_LAST, /**< primary service discovery response */ - MSG_ID_BLE_GATTC_DISC_INCL_SVC_EVT, /**< include service discovery response */ - MSG_ID_BLE_GATTC_DISC_CHAR_EVT, /**< characteristic discovery response */ - MSG_ID_BLE_GATTC_DISC_DESCR_EVT, /**< descriptor discovery response */ - MSG_ID_BLE_GATTC_RD_EVT, /**< data read response */ - MSG_ID_BLE_GATTC_WR_EVT, /**< data write response */ - MSG_ID_BLE_GATTC_HDL_NOTIF_EVT, /**< handle indication/notification event */ - MSG_ID_BLE_GATTC_TO_EVT, /**< GATT Client timeout event */ - MSG_ID_BLE_GATTC_LAST -}; - -/** - * Maximum UUID size - 16 bytes, and structure to hold any type of UUID. - */ -#define MAX_UUID_SIZE 16 - -#define BLE_GATT_INVALID_HANDLE 0x0000 /**< reserved invalid attribute handle */ -#define BLE_GATT_MAX_HANDLE 0xffff /**< maximum handle in a BLE server */ -#define BLE_GATT_START_HANDLE_DISCOVER 0x0001 /**< Value of start handle during discovery. */ - -/** BT uuid types defined as length. */ -enum BT_UUID_TYPES { - BT_UUID16 = 2, /**< 16 bit UUID type */ - BT_UUID32 = 4, /**< 32 bit UUID type */ - BT_UUID128 = 16 /**< 128 bit UUID type */ -}; - -/** - * Generic uuid structure specific to BT/BLE. - */ -struct bt_uuid { - uint8_t type; /**< UUID type (encoded as length of the union element) @ref BT_UUID_TYPES */ - union { - uint16_t uuid16; - uint32_t uuid32; - uint8_t uuid128[MAX_UUID_SIZE]; - }; -}; - -/** - * UUID and Handle combination for services and characteristics - * - * Make sure this is 32 bit aligned! - */ -struct bt_uuid_handle_tuple { - void *p_priv; /**< Service private reference handle. */ - uint16_t handle; /** Service or characteristic handle. */ -}; - -/** - * GATT service types, primary versus secondary/included one. - */ -enum BLE_GATT_SVC_TYPES { - BLE_GATT_SVC_PRIMARY = 0, /**< primary service */ - BLE_GATT_SVC_INCLUDED /**< include service (must be referenced by a primary) */ -}; - -/** - * Characteristic properties. - */ -enum BLE_GATT_CHAR_PROPS { - BLE_GATT_CHAR_PROP_BIT_NONE = 0, - BLE_GATT_CHAR_PROP_BIT_BROADCAST = 0x01, - BLE_GATT_CHAR_PROP_BIT_READ = 0x02, - BLE_GATT_CHAR_PROP_BIT_WRITE_NR = 0x04, - BLE_GATT_CHAR_PROP_BIT_WRITE = 0x08, - BLE_GATT_CHAR_PROP_BIT_NOTIFY = 0x10, - BLE_GATT_CHAR_PROP_BIT_INDICATE = 0x20, - BLE_GATT_CHAR_PROP_BIT_AUTH = 0x40, - BLE_GATT_CHAR_PROP_BIT_EXTEND = 0x80/**< if set the extend property @ref BLE_GATT_CHAR_EXT_PROPS is present! */ -}; - -/** - * Extended characteristic properties. - */ -enum BLE_GATT_CHAR_EXT_PROPS { - BLE_GATT_CHAR_EXT_PROP_BIT_NONE = 0, - BLE_GATT_CHAR_EXT_PROP_RELIABLE_WR = 0x0001, /**< Reliable write procedure is supported */ - BLE_GATT_CHAR_EXT_PROP_WR_AUX = 0x0002, /**< User Descriptor Writes are permitted */ -}; - -struct ble_gatt_char_properties { - uint8_t props; /**< properties, @ref BLE_GATT_CHAR_PROPS */ - uint16_t ext_props; /**< extended properties, @ref BLE_GATT_CHAR_EXT_PROPS, valid if BLE_GATT_CHAR_PROP_BIT_EXTEND set */ -}; - -/** - * Format of the value of a characteristic, enumeration type. - */ -enum BLE_GATT_FORMATS { - BLE_GATT_FORMAT_RES, /* rfu */ - BLE_GATT_FORMAT_BOOL, /* 0x01 boolean */ - BLE_GATT_FORMAT_2BITS, /* 0x02 2 bit */ - BLE_GATT_FORMAT_NIBBLE, /* 0x03 nibble */ - BLE_GATT_FORMAT_UINT8, /* 0x04 uint8 */ - BLE_GATT_FORMAT_UINT12, /* 0x05 uint12 */ - BLE_GATT_FORMAT_UINT16, /* 0x06 uint16 */ - BLE_GATT_FORMAT_UINT24, /* 0x07 uint24 */ - BLE_GATT_FORMAT_UINT32, /* 0x08 uint32 */ - BLE_GATT_FORMAT_UINT48, /* 0x09 uint48 */ - BLE_GATT_FORMAT_UINT64, /* 0x0a uint64 */ - BLE_GATT_FORMAT_UINT128,/* 0x0B uint128 */ - BLE_GATT_FORMAT_SINT8, /* 0x0C signed 8 bit integer */ - BLE_GATT_FORMAT_SINT12, /* 0x0D signed 12 bit integer */ - BLE_GATT_FORMAT_SINT16, /* 0x0E signed 16 bit integer */ - BLE_GATT_FORMAT_SINT24, /* 0x0F signed 24 bit integer */ - BLE_GATT_FORMAT_SINT32, /* 0x10 signed 32 bit integer */ - BLE_GATT_FORMAT_SINT48, /* 0x11 signed 48 bit integer */ - BLE_GATT_FORMAT_SINT64, /* 0x12 signed 64 bit integer */ - BLE_GATT_FORMAT_SINT128,/* 0x13 signed 128 bit integer */ - BLE_GATT_FORMAT_FLOAT32,/* 0x14 float 32 */ - BLE_GATT_FORMAT_FLOAT64,/* 0x15 float 64 */ - BLE_GATT_FORMAT_SFLOAT, /* 0x16 IEEE-11073 16 bit SFLOAT */ - BLE_GATT_FORMAT_FLOAT, /* 0x17 IEEE-11073 32 bit SFLOAT */ - BLE_GATT_FORMAT_DUINT16,/* 0x18 IEEE-20601 format */ - BLE_GATT_FORMAT_UTF8S, /* 0x19 UTF-8 string */ - BLE_GATT_FORMAT_UTF16S, /* 0x1a UTF-16 string */ - BLE_GATT_FORMAT_STRUCT, /* 0x1b Opaque structure */ - BLE_GATT_FORMAT_MAX /* 0x1c or above reserved */ -}; - -/** - * GATT characteristic user description. - */ -struct ble_gatt_char_user_desc { - uint8_t *buffer; /**< Pointer to a UTF-8 string. */ - uint8_t len; /**< The size in bytes of the user description. */ -}; - -/** - * GATT characteristic presentation format description. - */ -struct ble_gatt_pf_desc { - uint16_t unit; /**< as UUIUD defined by SIG */ - uint16_t descr; /**< as UUID as defined by SIG */ - uint8_t format; /**< @ref BLE_GATT_FORMATS */ - int8_t exp; /**< see Unit from Bluetooth Assigned Numbers, https://developer.bluetooth.org/gatt/units/Pages/default.aspx */ - uint8_t name_spc; /**< name space of the description */ -} ; - -/** - * GATT indication types. - */ -enum BLE_GATT_IND_TYPES { - BLE_GATT_IND_TYPE_NONE = 0, - BLE_GATT_IND_TYPE_NOTIFICATION, - BLE_GATT_IND_TYPES_INDICATION, -}; - -/** - * GATT Write operation types - * - * (BT spec Vol 3, Part G, chapter. 4.9) - * @note long char write, Prepare & Exe request are handled internally to the controller stack - */ -enum BLE_GATT_WR_OP_TYPES { - BLE_GATT_WR_OP_NOP = 0, /**< normally not used except to cancel BLE_GATT_WR_OP_REQ long char write procedure */ - BLE_GATT_WR_OP_CMD, /**< Write Command, (no response) */ - BLE_GATT_WR_OP_REQ, /**< Write Request, Write response is received , if length is longer then ATT MTU, Prepare write procedure */ - BLE_GATT_WR_OP_SIGNED_CMD, /**< Signed Write Command */ -}; - -/** @} */ - -#endif diff --git a/system/libarc32_arduino101/framework/include/services/ble/ble_service_gattc_api.h b/system/libarc32_arduino101/framework/include/services/ble/ble_service_gattc_api.h deleted file mode 100644 index d7b42df9..00000000 --- a/system/libarc32_arduino101/framework/include/services/ble/ble_service_gattc_api.h +++ /dev/null @@ -1,372 +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. - */ - -#ifndef __BLE_SERVICE_GATTC_H__ -#define __BLE_SERVICE_GATTC_H__ - -#include "ble_service.h" -#include "ble_service_gap_api.h" -#include "ble_service_gatt.h" - -/** - * @defgroup ble_core_service_gattc BLE Core Service GATTC - * @ingroup ble_core_service - * - * BLE Core Service GATTC APIs used to implement GATT Clients. - * - * This is typically only used to add new client services to BLE service. - * - * It provides the following services: - * - Discover remote \b primary services or a specific service - * - Discover remote characteristics - * - Discover remote descriptors - * - read/write remote characteristics - * - Getting notified on characteristic changes - * - * @{ - */ - -/** - * Generic GATTC response message. - */ -struct ble_gattc_rsp { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; - uint16_t conn_handle; /**< GAP connection handle */ -}; - -/** - * Generic GATTC error event. - */ -struct ble_gattc_err_rsp_evt { - uint16_t err_handle; /**< handle of char attribute causing the failure */ -}; - -/** - * Handle range for a service operation. - */ -struct ble_gattc_handle_range { - uint16_t start_handle; - uint16_t end_handle; -}; - -typedef struct { - struct ble_gattc_handle_range handle_range; /**< range of characteristic handles within a service */ - struct bt_uuid uuid; /**< service uuid */ -} ble_gattc_svc_t; - -/** - * Primary Service discovery Indication message @ref MSG_ID_BLE_GATTC_DISC_PRIM_SVC_EVT. - */ -typedef struct { - uint16_t svc_count; /**< number of service included into this indication */ - ble_gattc_svc_t service_found[];/**< array on fouTnd services */ -} ble_gattc_primary_svc_disc_evt_t; - -/** - * Included service. - */ -typedef struct { - uint16_t incl_handle; /**< handle of included service */ - ble_gattc_svc_t svc; /**< included service */ -} ble_gattc_incl_svc_t; - -/** - * Discovered included services @ref MSG_ID_BLE_GATTC_DISC_INCL_SVC_EVT. - */ -typedef struct { - uint16_t incl_count; /**< Number of included services */ - ble_gattc_incl_svc_t included[]; /**< Array on found services */ -} ble_gattc_incl_svc_disc_evt_t; - -typedef struct { - struct ble_gatt_char_properties char_properties; /**< characteristic properties */ - uint16_t decl_handle; /**< Characteristic declaration handle */ - uint16_t value_handle; /**< Char's value handle */ - struct bt_uuid uuid; /**< Characteristic's UUID */ -} ble_gattc_characteristic_t; - -/** - * Discovered characteristics indication @ref MSG_ID_BLE_GATTC_DISC_CHAR_EVT. - */ -typedef struct { - uint16_t char_count; /**< number of characteristics in this message */ - ble_gattc_characteristic_t chars[]; /**< characteristics data as per char_count */ -} ble_gattc_char_disc_evt_t; - -/** - * GATTC descriptor. - */ -typedef struct { - uint16_t handle; /**< descriptor handle */ - struct bt_uuid uuid; /**< uuid of the descriptor */ -} ble_gattc_descriptor_t; - -/** - * Descriptor discover indication. - */ -typedef struct { - uint16_t desc_count; /**< number of descriptors in this message */ - ble_gattc_descriptor_t descs[]; /**< found descriptors */ -} ble_gattc_desc_disc_evt_t; - -enum BLE_GATTC_RD_CHAR_TYPES { - BLE_GATTC_RD_CHAR_BY_UUID = 0, /**< Read characteristic by UUID */ - BLE_GATTC_RD_CHAR, /**< Read (Long) characteristic or (Long) descriptor. Maybe called multiple times in case of long */ - BLE_GATTC_RD_CHAR_MULTIPLE /**< Read multiple characteristic attributes */ -}; - -/** - * Characteristic read by using UUID. - */ -typedef struct { - struct ble_gattc_handle_range handle_range; /**< characteristic or descriptor handle range */ - struct bt_uuid *p_uuid; /**< uuid of characteristic to read */ -} ble_gattc_rd_char_by_uuid_t; - -/** - * Characteristic or descriptor read. - * - * Maybe used for long too. - */ -typedef struct { - uint16_t handle; /**< attribute handle for reading */ - uint16_t offset; /**< offset into attribute data to read */ -} ble_gattc_rd_char_t; - -/** - * Read multiple characteristics values. - */ -typedef struct { - uint16_t handle_count; /**< number of handles in this structure */ - uint16_t handle[]; /**< handles of attributes to read from */ -} ble_gattc_rd_multi_char_t; - -typedef struct { - union { - ble_gattc_rd_char_by_uuid_t char_by_uuid; - ble_gattc_rd_char_t char_desc; /**< (Long) characteristic or descriptor to read */ - ble_gattc_rd_multi_char_t multi_char; - /**< read multiple characteristics */ - }; -} ble_gattc_rd_characteristic_t; - -typedef struct { - uint16_t char_handle; /**< handle of characteristic */ - uint16_t len; /**< if len is bigger then ATT MTU size, the controller fragment buffer itself */ - uint8_t *p_value; /**< characteristic value to write */ - uint8_t wr_type; /**< type of write operation @ref BLE_GATT_WR_OP_TYPES */ -} ble_gattc_wr_characteristic_t; - -/** - * Read characteristic response indication (@ref MSG_ID_BLE_GATTC_RD_EVT). - */ -typedef struct { - uint16_t handle; /**< handle of characteristic attribute read */ - uint16_t offset; /**< offset of data returned */ - uint16_t len; /**< length of data returned */ - uint8_t data[]; /**< characteristic attribute data */ -} ble_gattc_rd_char_evt_t; - -/** - * Characteristic write response indication @ref MSG_ID_BLE_GATTC_WR_EVT. - */ -typedef struct { - uint16_t char_handle; - uint16_t len; -} ble_gattc_wr_char_evt_t; - -/** - * Handle value indication or notification indication/event (@ref MSG_ID_BLE_GATTC_HDL_NOTIF_EVT). - */ -typedef struct { - uint16_t handle; /**< handle of characteristic being notified/indicated */ - uint16_t len; /**< length of value included into this indication */ - uint8_t type; /**< notification versus indication, @ref BLE_GATT_IND_TYPES */ - uint8_t data[]; /**< value data received */ -} ble_gattc_value_evt_t; - -/** - * GATT timeout reason. - */ -typedef struct { - uint16_t reason; /**< GATT timeout reason */ -} ble_gattc_to_evt_t; - -/** - * GATTC indication or response message structure applicable to most indications/events/responses. - */ -struct ble_gattc_evt_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; - uint16_t conn_handle; - union { - struct ble_gattc_err_rsp_evt err_rsp; /**< returned only if status != BLE_GATT_STATUS_SUCCESS */ - ble_gattc_primary_svc_disc_evt_t prim_svc_disc; - /**< primary service discovery indication event */ - ble_gattc_incl_svc_disc_evt_t incl_svc_disc; /**< included services discovered */ - ble_gattc_char_disc_evt_t char_disc; /**< characteristic discover event/indication */ - ble_gattc_desc_disc_evt_t desc_disc; /**< discovered descriptors indication/event */ - ble_gattc_rd_char_evt_t char_rd; /**< read characteristic indication/event */ - ble_gattc_wr_char_evt_t char_wr; /**< characteristic write indication event */ - ble_gattc_value_evt_t val_ind; /**< value indication or notification */ - ble_gattc_to_evt_t timeout_ind; /**< gattc timeout protocol error */ - }; /**< in case for responses, union is not used! */ -}; - -/** - * Discover primary service. - * - * @param p_svc_handle service handle - * @param conn_handle connection to use - * @param p_svc_uuid points to service UUID. if NULL, all services found are returned - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTC_DISCOVER_PRIMARY_SERVICE_RSP @ref ble_gattc_rsp - * @return EVT: MSG_ID_BLE_GATTC_DISC_PRIM_SVC_EVT @ref ble_gattc_primary_svc_disc_evt_t - */ -int ble_gattc_discover_primary_service(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const struct bt_uuid * p_svc_uuid, - void *p_priv); - -/** - * Discover included services on a previously discovered primary service. - * - * @param p_svc_handle service handle - * @param conn_handle connection to use - * @param p_handle_range handle range previously returned by @ref ble_gattc_primary_svc_disc_evt_t - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTC_DISCOVER_INCLUDED_SERVICES_RSP @ref ble_gattc_rsp - */ -int ble_gattc_discover_included_service(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const struct ble_gattc_handle_range * - p_handle_range, void *p_priv); - -/** - * Discover characteristics on a service. - * - * May be called several times if not all characteristics have been discovered. - * In this case a new handle range needs to be provided. - * - * @param p_svc_handle service handle - * @param conn_handle connection to use - * @param p_handle_range handle range - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTC_DISCOVER_CHAR_RSP @ref ble_gattc_rsp - * @ref MSG_ID_BLE_GATTC_DISC_CHAR_EVT @ref ble_gattc_char_disc_evt_t - */ -int ble_gattc_discover_characteristic(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const struct ble_gattc_handle_range * p_handle_range, - void *p_priv); - -/** - * Discover characteristics on a service. - * - * May be called several times if not all characteristics have been discovered. - * In this case a new handle range needs to be provided. - * - * @param p_svc_handle service handle - * @param conn_handle connection to use - * @param p_handle_range handle range - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTC_DISCOVER_DESCRIPTOR_RSP @ref ble_gattc_rsp - * @ref MSG_ID_BLE_GATTC_DISC_DESCR_EVT @ref ble_gattc_desc_disc_evt_t - */ -int ble_gattc_discover_descriptor(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const struct ble_gattc_handle_range * - p_handle_range, void *p_priv); - -/** - * Read characteristic on remote server. - * - * @param p_svc_handle service handle - * @param conn_handle connection to use - * @param type type of read to execute @ref BLE_GATTC_RD_CHAR_TYPES - * @param p_rd_char_param read type specific characteristic read parameter - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTC_RD_CHARS_RSP @ref ble_gattc_rsp - * @return EVT: MSG_ID_BLE_GATTC_RD_EVT @ref ble_gattc_rd_char_evt_t - */ -int ble_gattc_read_characteristic(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - uint8_t type, - const ble_gattc_rd_characteristic_t * p_rd_char_param, - void *p_priv); - -/** - * Write characteristic on server. - * - * @param p_svc_handle service handle - * @param conn_handle connection to use - * @param p_wr_char_param write characteristic on remote service - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GATTC_WR_OP_RSP @ref ble_gattc_rsp - */ -int ble_gattc_write_char_op(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const ble_gattc_wr_characteristic_t * - p_wr_char_param, - void *p_priv); - - -/** - * Write characteristic on server. - * - * @param p_svc_handle service handle - * @param conn_handle connection to use - * @param val_handle handle to confirm and received by Handle Value Indication (@ref MSG_ID_BLE_GATTC_HDL_NOTIF_EVT) - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE, - * @return MSG: MSG_ID_BLE_GATTC_SEND_HANDLE_VALUE_RSP @ref ble_gattc_rsp - */ -int ble_gattc_send_confirm_handle_value(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - uint16_t val_handle, - void *p_priv); - -/** @} */ - -#endif diff --git a/system/libarc32_arduino101/framework/include/services/ble/ble_service_gatts_api.h b/system/libarc32_arduino101/framework/include/services/ble/ble_service_gatts_api.h deleted file mode 100644 index 76bc3149..00000000 --- a/system/libarc32_arduino101/framework/include/services/ble/ble_service_gatts_api.h +++ /dev/null @@ -1,559 +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. - */ - -#ifndef __BLE_SERVICE_GATTS_H__ -#define __BLE_SERVICE_GATTS_H__ - -#include "ble_service.h" -#include "ble_service_gap_api.h" -#include "ble_service_gatt.h" - -/** @defgroup ble_core_service_gatts BLE Core Service GATTS - * @ingroup ble_core_service - * - * BLE Core GATTS Service APIs to implement GATT Servers. - * - * This API should only be used by BLE service to implement additional BLE profiles/services. - * - * Those the GATT server APIs provide the following services: - * - Create an new (server) BLE service - * - Add characteristics to the service - * - Write local server characteristics - * - Receive data when updated by client - * - * @note If a service is based on a 128 bit UUID (vendor service), all the characteristic - * need to use the same 128 bit UUID base and only vary octets 12-13 of base UUID. - * - * @{ - */ - -/** - * BLE GATTS max attribute length. - * @note BLE controller dependent - */ -#define BLE_SVC_GATTS_FIX_ATTR_LEN_MAX 510 /**< Maximum length for fixed length Attribute Values. */ -#define BLE_SVC_GATTS_VAR_ATTR_LEN_MAX 512 /**< Maximum length for variable length Attribute Values. */ - -/* forward declaration for callback handlers */ -struct _ble_service_cb; -struct ble_gatts_add_svc_rsp; -struct ble_gatts_add_char_rsp; -struct ble_gatts_add_desc_rsp; -struct ble_gatts_notif_ind_rsp_msg; - -/** - * Generic GATTS response message. - */ -typedef struct { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; - uint16_t conn_handle; /**< GAP connection handle */ -} ble_gatts_rsp_t; - -/** - * Add Service callback handler. - */ -typedef int (* ble_gatts_add_svc_cback_t)(struct ble_gatts_add_svc_rsp * rsp, - struct _ble_service_cb * p_cb); - -/** - * Add service response message. - */ -struct ble_gatts_add_svc_rsp { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; /**< status of service creation */ - ble_gatts_add_svc_cback_t cback; /**< Callback function to execute on reception of this message */ - uint16_t svc_handle; /**< Handle of newly allocated service (only valid in case of success. */ -}; - -/** - * Include service response. - */ -typedef struct { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; /**< status of service creation */ - uint16_t svc_handle; /**< updated handle of included service (only valid in case of success */ -} ble_gatts_incl_svc_rsp_t; - -/** - * ATT attribute permission - */ -struct ble_gatts_permissions { - uint8_t rd; /**< Read permissions, @ref BLE_GAP_SEC_MODES */ - uint8_t wr; /**< Write permissions @ref BLE_GAP_SEC_MODES */ -}; - -/** - * GATT characteristic. - */ -struct ble_gatts_characteristic { - struct bt_uuid * p_uuid; /**< Pointer to the characteristic UUID. */ - struct ble_gatts_permissions perms; /**< Characteristic value attribute permissions */ - struct ble_gatt_char_properties props; /**< Characteristic Properties. @ref ble_gatt_char_properties */ - uint16_t max_len; /**< Maximum characteristic value length in bytes, see @ref BLE_SVC_GATTS_FIX_ATTR_LEN_MAX or @ref BLE_SVC_GATTS_VAR_ATTR_LEN_MAX. */ - uint16_t init_len; /**< Initial characteristic value length in bytes. */ - uint8_t * p_value; /**< Pointer to the characteristic initialization value */ - // optional descriptors - struct ble_gatt_char_user_desc * p_user_desc; /**< Optional user description of the characteristic, NULL if not required */ - struct ble_gatt_pf_desc *p_char_pf_desc; /**< Pointer to a presentation format structure or NULL if the descriptor is not required. */ -}; - -/** - * GATT generic descriptor. - */ -struct ble_gatts_descriptor { - struct bt_uuid * p_uuid; /**< Pointer to the descriptor UUID. */ - uint8_t * p_value; /**< Value of the descriptor */ - uint16_t length; /**< Length of the descriptor value */ - struct ble_gatts_permissions perms; /**< Descriptor attribute permissions */ -}; - -struct ble_gatts_char_handles { - uint16_t value_handle; /**< Handle to the characteristic value. */ - uint16_t cccd_handle; /**< Handle to the Client Characteristic Configuration Descriptor, or BLE_GATT_HANDLE_INVALID if not present. */ - uint16_t sccd_handle; /**< Handle to the Server Characteristic Configuration Descriptor, or BLE_GATT_HANDLE_INVALID if not present. */ -}; - -/** - * Add Service callback handler. - */ -typedef int (* ble_gatts_add_char_cback_t)(struct ble_gatts_add_char_rsp * rsp, - struct _ble_service_cb * p_cb); - -/** - * Add characteristic response message. - */ -struct ble_gatts_add_char_rsp { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; /**< Status of the operation. */ - ble_gatts_add_char_cback_t cback; /**< Callback function to call on reception of this message */ - struct ble_gatts_char_handles char_h; /**< Handles of the created characteristic */ -}; - -/** - * Add Service callback handler. - */ -typedef int (* ble_gatts_add_desc_cback_t)(struct ble_gatts_add_desc_rsp * rsp, - struct _ble_service_cb * p_cb); - -/** - * Add descriptor response message. - */ -struct ble_gatts_add_desc_rsp { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; /**< Status of the operation. */ - ble_gatts_add_desc_cback_t cback; /**< Callback function to call on reception of this message */ - uint16_t handle; /**< Handle of the created descriptor */ -}; - -/** - * Set attribute response message. - */ -struct ble_gatts_set_attr_rsp_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; - uint16_t value_handle; -}; - -/** - * Notification/Indication callback. - */ -typedef int (* ble_gatts_notif_ind_cback_t)(struct ble_gatts_notif_ind_rsp_msg * rsp, - struct _ble_service_cb * p_cb); - -/** - * Notification/Indication response message. - */ -struct ble_gatts_notif_ind_rsp_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; - uint16_t conn_handle; - ble_gatts_notif_ind_cback_t cback; /**< Callback function to call on reception of this message */ - uint16_t handle; /**< Characteristic value handle */ -}; - -/** - * Shortened attribute type definitions. - * See BT Spec r Vol 3, PART G, chapter 3 - */ -enum BLE_SVC_GATTS_ATTR_TYPES { - BLE_SVC_GATTS_ATTR_TYPE_NONE = 0, - BLE_SVC_GATTS_ATTR_TYPE_PRIMARY_SVC_DECL, - /**< primary service attribute declaration (chpt 3.1) */ - BLE_SVC_GATTS_ATTR_TYPE_SECONDARY_SVC_DECL, - /**< secondary service attribute declaration (chpt 3.1) */ - BLE_SVC_GATTS_ATTR_TYPE_INCLUDE_DECL, /**< include attribute declaration (3.2) */ - BLE_SVC_GATTS_ATTR_TYPE_CHAR_DECL, /**< characteristic declaration (3.3.1) */ - BLE_SVC_GATTS_ATTR_TYPE_CHAR_VALUE_DECL,/**< Characteristic value declaration */ - BLE_SVC_GATTS_ATTR_TYPE_DESC_DECL, /**< descriptor declaration */ -}; - -/** - * GATT server write ops. - */ -enum BLE_GATTS_WR_OPS { - BLE_GATTS_OP_NONE = 0, - BLE_GATTS_OP_WR, /**< 3.4.5.1 Write Request (Attribute), expects write response */ - BLE_GATTS_OP_WR_CMD, /**< 3.4.5.3 Write Command (Attribute) NO response sent */ - BLE_GATTS_OP_WR_CMD_SIGNED, /**< 3.4.5.4 Write Command Signed (Attribute), NO response sent */ - BLE_GATTS_OP_WR_PREP_REQ, /**< 3.4.6.1 Write Prepare Request, expects a prepare write request response */ - BLE_GATTS_OP_WR_EXE_REQ_CANCEL, /**< 3.4.6.3 Cancel Executed Write Request, cancel and clear queue (flags = 0) */ - BLE_GATTS_OP_WR_EXE_REQ_IMM /**< 3.4.6.3 Immediately Execute Write Request */ -}; - -/** - * Write authorization context data structure. - */ -typedef struct { - uint16_t attr_handle; /**< handle of attribute to write */ - uint16_t offset; - uint16_t len; - uint8_t op; /**< @ref BLE_GATTS_WR_OPS */ - uint8_t data[]; -} ble_gatt_wr_evt_t; - -/** - * Read authorization context data structure. - */ -typedef struct { - uint16_t attr_handle; /**< handle of attribute to been read */ - uint16_t offset; -} ble_gatt_rd_evt_t; - -/** - * Connection attribute data is missing @ref MSG_ID_BLE_GATTS_CONN_ATTRIB_MISSING_EVT. - */ -typedef struct { - uint16_t miss_type; /**< missing connection attribute type */ -} ble_gatts_conn_attrib_missing_evt_t; - -/** - * Handle Value Confirmation, @ref MSG_ID_BLE_GATTS_INDICATION_CONF_EVT in response an handle value indication. - */ -typedef struct { - uint16_t handle; /**< attribute handle of indication value sent */ -} ble_gatts_handle_value_conf_evt_t; - -/** - * Read attribute value rsp message. - */ -typedef struct { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; - uint16_t conn_handle; /**< GAP connection handle */ - uint16_t val_handle; /**< handle of attribute value */ - uint16_t len; /**< length of value returned */ - uint16_t offset; /**< offset in the value. the same as in the rd request! */ - uint8_t value[]; /**< value data of length \ref len */ -} ble_gatts_rd_attrib_val_rsp_t; - -/** - * Indication or notification. - */ -typedef struct { - uint16_t val_handle; /**< handle of attribute value */ - uint16_t len; /**< len of attribute data value to indicate */ - uint8_t *p_data; /**< data to indicate (maybe NULL if currently stored shall be used) */ - uint16_t offset; /**< optional offset into attribute value data */ -} ble_gatts_ind_params_t; - -/** - * Connection related attribute data parameters (stack specific). - */ -typedef struct { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; /**< result for request, if not success, the data afterwards may not be valid */ - uint16_t conn_handle; /**< connection handle of the retrieved connection attribute data */ - uint16_t len; /**< length of the following connection attribute data */ - uint8_t conn_attr_data[]; -} ble_gatts_rd_conn_attr_rsp_t; - -/** - * GATTS timeout @ref MSG_ID_BLE_GATTS_TO_EVT. - */ -typedef struct { - uint16_t reason; /**< reason for timeout */ -} ble_gatts_timeout_evt_t; - -/** - * BLE GATTS Indication Data structure. - */ -struct ble_gatts_evt_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_status_t status; /**< result for request, if not success, the data afterwards may not be valid */ - uint16_t conn_handle; - union { - ble_gatt_wr_evt_t wr; /**< write indication */ - ble_gatts_conn_attrib_missing_evt_t conn_attr; - /**< connection related attribute missing */ - ble_gatts_handle_value_conf_evt_t handle_val_conf; - /**< value confirmation (confirmation of an indication) */ - ble_gatts_timeout_evt_t timeout; /**< GATTS timeout occurred */ - }; -}; - -/** - * Create an new service, primary or include. - * - * @param p_svc_handle service handle - * @param p_uuid UUID of new service - * @param type primary versus included @ref BLE_GATT_SVC_TYPES - * @param cback Callback function to be called on reception of add service response - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_ADD_SERVICE_RSP @ref ble_gatts_add_svc_rsp - */ -int ble_gatts_add_service(svc_client_handle_t * p_svc_handle, - const struct bt_uuid * p_uuid, - uint8_t type, - ble_gatts_add_svc_cback_t cback, - void *p_priv); - -/** - * Include a (secondary) service into a primary service. - * - * @param p_svc_handle service handle - * @param svc_handle service to which to add the included service - * @param svc_handle_to_include the previously created includable service - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_ADD_INCL_SVC @ref ble_gatts_incl_svc_rsp_t - */ -int ble_gatts_add_included_svc(svc_client_handle_t * p_svc_handle, - uint16_t svc_handle, - uint16_t svc_handle_to_include, - void *p_priv); - -/** - * Add a characteristic to service. - * - * @note this may called with the same UUID. the returned handle will be different in this case to - * distinguish multiple instances of the same char - * - * @param p_svc_handle service handle - * @param svc_handle service to which to add the characteristic - * @param p_char meta data for characteristic - * @param cback Callback function called on reception of response message - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_ADD_CHARACTERISTIC @ref ble_gatts_add_char_rsp - */ -int ble_gatts_add_characteristic(svc_client_handle_t * p_svc_handle, - uint16_t svc_handle, - const struct ble_gatts_characteristic * p_char, - ble_gatts_add_char_cback_t cback, - void *p_priv); - -/** - * Add a descriptor to the last added characteristic. - * - * @note The descriptor is automatically added to the latest - * added characteristic - * - * @param p_svc_handle service handle - * @param p_desc description of the descriptor - * @param cback Callback function called on reception of response message - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_ADD_DESCRIPTOR @ref ble_gatts_add_desc_rsp - */ -int ble_gatts_add_descriptor(svc_client_handle_t * p_svc_handle, - const struct ble_gatts_descriptor * p_desc, - ble_gatts_add_desc_cback_t cback, - void * p_priv); - -/** - * Start BLE Service setup before. - * - * @param p_svc_handle service handle - * @param svc_handle service to start - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_START_SERVICE @ref ble_rsp - */ -int ble_gatts_start_service(svc_client_handle_t * p_svc_handle, - uint16_t svc_handle, - void *p_priv); - -/** - * Stop and remove service. - * - * @note Not yet supported - * - * @param p_svc_handle service handle - * @param svc_handle handle of characteristic to which to add the descriptor - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_REMOVE_SERVICE_RSP @ref ble_rsp - */ -int ble_gatts_remove_service(svc_client_handle_t * p_svc_handle, - uint16_t svc_handle, - void *p_priv); - -/** - * Send a service change indication. - * - * @note Not yet supported - * - * @param p_svc_handle service handle - * @param conn_handle handle of the connection affected by the service layout change - * @param start_handle start handle of changed attribute handle range - * @param end_handle end handle of changed attribute handle range - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_INDICATE_SERVICE_CHANGE @ref ble_gatts_rsp_t - */ -int ble_gatts_send_svc_changed(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - uint16_t start_handle, - uint16_t end_handle, - void *p_priv); - -/** - * Set an attribute value. - * - * @param p_svc_handle service handle - * @param value_handle handle of value to change - * @param len length of attribute value to write - * @param p_value attribute value data to write - * @param offset optional offset from which on to write the attribute value data - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_WR_ATTRIBUTE_VALUE ble_gatts_wr_attr_rsp_msg - */ -int ble_gatts_set_attribute_value(svc_client_handle_t * p_svc_handle, - uint16_t value_handle, - uint16_t len, - const uint8_t * p_value, - uint16_t offset, - void *p_priv); - -/** - * Get an attribute value. - * - * @param p_svc_handle service handle - * @param value_handle handle of the attribute value to retrieve - * @param len length of the attribute value to get - * @param offset optional offset from which on to get the attribute value - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_RD_ATTRIBUTE_VALUE @ref ble_gatts_rd_attrib_val_rsp_t - */ -int ble_gatts_get_attribute_value(svc_client_handle_t * p_svc_handle, - uint16_t value_handle, - uint16_t len, - uint16_t offset, - void *p_priv); - -/** - * Send notification. - * - * @param p_svc_handle service handle - * @param conn_handle handle of the connection affected by the service layout change - * @param p_ind_params length of attribute value to write - * @param cback callback function to be called on reception of reception of notif response - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_SEND_NOTIF_RSP @ref ble_gatts_notif_ind_rsp_msg - */ -int ble_gatts_send_notif(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const ble_gatts_ind_params_t * p_params, - ble_gatts_notif_ind_cback_t cback, - void *p_priv); - -/** - * Send indication. - * - * @param p_svc_handle service handle - * @param conn_handle handle of the connection affected by the service layout change - * @param p_ind_params length of attribute value to write - * @param cback callback function to be called on reception of reception of ind response - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_SEND_NOTIF_RSP @ref ble_gatts_notif_ind_rsp_msg - */ -int ble_gatts_send_ind(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const ble_gatts_ind_params_t * p_params, - ble_gatts_notif_ind_cback_t cback, - void *p_priv); - -/** - * Write stack specific data of a previously bonded connection. - * - * @note this data is typically stored in NVRAM in relation ship to the bonded device! - * (e.g. CCD) - * - * @param p_svc_handle service handle - * @param conn_handle handle of the connection - * @param p_data data blob specific to stack to write - * @param len length of above byte stream (little endian) - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_WR_CONN_ATTRIBUTES @ref ble_gatts_rsp_t - */ -int ble_gatts_write_conn_attributes(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const uint8_t * p_data, - uint16_t len, - void *p_priv); - -/** - * Read stack specific data of the bonded connection. - * - * @note this data is typically stored in NVRAM in relation ship to the bonded device! - * - * @param p_svc_handle service handle - * @param conn_handle handle of the connection - * @param p_priv pointer to private data - * - * @return @ref OS_ERR_TYPE - * @return MSG: MSG_ID_BLE_GATTS_RD_CONN_ATTRIBUTES @ref ble_gatts_rd_conn_attr_rsp_t - */ -int ble_gatts_read_conn_attributes(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - void *p_priv); - -/** @} */ - -#endif diff --git a/system/libarc32_arduino101/framework/include/services/services_ids.h b/system/libarc32_arduino101/framework/include/services/services_ids.h index ccf2260c..c153a468 100644 --- a/system/libarc32_arduino101/framework/include/services/services_ids.h +++ b/system/libarc32_arduino101/framework/include/services/services_ids.h @@ -57,6 +57,7 @@ enum { CFW_LAST_SERVICE_ID = 17 }; +#define MSG_ID_BLE_SERVICE_BASE (BLE_SERVICE_ID << 10) #define BLE_SERVICE_MSG_BASE (BLE_SERVICE_ID << 10) #define BLE_SERVICE_GAP_MSG_BASE (BLE_CORE_SERVICE_ID << 10) #define MSG_ID_GPIO_BASE (SOC_GPIO_SERVICE_ID << 10) diff --git a/system/libarc32_arduino101/framework/include/util/misc.h b/system/libarc32_arduino101/framework/include/util/misc.h new file mode 100644 index 00000000..ea2cdff4 --- /dev/null +++ b/system/libarc32_arduino101/framework/include/util/misc.h @@ -0,0 +1,110 @@ +/* + * 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. + */ + +#ifndef __MISC_H__ +#define __MISC_H__ + +/* required for offsetof */ +#include + +//#include "util/compiler.h" + +/** Generate a build time error if a condition is met + * + * @param condition The condition to be tested + * + * @note This function should be used inside a code block + */ +#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2 * !!(condition)])) + +/** Generate a build time error if a condition is met or return 0 + * + * @param condition The condition to be tested + * + * @return 0 + */ +#define BUILD_BUG_ON_ZERO(e) (sizeof(char[1 - 2 * !!(e)]) - 1) + +/** + * Similar to BUILD_BUG_ON_ZERO + */ +#define STATIC_ASSERT(EXPR) typedef char __unused static_assert_failed[(EXPR) ? \ + 1 : -1] + +/** Generate a build time error if the parameter is not an array otherwise return 0 + * + * @param A The array to be checked. + * + * @return 0 + */ +#define __must_be_array(A) \ + BUILD_BUG_ON_ZERO (HAVE_SAME_TYPE(A, &A[0])) + +/** + * Check if the integer provided is a power of two. + * + * @param A Number to be tested. + * + * @return true if value is power of two else false. + */ +#define IS_POWER_OF_TWO(A) ((A) != 0 && (((A)-1) & (A)) == 0) + +/** + * Given a pointer on a member, return the pointer on the containing struct + * + * @param ptr Pointer to the member + * @param type Containing struct + * @param member Member name + * + * @return Casted pointer to the struct + * + * @note Use if possible CONTAINER_OF() defined in Zephyr include + */ +#define container_of(ptr, type, member) ({ \ + (type *)((char *)(ptr) - \ + offsetof(type, member)); }) + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +/** + * Concatenate 4 ASCII characters into an integer + * + * @param key_1 first ASCII char + * @param key_2 second ASCII char + * @param key_3 third ASCII char + * @param key_4 fourth ASCII char + * + * @return the integer representation of the four-digit string + */ +#define GEN_KEY(key_1, key_2, key_3, key_4) \ + (key_1 << 24) | (key_2 << 16) | (key_3 << 8) | key_4 + +#endif /* __MISC_H__ */ diff --git a/system/libarc32_arduino101/framework/src/cfw/service_api.c b/system/libarc32_arduino101/framework/src/cfw/service_api.c index 936fa3f9..28b5bfe5 100644 --- a/system/libarc32_arduino101/framework/src/cfw/service_api.c +++ b/system/libarc32_arduino101/framework/src/cfw/service_api.c @@ -122,54 +122,6 @@ struct cfw_message * cfw_alloc_internal_msg(int msg_id, int size, void * priv) { return evt; } -void default_msg_handler(struct cfw_message * msg, void *data) { - pr_error(LOG_MODULE_CFW, "Bug: %s should not be called data: %p", __func__, data); - cfw_dump_message(msg); -} - -void client_handle_message(struct cfw_message * msg, void *param) { - _cfw_handle_t * h = (_cfw_handle_t*)param; - switch(CFW_MESSAGE_ID(msg)) { - case MSG_ID_CFW_OPEN_SERVICE: - { - cfw_open_conn_rsp_msg_t * cnf = (cfw_open_conn_rsp_msg_t *) msg; - /** Make client handle point to server handle */ - ((svc_client_handle_t*)cnf->client_handle)->server_handle = cnf->svc_server_handle; - /** Initialize service port. */ - ((svc_client_handle_t*)cnf->client_handle)->port = cnf->port; -#ifndef CONFIG_INFRA_IS_MASTER - /* Set local port and cpu id */ - if (get_cpu_id() != cnf->cpu_id) { - port_set_port_id(cnf->port); - port_set_cpu_id(cnf->port, cnf->cpu_id); - } -#endif - break; - } - case MSG_ID_CFW_CLOSE_SERVICE: - { - /* Free client-side conn */ - bfree(msg->conn); - break; - } - default: - //Nothing to do - break; - } - h->handle_msg(msg, h->data); -} - -cfw_handle_t cfw_init(void * queue, handle_msg_cb_t cb, void *cb_data) { - _cfw_handle_t * handle = (_cfw_handle_t*)balloc(sizeof(*handle), NULL); - handle->handle_msg = cb; - handle->data = cb_data; - - handle->client_port_id = port_alloc(queue); - - cfw_port_set_handler(handle->client_port_id, client_handle_message, handle); - - return (cfw_handle_t) handle; -} int _cfw_send_message(struct cfw_message * message) { diff --git a/system/libarc32_arduino101/framework/src/cfw_platform.c b/system/libarc32_arduino101/framework/src/cfw_platform.c index b2da0288..5daa0951 100644 --- a/system/libarc32_arduino101/framework/src/cfw_platform.c +++ b/system/libarc32_arduino101/framework/src/cfw_platform.c @@ -42,10 +42,11 @@ #include "cfw/cfw_messages.h" -#include "nordic_interface.h" +#include "nble_driver.h" /* FIXME: Service manager API */ extern void _cfw_init(void *); +extern void ble_cfw_service_init(int service_id, T_QUEUE queue); extern void *services; @@ -81,21 +82,6 @@ static void free_message_ipc(struct message *msg) { extern "C" { #endif - -void cfw_platform_nordic_init(void) -{ - /* 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 */ - - /* Reset the nordic to force sync - Warning: not working everytime */ - nordic_interface_init(service_mgr_queue); - uart_ipc_init(0); - uart_ipc_set_channel(uart_ipc_channel_open(SYNC_CHANNEL, uart_ipc_message_cback)); -} - static void cfw_platform_mbx_int_enable(void) { /* Set up mailbox interrupt handler */ @@ -116,8 +102,6 @@ void cfw_platform_init(void) set_cpu_id(CPU_ID_ARC); set_cpu_message_sender(ipc_remote_cpu, send_message_ipc); set_cpu_free_handler(ipc_remote_cpu, free_message_ipc); - set_cpu_message_sender(CPU_ID_BLE, send_message_ipc_uart); - set_cpu_free_handler(CPU_ID_BLE, free_message_ipc_uart); service_mgr_queue = queue_create(IPC_QUEUE_DEPTH, NULL); @@ -131,6 +115,7 @@ void cfw_platform_init(void) shared_data->services, shared_data->service_mgr_port_id); #else _cfw_init(service_mgr_queue); + ble_cfw_service_init(BLE_SERVICE_ID, service_mgr_queue); /* Initialized shared structure. */ shared_data->ports = port_get_port_table(); diff --git a/system/libarc32_arduino101/framework/src/infra/log.c b/system/libarc32_arduino101/framework/src/infra/log.c index c0d0ab7a..7e21decf 100644 --- a/system/libarc32_arduino101/framework/src/infra/log.c +++ b/system/libarc32_arduino101/framework/src/infra/log.c @@ -62,10 +62,12 @@ void log_init() uint8_t i; for (i = 0; i < LOG_MODULE_NUM; i++) { - global_infos.modules_filter[i].status = 1; - global_infos.modules_filter[i].log_level = LOG_LEVEL_INFO; + global_infos.modules_filter[i].status = true; + global_infos.modules_filter[i].log_level = LOG_LEVEL_DEBUG; } - global_infos.log_level_limit = LOG_LEVEL_INFO; + global_infos.log_level_limit = LOG_LEVEL_DEBUG; + + global_infos.modules_filter[LOG_MODULE_MAIN].log_level = LOG_LEVEL_INFO; log_impl_init(); } diff --git a/system/libarc32_arduino101/framework/src/infra/log_impl_printk.c b/system/libarc32_arduino101/framework/src/infra/log_impl_printk.c index ed8f1e99..958b7521 100644 --- a/system/libarc32_arduino101/framework/src/infra/log_impl_printk.c +++ b/system/libarc32_arduino101/framework/src/infra/log_impl_printk.c @@ -32,13 +32,14 @@ #include "log_impl.h" #include "infra/log_backend.h" -extern int printk(const char * format, ...); +//extern int printk(const char * format, ...); +extern void printk(const char *fmt, va_list args); uint32_t log_write_msg(uint8_t level, uint8_t module, const char *format, va_list args) { // TODO - implement printk -// printk(format, args); + printk(format, args); return 0; } diff --git a/system/libarc32_arduino101/framework/src/nordic_interface.c b/system/libarc32_arduino101/framework/src/nordic_interface.c deleted file mode 100644 index daee0f12..00000000 --- a/system/libarc32_arduino101/framework/src/nordic_interface.c +++ /dev/null @@ -1,192 +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 -#include "os/os.h" -#include "cfw/cfw.h" -#include "cfw/cfw_debug.h" -#include "cfw/cfw_internal.h" -#include "cfw/cfw_messages.h" -#include "infra/ipc_uart.h" -#include "infra/ipc_requests.h" -#include "infra/log.h" -#include "infra/message.h" -#include "infra/time.h" -#include "drivers/soc_gpio.h" -#include "platform.h" - -#include "portable.h" - -/* Macro definition for reset pin */ -#define BLE_SW_CLK_PIN 27 -#define BLE_SWDIO_PIN 6 -#define RESET_PIN BLE_SWDIO_PIN -#define ATP_BLE_INT 5 - -static T_QUEUE service_mgr_queue; - -/* When we set val to 1 it will wake up the Nordic, setting it to 0 - * will set it back to sleep. */ -static int nordic_wake_assert(bool val) -{ - uint8_t ret = soc_gpio_write(SOC_GPIO_32_ID, ATP_BLE_INT, val); - if (ret != DRV_RC_OK) - pr_error(LOG_MODULE_IPC, "Error setting ATP_BLE_INT %d", val); - return ret; -} - -void nordic_wake_deassert(void* ignored) -{ - nordic_wake_assert(0); -} - -int send_message_ipc_uart(struct cfw_message * message) { - int ret = uart_ipc_send_message(uart_ipc_get_channel(), - CFW_MESSAGE_LEN(message), message); - message_free((struct message *)message); - return ret; -} - -void free_message_ipc_uart(void * ptr) { - bfree(ptr); -} - -/** - * IPC CFW message format is the following (little endian): - * ------------------------------------- - * | len: 2 bytes | chan 1 byte: sender cpu id: 1 byte | - * ------------------------------------- - * | REQUEST_ID | payload | - * ------------------------------------- - * - * For TYPE_MESSAGE request, the payload is the message copy. - * For TYPE_FREE is not valid (this ipc is not shared mem based) - */ -void uart_ipc_message_cback(uint8_t cpu_id, int channel, int len, void * p_data) -{ - struct cfw_message * msg; - unsigned int request = *(uint32_t*)p_data; - - switch (request) { - case IPC_MSG_TYPE_MESSAGE: - { - OS_ERR_TYPE error = E_OS_OK; - int size = len - sizeof(uint32_t); - msg = (struct cfw_message *)message_alloc(size, &error); - if (error != E_OS_OK) - pr_error(LOG_MODULE_IPC, "NO MEM: error: %d size: %d", error, size); - else { - memcpy(msg, (uint8_t *)p_data + sizeof(uint32_t), size); - handle_ipc_sync_request(cpu_id, request, 0, 0, msg); - } - break; - } - case IPC_REQUEST_ALLOC_PORT: - { - unsigned int ret; - unsigned int error; - uint16_t port_id = port_alloc(NULL); - port_set_cpu_id(port_id, cpu_id); - ret = port_id; - pr_info(LOG_MODULE_IPC, "%s return port_id %d", __func__, ret); - error = uart_ipc_send_sync_resp(channel, request, ret, 0, NULL); - if (error) - pr_error(LOG_MODULE_IPC, "%s returned error from ipc uart sync resp %d", __func__, error); - break; - } - default: - { - unsigned int error; - int32_t * p = ((int32_t *) p_data) + 1; - int32_t param0 = *p++; - int32_t param1 = *p++; - void * ptr = (void *) *p; - pr_info(LOG_MODULE_IPC, "%s request %xh, param1 %d, param2 %d", __func__, request, param0, param1); - handle_ipc_sync_request(cpu_id, request, param0, param1, ptr); - error = uart_ipc_send_sync_resp(channel, request, 0, 0, NULL); - if (error) - pr_error(LOG_MODULE_IPC, "%s returned error from ipc uart sync resp %d", __func__, error); - break; - } - } - bfree(p_data); - - /* Dequeue and process any new messages received */ - while(queue_process_message(service_mgr_queue) != 0); -} - -/* Nordic reset is achieved by asserting low the SWDIO pin. - * However, the Nordic chip can be in SWD debug mode, and NRF_POWER->RESET = 0 due to, - * other constraints: therefore, this reset might not work everytime, especially after - * flashing or debugging. - */ -static int nordic_reset(void) -{ - /* RESET_PIN depends on the board and the local configuration: check top of file */ - uint32_t delay_until; - gpio_cfg_data_t pin_cfg = { .gpio_type = GPIO_OUTPUT }; - - soc_gpio_set_config(SOC_GPIO_32_ID, RESET_PIN, &pin_cfg); - - /* Reset hold time is 0.2us (normal) or 100us (SWD debug) */ - soc_gpio_write(SOC_GPIO_32_ID, RESET_PIN, 0); - /* Wait for ~1ms */ - delay_until = get_uptime_32k() + 32768; - while (get_uptime_32k() < delay_until); - /* De-assert the reset */ - soc_gpio_write(SOC_GPIO_32_ID, RESET_PIN, 1); - - /* Set back GPIO to input to avoid interfering with external debugger */ - pin_cfg.gpio_type = GPIO_INPUT; - soc_gpio_set_config(SOC_GPIO_32_ID, RESET_PIN, &pin_cfg); - - return 0; -} - -int nordic_interface_init(T_QUEUE queue) -{ - uint8_t ret; - gpio_cfg_data_t config; - - service_mgr_queue = queue; - - config.gpio_type = GPIO_OUTPUT; - ret = soc_gpio_set_config(SOC_GPIO_32_ID, ATP_BLE_INT, &config); - if (ret != DRV_RC_OK) - return -1; - ret = nordic_wake_assert(1); - if (ret != DRV_RC_OK) - return -1; - ret = nordic_reset(); - if (ret != DRV_RC_OK) - return -1; - - return 0; -} diff --git a/system/libarc32_arduino101/framework/src/os/os.c b/system/libarc32_arduino101/framework/src/os/os.c index 63aa31f6..ed84eb8b 100644 --- a/system/libarc32_arduino101/framework/src/os/os.c +++ b/system/libarc32_arduino101/framework/src/os/os.c @@ -34,6 +34,7 @@ /************************* MEMORY *************************/ #ifdef TRACK_ALLOCS +#include "infra/log.h" int alloc_count = 0; #endif @@ -45,6 +46,7 @@ void * cfw_alloc(int size, OS_ERR_TYPE * err) { (*(int*) ptr) = size; #ifdef TRACK_ALLOCS alloc_count++; + pr_info(0, "alloc_count - %d", alloc_count); #endif interrupt_unlock(flags); return ptr; @@ -56,6 +58,7 @@ 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); diff --git a/system/libarc32_arduino101/framework/src/os/panic.c b/system/libarc32_arduino101/framework/src/os/panic.c new file mode 100644 index 00000000..9fe88ef9 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/os/panic.c @@ -0,0 +1,16 @@ + +#include "os/os.h" + +extern void _do_fault(); +void panic(int x) +{ + _do_fault(); +} + + +void __assert_fail() +{ + panic(-10); +} + + diff --git a/system/libarc32_arduino101/framework/src/services/ble/ble_protocol.h b/system/libarc32_arduino101/framework/src/services/ble/ble_protocol.h deleted file mode 100644 index 460e7458..00000000 --- a/system/libarc32_arduino101/framework/src/services/ble/ble_protocol.h +++ /dev/null @@ -1,233 +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. - */ - -#ifndef __BLE_PROTOCOL_H__ -#define __BLE_PROTOCOL_H__ - -/** - * @defgroup ble_protocol BLE protocol definitions - * - * BT Spec definitions. - * @ingroup ble_service - * @{ - * - * Bluetooth SIG defined macros and enum extracted from Bluetooth Spec 4.2 - */ -#define BLE_MAX_DEVICE_NAME 20 /**< Max BLE device name length, spec size: 248 */ -#define BLE_MAX_ADV_SIZE 31 - -/** Advertising Data Type. */ -#define BLE_ADV_TYPE_FLAGS 0x01 /* Flags */ -#define BLE_ADV_TYPE_INC_16_UUID 0x02 /* Incomplete List of 16-bit Service Class UUIDs */ -#define BLE_ADV_TYPE_COMP_16_UUID 0x03 /* Complete List of 16-bit Service Class UUIDs */ -#define BLE_ADV_TYPE_INC_32_UUID 0x04 /* Incomplete List of 32-bit Service Class UUIDs */ -#define BLE_ADV_TYPE_COMP_32_UUID 0x05 /* Complete List of 32-bit Service Class UUIDs */ -#define BLE_ADV_TYPE_INC_128_UUID 0x06 /* Incomplete List of 128-bit Service Class UUIDs */ -#define BLE_ADV_TYPE_COMP_128_UUID 0x07 /* Complete List of 128-bit Service Class UUIDs */ -#define BLE_ADV_TYPE_SHORT_LOCAL_NAME 0x08 /* Shortened Local Name */ -#define BLE_ADV_TYPE_COMP_LOCAL_NAME 0x09 /* Complete Local Name */ -#define BLE_ADV_TYPE_TX_POWER 0x0A /* Tx Power Level */ -#define BLE_ADV_TYPE_CLASS 0x0D /* Class of Device */ -#define BLE_ADV_TYPE_PAIRING_C 0x0E /* Simple Pairing Hash C */ -#define BLE_ADV_TYPE_PAIRING_C_192 0x0E /* Simple Pairing Hash C-192 */ -#define BLE_ADV_TYPE_PAIRING_R_192 0x0F /* Simple Pairing Randomizer R-192 */ -#define BLE_ADV_TYPE_DEVICE_ID 0x10 /* Device ID */ -#define BLE_ADV_TYPE_TK_VALUE 0x10 /* Security Manager TK Value */ -#define BLE_ADV_TYPE_OOB_FLAGS 0x11 /* Security Manager Out of Band Flags */ -#define BLE_ADV_TYPE_CONN_INTERVAL_RANGE 0x12 /* Slave Connection Interval Range */ -#define BLE_ADV_TYPE_SERVICE_SOLICITATION_16_UUID 0x14 /* List of 16-bit Service Solicitation UUIDs */ -#define BLE_ADV_TYPE_SERVICE_SOLICITATION_32_UUID 0x1F /* List of 32-bit Service Solicitation UUIDs */ -#define BLE_ADV_TYPE_SERVICE_SOLICITATION_128_UUID 0x15 /* List of 128-bit Service Solicitation UUIDs */ -#define BLE_ADV_TYPE_SERVICE_DATA 0x16 /* Service Data */ -#define BLE_ADV_TYPE_SERVICE_DATA_16_UUID 0x16 /* Service Data - 16-bit UUID */ -#define BLE_ADV_TYPE_SERVICE_DATA_32_UUID 0x20 /* Service Data - 32-bit UUID */ -#define BLE_ADV_TYPE_SERVICE_DATA_128_UUID 0x21 /* Service Data - 128-bit UUID */ -#define BLE_ADV_TYPE_SEC_CONF_VALUE 0x22 /* LE Secure Connections Confirmation Value */ -#define BLE_ADV_TYPE_SEC_RANDOM_VALUE 0x23 /* LE Secure Connections Random Value */ -#define BLE_ADV_TYPE_PUB_TARGET_ADDR 0x17 /* Public Target Address */ -#define BLE_ADV_TYPE_APPEARANCE 0x19 /* Appearance */ -#define BLE_ADV_TYPE_ADV_INTERVAL 0x1A /* Advertising Interval */ -#define BLE_ADV_TYPE_DEVICE_ADDR 0x1B /* LE Bluetooth Device Address */ -#define BLE_ADV_TYPE_ROLE 0x1C /* LE Role */ -#define BLE_ADV_TYPE_PAIRING_C_256 0x1D /* Simple Pairing Hash C-256 */ -#define BLE_ADV_TYPE_PAIRING_R_256 0x1E /* Simple Pairing Randomizer R-256 */ -#define BLE_ADV_TYPE_3D 0x3D /* 3D Information Data */ -#define BLE_ADV_TYPE_MANUFACTURER 0xFF /* Manufacturer Specific Data */ - -/** BLE Service UUID Definitions. */ -#define BLE_SVC_UUID_IMMEDIATE_ALERT_SERVICE 0x1802 /**< Immediate Alert service UUID. */ -#define BLE_SVC_UUID_LINK_LOSS_SERVICE 0x1803 /**< Link Loss service UUID. */ -#define BLE_SVC_UUID_TX_POWER_SERVICE 0x1804 /**< TX Power service UUID. */ -#define BLE_SVC_UUID_CURRENT_TIME_SERVICE 0x1805 /**< Current Time service UUID. */ -#define BLE_SVC_UUID_REFERENCE_TIME_UPDATE_SERVICE 0x1806 /**< Reference Time Update service UUID. */ -#define BLE_SVC_UUID_NEXT_DST_CHANGE_SERVICE 0x1807 /**< Next Dst Change service UUID. */ -#define BLE_SVC_UUID_GLUCOSE_SERVICE 0x1808 /**< Glucose service UUID. */ -#define BLE_SVC_UUID_HEALTH_THERMOMETER_SERVICE 0x1809 /**< Health Thermometer service UUID. */ -#define BLE_SVC_UUID_DEVICE_INFORMATION_SERVICE 0x180A /**< Device Information service UUID. */ -#define BLE_SVC_UUID_HEART_RATE_SERVICE 0x180D /**< Heart Rate service UUID. */ -#define BLE_SVC_UUID_PHONE_ALERT_STATUS_SERVICE 0x180E /**< Phone Alert Status service UUID. */ -#define BLE_SVC_UUID_BATTERY_SERVICE 0x180F /**< Battery service UUID. */ -#define BLE_SVC_UUID_BLOOD_PRESSURE_SERVICE 0x1810 /**< Blood Pressure service UUID. */ -#define BLE_SVC_UUID_ALERT_NOTIFICATION_SERVICE 0x1811 /**< Alert Notification service UUID. */ -#define BLE_SVC_UUID_HUMAN_INTERFACE_DEVICE_SERVICE 0x1812 /**< Human Interface Device service UUID. */ -#define BLE_SVC_UUID_SCAN_PARAMETERS_SERVICE 0x1813 /**< Scan Parameters service UUID. */ -#define BLE_SVC_UUID_RUNNING_SPEED_AND_CADENCE 0x1814 /**< Running Speed and Cadence service UUID. */ -#define BLE_SVC_UUID_CYCLING_SPEED_AND_CADENCE 0x1816 /**< Cycling Speed and Cadence service UUID. */ - -#define BLE_SVC_GAP_ADV_FLAG_LE_LIMITED_DISC_MODE (0x01) /**< LE Limited Discoverable Mode. */ -#define BLE_SVC_GAP_ADV_FLAG_LE_GENERAL_DISC_MODE (0x02) /**< LE General Discoverable Mode. */ -#define BLE_SVC_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED (0x04) /**< BR/EDR not supported. */ -#define BLE_SVC_GAP_ADV_FLAG_LE_BR_EDR_CONTROLLER (0x08) /**< Simultaneous LE and BR/EDR, Controller. */ -#define BLE_SVC_GAP_ADV_FLAG_LE_BR_EDR_HOST (0x10) /**< Simultaneous LE and BR/EDR, Host. */ -#define BLE_SVC_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE (BLE_SVC_GAP_ADV_FLAG_LE_LIMITED_DISC_MODE | BLE_SVC_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) /**< LE Limited Discoverable Mode, BR/EDR not supported. */ -#define BLE_SVC_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE (BLE_SVC_GAP_ADV_FLAG_LE_GENERAL_DISC_MODE | BLE_SVC_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) /**< LE General Discoverable Mode, BR/EDR not supported. */ - - -/** - * Characteristics UUID definitions. - */ - -/* GAP */ -#define BLE_GAP_DEVICE_NAME 0x2A00 -#define BLE_GAP_APPEARANCE 0x2A01 -#define BLE_GAP_PER_PRIVACY_FLAG 0x2A02 -#define BLE_GAP_RECONN_ADDR 0x2A03 -#define BLE_GAP_PREF_CONN_PARAM 0x2A04 - -/* DIS */ -#define BLE_DIS_MANUFACTURER_NAME 0x2A29 -#define BLE_DIS_MODEL_NB 0x2A24 -#define BLE_DIS_SERIAL_NB 0x2A25 -#define BLE_DIS_FW_REV 0x2A26 -#define BLE_DIS_HW_REV 0x2A27 -#define BLE_DIS_SW_REV 0x2A28 -#define BLE_DIS_SYS_ID 0x2A23 -#define BLE_DIS_CERTIF_DATA_LIST 0x2A2A -#define BLE_DIS_PNP_ID 0x2A50 - -/* BATTERY */ -#define BLE_BAT_BAT_LEVEL 0x2A19 - -/* HR */ -#define BLE_HEART_RATE_MEASUREMENT 0x2A37 -#define BLE_HEART_RATE_SENSOR_LOCATION 0x2A38 -#define BLE_HEART_RATE_CONTROL_POINT 0x2A39 - -/* RSC */ -#define BLE_RSC_MEASUREMENT 0x2A53 -#define BLE_RSC_SENSOR_LOCATION 0x2A5D -#define BLE_RSC_SUPPORTED_FEATURE 0x2A54 -#define BLE_RSC_CONTROL_POINT 0x2A55 - -/*CSC */ -#define BLE_CSC_MEASUREMENT 0x2A5B -#define BLE_CSC_SENSOR_LOCATION BLE_RSC_SENSOR_LOCATION -#define BLE_CSC_SUPPORTED_FEATURE 0x2A5C -#define BLE_CSC_CONTROL_POINT 0x2A55 - -/* CP */ -#define BLE_CP_MEASUREMENT 0x2A63 -#define BLE_CP_SENSOR_LOCATION BLE_RSC_SENSOR_LOCATION -#define BLE_CP_SUPPORTED_FEATURE 0x2A65 -#define BLE_CP_POWER_VECTOR 0x2A64 -#define BLE_CP_CONTROL_POINT 0x2A66 - -/* HCI status (error) codes as per BT spec */ -#define HCI_REMOTE_USER_TERMINATED_CONNECTION 0x13 -#define HCI_REMOTE_DEV_TERMINATION_DUE_TO_LOW_RESOURCES 0x14 -#define HCI_REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF 0x15 -#define HCI_LOCAL_HOST_TERMINATED_CONNECTION 0x16 - -/** BLE GAP Appearance Characteristic definitions. - * - * See http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml - */ -#define BLE_GAP_APPEARANCE_TYPE_UNKNOWN 0 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_PHONE 64 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_COMPUTER 128 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_WATCH 192 -#define BLE_GAP_APPEARANCE_TYPE_WATCH_SPORTS_WATCH 193 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_CLOCK 256 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_DISPLAY 320 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_REMOTE_CONTROL 384 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_EYE_GLASSES 448 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_TAG 512 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_KEYRING 576 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_MEDIA_PLAYER 640 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_BARCODE_SCANNER 704 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_THERMOMETER 768 -#define BLE_GAP_APPEARANCE_TYPE_THERMOMETER_EAR 769 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_HEART_RATE_SENSOR 832 -#define BLE_GAP_APPEARANCE_TYPE_HEART_RATE_SENSOR_HEART_RATE_BELT 833 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_BLOOD_PRESSURE 896 -#define BLE_GAP_APPEARANCE_TYPE_BLOOD_PRESSURE_ARM 897 -#define BLE_GAP_APPEARANCE_TYPE_BLOOD_PRESSURE_WRIST 898 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_HID 960 -#define BLE_GAP_APPEARANCE_TYPE_HID_KEYBOARD 961 -#define BLE_GAP_APPEARANCE_TYPE_HID_MOUSE 962 -#define BLE_GAP_APPEARANCE_TYPE_HID_JOYSTICK 963 -#define BLE_GAP_APPEARANCE_TYPE_HID_GAMEPAD 964 -#define BLE_GAP_APPEARANCE_TYPE_HID_DIGITIZERSUBTYPE 965 -#define BLE_GAP_APPEARANCE_TYPE_HID_CARD_READER 966 -#define BLE_GAP_APPEARANCE_TYPE_HID_DIGITAL_PEN 967 -#define BLE_GAP_APPEARANCE_TYPE_HID_BARCODE 968 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_GLUCOSE_METER 1024 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_RUNNING_WALKING_SENSOR 1088 -#define BLE_GAP_APPEARANCE_TYPE_RUNNING_WALKING_SENSOR_IN_SHOE 1089 -#define BLE_GAP_APPEARANCE_TYPE_RUNNING_WALKING_SENSOR_ON_SHOE 1090 -#define BLE_GAP_APPEARANCE_TYPE_RUNNING_WALKING_SENSOR_ON_HIP 1091 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_CYCLING 1152 -#define BLE_GAP_APPEARANCE_TYPE_CYCLING_CYCLING_COMPUTER 1153 -#define BLE_GAP_APPEARANCE_TYPE_CYCLING_SPEED_SENSOR 1154 -#define BLE_GAP_APPEARANCE_TYPE_CYCLING_CADENCE_SENSOR 1155 -#define BLE_GAP_APPEARANCE_TYPE_CYCLING_POWER_SENSOR 1156 -#define BLE_GAP_APPEARANCE_TYPE_CYCLING_SPEED_CADENCE_SENSOR 1157 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_PULSE_OXIMETER 3136 -#define BLE_GAP_APPEARANCE_TYPE_PULSE_OXIMETER_FINGERTIP 3137 -#define BLE_GAP_APPEARANCE_TYPE_PULSE_OXIMETER_WRIST_WORN 3138 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_WEIGHT_SCALE 3200 -#define BLE_GAP_APPEARANCE_TYPE_GENERIC_OUTDOOR_SPORTS_ACT 5184 -#define BLE_GAP_APPEARANCE_TYPE_OUTDOOR_SPORTS_ACT_LOC_DISP 5185 -#define BLE_GAP_APPEARANCE_TYPE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_DISP 5186 -#define BLE_GAP_APPEARANCE_TYPE_OUTDOOR_SPORTS_ACT_LOC_POD 5187 -#define BLE_GAP_APPEARANCE_TYPE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_POD 5188 - -/** - * DTM commands, opcodes, indexes. - */ -#define DTM_HCI_CMD 0x01 -#define DTM_HCI_OPCODE2 0x20 - -#define DTM_HCI_STATUS_IDX 6 -#define DTM_HCI_LE_END_IDX (DTM_HCI_STATUS_IDX + 1) - -/** @} */ - -#endif diff --git a/system/libarc32_arduino101/framework/src/services/ble/ble_service_core_int.h b/system/libarc32_arduino101/framework/src/services/ble/ble_service_core_int.h deleted file mode 100644 index d2b9311d..00000000 --- a/system/libarc32_arduino101/framework/src/services/ble/ble_service_core_int.h +++ /dev/null @@ -1,207 +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. - */ - -#ifndef __BLE_SERVICE_CORE_INT_H__ -#define __BLE_SERVICE_CORE_INT_H__ - -#include -#include "services/ble/ble_service_gap_api.h" -#include "services/ble/ble_service_gattc_api.h" - -/* Forward declarations */ -struct _ble_service_cb; -struct ble_enable_req_msg; - -/** - * BLE common structures. - */ - -struct ble_svc_string { - uint8_t *p_string; /**< String utf8 encoded */ - uint8_t len; /**< length of string */ -}; - -struct ble_svc_sec_mode { - uint8_t rd_perm; - uint8_t wr_perm; -}; - -struct ble_svc_cccd_sec_mode { - uint8_t cccd_wr_perm; - uint8_t rd_perm; /**< Read permissions. */ - uint8_t wr_perm; /**< Write permissions. */ -}; - -struct ble_svc_report_reference { - uint8_t report_id; /**< Non-zero value if these is more than one instance of the same Report Type */ - uint8_t report_type; /**< Type of Report characteristic */ -}; - -struct ble_gap_write_config_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - uint16_t appearance; - uint8_t bda_len; - uint8_t name_len; - int8_t tx_power; - struct ble_gap_connection_params peripheral_conn_params; - struct ble_gap_connection_params central_conn_params; - uint8_t data[]; -}; - -struct ble_gap_wr_adv_data_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - uint8_t adv_len; - uint8_t scan_rsp_len; - uint8_t data[]; - /* adv_data, - * scan_rsp_dat */ -}; - -struct ble_gap_start_advertise_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - uint16_t timeout; - uint16_t interval_min; /**< min interval 0xffff: use default 0x0800 */ - uint16_t interval_max; /**< max interval 0xffff: use default 0x0800 */ - uint8_t type; /**< advertisement types @ref GAP_ADV_TYPES */ - uint8_t filter_policy; /**< filter policy to apply with white list */ - uint8_t options; /**< options see @ref BLE_GAP_ADV_OPTIONS (to be ORed) */ - uint8_t bda_len; /**< non 0 if peer_bda is present */ - uint8_t peer_bda[]; /**< format ble_addr_t */ -}; - -struct ble_gap_conn_update_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - uint16_t conn_handle; - struct ble_gap_connection_params conn_params; -}; - -struct ble_gap_svc_local_name_req { - uint8_t sec_mode; /**< security mode for writing device name, @ref BLE_GAP_SEC_MODES (GAP_SEC_NO_PERMISSION: write forbidden) */ - uint8_t authorization; /**< 0: no authorization, 1: authorization required */ - uint8_t len; /**< device name length (0-248) */ - uint8_t name_array[]; /**< name to to write */ -}; - -struct ble_gap_service_write_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - uint16_t attr_type; /**< GAP Characteristics attribute type @ref BLE_GAP_SVC_ATTR_TYPE */ - union { - struct ble_gap_svc_local_name_req name; - uint16_t appearance; /**< Appearance UUID */ - struct ble_gap_connection_params conn_params; - /**< Preferred Peripheral Connection Parameters */ - uint8_t car; /**< Central Address Resolution support 0: no, 1: yes */ - }; -}; - -struct ble_gap_disconnect_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - uint16_t conn_handle; /**< Connection handle*/ - uint8_t reason; /**< Reason of the disconnect*/ -}; - -struct ble_gap_sm_config_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - struct ble_gap_sm_config_params params; -}; - -struct ble_gap_sm_pairing_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - struct ble_gap_sm_pairing_params params; - uint16_t conn_handle; -}; - -struct ble_dtm_test_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - struct ble_test_cmd params; -}; - -struct ble_gap_set_rssi_report_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - struct rssi_report_params params; /**< RSSI report config @ref rssi_report_cfg */ -}; - -struct ble_gattc_discover_primary_service_req_msg { - struct cfw_message header; - uint16_t conn_handle; /**< Connection handle */ - uint8_t data[]; /**< Variable length data of the request (UUID) */ -}; - -struct ble_gattc_discover_included_service_req_msg { - struct cfw_message header; - uint16_t conn_handle; - struct ble_gattc_handle_range handle_range; -}; - -struct ble_gattc_discover_characteristic_req_msg { - struct cfw_message header; - uint16_t conn_handle; - struct ble_gattc_handle_range handle_range; -}; - -struct ble_gattc_discover_descriptor_req_msg { - struct cfw_message header; - uint16_t conn_handle; - struct ble_gattc_handle_range handle_range; -}; - -struct ble_gattc_read_characteristic_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - uint16_t conn_handle; /**< Connection handle*/ - uint16_t char_handle; /**< handle of the attribute to be read */ - uint16_t offset; /**< offset into the attribute value to be read */ -}; - -struct _ble_gattc_wr_characteristic { - uint16_t char_handle; /**< handle of characteristic */ - uint16_t len; /**< if len is bigger then ATT MTU size, the controller fragment buffer itself */ - uint8_t wr_type; /**< type of write operation @ref BLE_GATT_WR_OP_TYPES */ - uint8_t value[]; /**< characteristic value to write */ -}; - -struct ble_gattc_write_char_op_req_msg { - struct cfw_message header; - uint16_t conn_handle; - struct _ble_gattc_wr_characteristic wr_char_param; -}; - -/** - * Generic BLE controller commands. - */ -struct ble_generic_cmd_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ -}; - - -void ble_core_resume_enable(struct ble_enable_req_msg *req, struct _ble_service_cb * p_cb, uint8_t * p_name); - -void ble_core_delete_conn_params_timer(void); - -#endif diff --git a/system/libarc32_arduino101/framework/src/services/ble/ble_service_gap_api.c b/system/libarc32_arduino101/framework/src/services/ble/ble_service_gap_api.c deleted file mode 100644 index 6b772864..00000000 --- a/system/libarc32_arduino101/framework/src/services/ble/ble_service_gap_api.c +++ /dev/null @@ -1,384 +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 -#include "services/ble/ble_service_gap_api.h" -#include "ble_protocol.h" -#include "ble_service_core_int.h" -#include "infra/log.h" - -int ble_gap_set_enable_config(svc_client_handle_t * p_svc_handle, - const struct ble_wr_config * p_config, - void * p_priv) -{ - struct ble_gap_write_config_req_msg *msg; - int total_len = sizeof(*msg); - int str_len = 0; - - if (p_config->p_bda) - total_len += sizeof(ble_addr_t); - if (p_config->p_name) { - str_len = strlen((char *)p_config->p_name); - if (str_len > BLE_MAX_DEVICE_NAME) - return -2; - total_len += str_len; - } - msg = (struct ble_gap_write_config_req_msg *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_WR_CONF_REQ, - total_len, - p_priv); - msg->name_len = str_len; - msg->appearance = p_config->appearance; - msg->tx_power = p_config->tx_power; - msg->central_conn_params = p_config->central_conn_params; - msg->peripheral_conn_params = p_config->peripheral_conn_params; - if (p_config->p_bda) { - msg->bda_len = sizeof(ble_addr_t); - memcpy(msg->data, p_config->p_bda, msg->bda_len); - } else - msg->bda_len = 0; - if (p_config->p_name) - strcpy((char *)&msg->data[msg->bda_len], (char *)p_config->p_name); - - return cfw_send_message(msg); -} - -int ble_gap_read_bda(svc_client_handle_t * p_svc_handle, void * p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_RD_BDA_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gap_wr_adv_data(svc_client_handle_t * p_svc_handle, - const struct ble_gap_adv_rsp_data * p_adv_data, - const struct ble_gap_adv_rsp_data * p_scan_data, - void * p_priv) -{ - int data_len = sizeof(struct ble_gap_wr_adv_data_req_msg); - struct ble_gap_wr_adv_data_req_msg *msg; - - if (NULL != p_adv_data) - data_len += p_adv_data->len; - if (NULL != p_scan_data) - data_len += p_scan_data->len; - - msg = (struct ble_gap_wr_adv_data_req_msg *)cfw_alloc_message_for_service( - p_svc_handle, MSG_ID_BLE_GAP_WR_ADV_DATA_REQ, - data_len, p_priv); - - if (NULL != p_adv_data) { - int i; - msg->adv_len = p_adv_data->len; - for (i = 0; i < msg->adv_len; i++) - msg->data[i] = p_adv_data->p_data[i]; - } else - msg->adv_len = 0; - - if (NULL != p_scan_data) { - int i; - msg->scan_rsp_len = p_scan_data->len; - for (i = 0; i < msg->adv_len; i++) - msg->data[msg->adv_len + i] = p_scan_data->p_data[i]; - } else - msg->scan_rsp_len = 0; - - return cfw_send_message(msg); -} - - -int ble_gap_wr_white_list(svc_client_handle_t * p_svc_handle, - const struct ble_gap_whitelist_info * p_white_list, - void * p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_WR_WHITE_LIST_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gap_clr_white_list(svc_client_handle_t * p_svc_handle, - uint32_t wl_hdl, void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_CLR_WHITE_LIST_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gap_start_advertise(svc_client_handle_t * p_svc_handle, - const ble_gap_adv_param_t * p_adv_param, - void *p_priv) -{ - struct ble_gap_start_advertise_req_msg *msg; - int data_len = sizeof(struct ble_gap_start_advertise_req_msg); - - if ((NULL != p_adv_param) && (NULL != p_adv_param->p_peer_bda)) { - data_len += sizeof(ble_addr_t); - } - msg = (struct ble_gap_start_advertise_req_msg *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_ENABLE_ADV_REQ, - data_len, - p_priv); - if (NULL != p_adv_param) { - uint8_t i; - msg->filter_policy = p_adv_param->filter_policy; - msg->interval_max = p_adv_param->interval_max; - msg->interval_min = p_adv_param->interval_min; - msg->options = p_adv_param->options; - msg->timeout = p_adv_param->timeout; - msg->type = p_adv_param->type; - if (NULL != (p_adv_param->p_peer_bda)) - { - msg->peer_bda[0] = p_adv_param->p_peer_bda->type; - for (i = 1; i <= BLE_ADDR_LEN; i++) - { - msg->peer_bda[i] = p_adv_param->p_peer_bda->addr[i-1]; - } - msg->bda_len = i; - } else - msg->bda_len = 0; - } - return cfw_send_message(msg); -} - -int ble_gap_stop_advertise(svc_client_handle_t * p_svc_handle, void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_DISABLE_ADV_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gap_conn_update(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const struct ble_gap_connection_params * p_conn_param, - void *p_priv) -{ - CFW_ALLOC_FOR_SVC(struct ble_gap_conn_update_req_msg, msg, p_svc_handle, - MSG_ID_BLE_GAP_CONN_UPDATE_REQ, 0, p_priv); - - msg->conn_handle = conn_handle; - msg->conn_params = *p_conn_param; - - return cfw_send_message(msg); -} - -int ble_gap_disconnect(svc_client_handle_t * p_svc_handle, - uint16_t conn_hdl, uint8_t reason, - void *p_priv) -{ - struct ble_gap_disconnect_req_msg *msg; - - msg = (struct ble_gap_disconnect_req_msg*)cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_DISCONNECT_REQ, - sizeof(*msg), - p_priv); - - msg->reason = reason; - msg->conn_handle = conn_hdl; - - return cfw_send_message(msg); -} - -int ble_gap_service_write(svc_client_handle_t * p_svc_handle, - const struct ble_gap_service_write_params * p_params, - void *p_priv) -{ - struct ble_gap_service_write_req_msg *msg; - int total_len = sizeof(*msg); - if ((p_params->attr_type == GAP_SVC_ATTR_NAME) && (p_params->name.len)) { - total_len += p_params->name.len; - } - msg = (struct ble_gap_service_write_req_msg *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_SERVICE_WRITE_REQ, - total_len, - p_priv); - msg->attr_type = p_params->attr_type; - - switch (p_params->attr_type) { - case GAP_SVC_ATTR_NAME: - msg->name.authorization = p_params->name.authorization; - msg->name.len = p_params->name.len; - msg->name.sec_mode = p_params->name.sec_mode; - if (msg->name.len) - strcpy((char *)&msg->name.name_array[0], (char *)p_params->name.p_name); - break; - case GAP_SVC_ATTR_APPEARANCE: - msg->appearance = p_params->appearance; - break; - case GAP_SVC_ATTR_PPCP: - msg->conn_params = p_params->conn_params; - break; - case GAP_SVC_ATTR_CAR: - msg->car = p_params->car; - break; - default: - pr_warning(LOG_MODULE_BLE, "ble_gap_srv_wr: Attr " - "not supported : 0x%x", p_params->attr_type); - } - - return cfw_send_message(msg); -} - -int ble_gap_service_read(svc_client_handle_t * p_svc_handle, - uint16_t type, void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_SERVICE_READ_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gap_sm_config(const svc_client_handle_t * h, - const struct ble_gap_sm_config_params * p_params, - void *p_priv) -{ - CFW_ALLOC_FOR_SVC(struct ble_gap_sm_config_req_msg, msg, h, MSG_ID_BLE_GAP_SM_CONFIG_REQ, 0, p_priv); - - msg->params = *p_params; - - return cfw_send_message(msg); -} - -int ble_gap_sm_pairing_req(const svc_client_handle_t * h, - uint16_t conn_handle, - const struct ble_gap_sm_pairing_params * p_params, - void *p_priv) -{ - CFW_ALLOC_FOR_SVC(struct ble_gap_sm_pairing_req_msg, msg, h, MSG_ID_BLE_GAP_SM_PAIRING_REQ, 0, p_priv); - - msg->params = *p_params; - msg->conn_handle = conn_handle; - - return cfw_send_message(msg); -} - -int ble_gap_set_rssi_report(svc_client_handle_t * p_svc_handle, - const struct rssi_report_params *params, - void *p_priv) -{ - CFW_ALLOC_FOR_SVC(struct ble_gap_set_rssi_report_req_msg, msg, p_svc_handle, MSG_ID_BLE_GAP_SET_RSSI_REPORT_REQ, 0, p_priv); - msg->params = *params; - return cfw_send_message(msg); -} - -int ble_gap_start_scan(svc_client_handle_t * p_svc_handle, - const ble_gap_scan_param_t * p_scan_params, void * p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_SCAN_START_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gap_stop_scan(svc_client_handle_t * p_svc_handle, void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_SCAN_STOP_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gap_connect(svc_client_handle_t * p_svc_handle, const ble_addr_t * p_bd, - const ble_gap_scan_param_t * p_scan_params, - const struct ble_gap_connection_params * p_conn_params, - void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_CONNECT_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gap_cancel_connect(svc_client_handle_t * p_svc_handle, - const ble_addr_t * p_bd, void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_CONNECT_CANCEL_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gap_set_option(svc_client_handle_t * p_svc_handle, uint8_t op, - const ble_gap_option_t * p_opt, void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_SET_OPTIONS_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gap_generic_cmd_req(svc_client_handle_t * p_svc_handle, - const struct ble_gap_gen_cmd_params *p_params, - void *p_priv) -{ - struct ble_generic_cmd_req_msg *msg = (struct ble_generic_cmd_req_msg *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_GENERIC_CMD_REQ, - sizeof(*msg), - p_priv); - - return cfw_send_message(msg); -} - -int ble_gap_get_version_req(svc_client_handle_t * p_svc_handle, void * p_priv) -{ - struct cfw_message *msg = (struct cfw_message *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_GET_VERSION_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gap_dtm_init_req(svc_client_handle_t * p_svc_handle, void * p_priv) -{ - struct cfw_message *msg = (struct cfw_message *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GAP_DTM_INIT_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} diff --git a/system/libarc32_arduino101/framework/src/services/ble/ble_service_gatt_int.h b/system/libarc32_arduino101/framework/src/services/ble/ble_service_gatt_int.h deleted file mode 100644 index 3f42b09f..00000000 --- a/system/libarc32_arduino101/framework/src/services/ble/ble_service_gatt_int.h +++ /dev/null @@ -1,102 +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. - */ - -#ifndef __BLE_SERVICE_GATT_INT_H__ -#define __BLE_SERVICE_GATT_INT_H__ - -#include "services/ble/ble_service_gatt.h" -#include "services/ble/ble_service_gatts_api.h" - -/** - * BLE GATT related shared internal structures between master and BLE controller. - */ -struct ble_gatts_add_service_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_gatts_add_svc_cback_t cback; /**< Callback function to be returnedn in response message */ - uint8_t type; /**< Primary or secondary \ref BLE_GATT_SVC_TYPES. */ - uint8_t data[]; /**< Variable length data of the request (UUID) */ -}; - -/** - * Component framework message to add a characteristic to a service - */ -struct ble_gatts_add_char_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_gatts_add_char_cback_t cback; /**< Callback function, to be returned to sender! */ - uint16_t svc_handle; /**< Handle of the service to which the characteristic should be added */ - struct ble_gatts_permissions perms; - struct ble_gatt_char_properties props; - uint16_t max_len; /**< Maximum length of the characteristic value */ - uint16_t init_len; /**< Length of the initialization value */ - uint8_t ud_len; /**< Length of the characteristic User Description */ - uint8_t pf_len; - - uint8_t data[]; /**< Variable length data of the request (UUID, init value, user descriptor) */ -}; - -/** - * Component framework message to add a descriptor to a characteristic - */ -struct ble_gatts_add_desc_req_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_gatts_add_desc_cback_t cback; /**< Callback function, to be returned to sender! */ - uint16_t length; - struct ble_gatts_permissions perms; /**< Read/Write permissions for descriptor */ - uint8_t data[]; /**< Variable length data of the request (descriptor value) */ -}; - -struct ble_gatts_start_service_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - uint16_t svc_handle; -}; - -struct ble_gatts_set_attribute_value_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - uint16_t value_handle; /* mandatory */ - uint16_t len; - uint16_t offset; /* by default 0 */ - uint8_t data[]; /* value to update */ -}; - -struct ble_gatts_notif_ind_params { - uint16_t conn_handle; - uint16_t val_handle; - uint16_t len; /* may be 0, in this case already stored data is sent */ - uint16_t offset; - uint8_t data[]; -}; - -struct ble_gatts_send_notif_ind_msg { - struct cfw_message header; /**< Component framework message header (@ref cfw), MUST be first element of structure */ - ble_gatts_notif_ind_cback_t cback; /**< Callback function to be returned in response message */ - struct ble_gatts_notif_ind_params params; /* parameters for notification/indication */ -}; - -#endif diff --git a/system/libarc32_arduino101/framework/src/services/ble/ble_service_gatts_api.c b/system/libarc32_arduino101/framework/src/services/ble/ble_service_gatts_api.c deleted file mode 100644 index 17345bde..00000000 --- a/system/libarc32_arduino101/framework/src/services/ble/ble_service_gatts_api.c +++ /dev/null @@ -1,287 +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 "services/ble/ble_service_gatt.h" -#include "services/ble/ble_service_gatts_api.h" -#include "ble_service_core_int.h" -#include "ble_service_gatt_int.h" -#include "ble_service_utils.h" -#include - -int ble_gatts_add_service(svc_client_handle_t * p_svc_handle, - const struct bt_uuid * p_uuid, - uint8_t type, - ble_gatts_add_svc_cback_t cback, - void *p_priv) -{ - struct ble_gatts_add_service_req_msg *msg = - (struct ble_gatts_add_service_req_msg *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_ADD_SERVICE_REQ, - sizeof(*msg) + ble_sizeof_bt_uuid(p_uuid), - p_priv); - msg->cback = cback; - msg->type = type; - uint8_t *p = (uint8_t *)&msg->data; - ble_encode_bt_uuid(p_uuid, p); - return cfw_send_message(msg); -} - -int ble_gatts_add_included_svc(svc_client_handle_t * p_svc_handle, - uint16_t svc_handle, - uint16_t svc_handle_to_include, - void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_ADD_INCL_SVC_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gatts_add_characteristic(svc_client_handle_t * p_svc_handle, - uint16_t svc_handle, - const struct ble_gatts_characteristic * p_char, - ble_gatts_add_char_cback_t cback, - void *p_priv) -{ - struct ble_gatts_add_char_req_msg *msg; - int data_len = sizeof(struct ble_gatts_add_char_req_msg); - uint8_t * p; - - // Sanity check - if (!p_char || !p_char->p_uuid) - return E_OS_ERR; - - // compute the variable length part of the message - data_len += ble_sizeof_bt_uuid(p_char->p_uuid); - data_len += p_char->init_len; - if (p_char->p_user_desc) - data_len += p_char->p_user_desc->len; - if (p_char->p_char_pf_desc) - data_len += sizeof(struct ble_gatt_pf_desc); - - msg = (struct ble_gatts_add_char_req_msg *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_ADD_CHARACTERISTIC_REQ, - data_len, p_priv); - msg->cback = cback; - p = msg->data; - p = ble_encode_bt_uuid(p_char->p_uuid, p); - msg->svc_handle = svc_handle; - msg->perms = p_char->perms; - msg->props = p_char->props; - msg->max_len = p_char->max_len; - msg->init_len = p_char->init_len; - memcpy(p, p_char->p_value, p_char->init_len); - p += p_char->init_len; - if (p_char->p_user_desc) { - msg->ud_len = p_char->p_user_desc->len; - memcpy(p, p_char->p_user_desc->buffer, p_char->p_user_desc->len); - p += p_char->p_user_desc->len; - } - if (p_char->p_char_pf_desc) { - msg->pf_len = sizeof(struct ble_gatt_pf_desc); - memcpy(p, p_char->p_char_pf_desc, msg->pf_len); - p += msg->pf_len; - } - return cfw_send_message(msg); -} - -int ble_gatts_add_descriptor(svc_client_handle_t * p_svc_handle, - const struct ble_gatts_descriptor * p_desc, - ble_gatts_add_desc_cback_t cback, - void * p_priv) -{ - struct ble_gatts_add_desc_req_msg *req; - uint8_t * p; - int data_len = sizeof(struct ble_gatts_add_desc_req_msg); - - /* Sanity check */ - if (!p_desc || !p_desc->length || !p_desc->p_value || !p_desc->p_uuid) - return E_OS_ERR; - - // compute the variable length part of the message - data_len += ble_sizeof_bt_uuid(p_desc->p_uuid); - data_len += p_desc->length; - - req = (struct ble_gatts_add_desc_req_msg *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_ADD_DESCRIPTOR_REQ, - data_len, p_priv); - req->cback = cback; - p = req->data; - p = ble_encode_bt_uuid(p_desc->p_uuid, p); - req->length = p_desc->length; - req->perms = p_desc->perms; - memcpy(p, p_desc->p_value, p_desc->length); - - return cfw_send_message(req); -} - - -int ble_gatts_start_service(svc_client_handle_t * p_svc_handle, - uint16_t svc_handle, - void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_START_SERVICE_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gatts_remove_service(svc_client_handle_t * p_svc_handle, - uint16_t svc_handle, - void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_REMOVE_SERVICE_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gatts_send_svc_changed(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - uint16_t start_handle, - uint16_t end_handle, - void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_INDICATE_SERVICE_CHANGE_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gatts_set_attribute_value(svc_client_handle_t * p_svc_handle, - uint16_t value_handle, - uint16_t len, - const uint8_t * p_value, - uint16_t offset, - void *p_priv) -{ - int i; - struct ble_gatts_set_attribute_value_msg *msg = - (struct ble_gatts_set_attribute_value_msg *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_SET_ATTRIBUTE_VALUE_REQ, - sizeof(*msg)+len, - p_priv); - msg->value_handle = value_handle; - msg->len = len; - msg->offset = offset; - - for (i = 0; i < len; i++) - msg->data[i] = p_value[i]; - return cfw_send_message(msg); -} - -int ble_gatts_get_attribute_value(svc_client_handle_t * p_svc_handle, - uint16_t value_handle, - uint16_t len, - uint16_t offset, - void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_GET_ATTRIBUTE_VALUE_REQ, sizeof(*msg), - p_priv); - - return cfw_send_message(msg); -} - -int ble_gatts_send_notif(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const ble_gatts_ind_params_t * p_params, - ble_gatts_notif_ind_cback_t cback, - void *p_priv) -{ - struct ble_gatts_send_notif_ind_msg *msg = - (struct ble_gatts_send_notif_ind_msg *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_SEND_NOTIF_REQ, - sizeof(*msg) + p_params->len, - p_priv); - - msg->cback = cback; - msg->params.conn_handle = conn_handle; - msg->params.val_handle = p_params->val_handle; - msg->params.len = p_params->len; - msg->params.offset = p_params->offset; - memcpy(msg->params.data, p_params->p_data, msg->params.len); - return cfw_send_message(msg); -} - -int ble_gatts_send_ind(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const ble_gatts_ind_params_t * p_params, - ble_gatts_notif_ind_cback_t cback, - void *p_priv) -{ - struct ble_gatts_send_notif_ind_msg *msg = - (struct ble_gatts_send_notif_ind_msg *) - cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_SEND_IND_REQ, - sizeof(*msg) + p_params->len, - p_priv); - - msg->cback = cback; - msg->params.conn_handle = conn_handle; - msg->params.val_handle = p_params->val_handle; - msg->params.len = p_params->len; - msg->params.offset = p_params->offset; - memcpy(msg->params.data, p_params->p_data, msg->params.len); - return cfw_send_message(msg); -} - -int ble_gatts_write_conn_attributes(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - const uint8_t * p_data, - uint16_t len, - void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_WR_CONN_ATTRIBUTES_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} - -int ble_gatts_read_conn_attributes(svc_client_handle_t * p_svc_handle, - uint16_t conn_handle, - void *p_priv) -{ - struct cfw_message *msg = cfw_alloc_message_for_service(p_svc_handle, - MSG_ID_BLE_GATTS_RD_CONN_ATTRIBUTES_REQ, - sizeof(*msg), - p_priv); - return cfw_send_message(msg); -} diff --git a/system/libarc32_arduino101/framework/src/services/ble/conn.c b/system/libarc32_arduino101/framework/src/services/ble/conn.c new file mode 100644 index 00000000..c0aa9014 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble/conn.c @@ -0,0 +1,927 @@ +/* + * 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 + +#include "hci_core.h" +#include "conn_internal.h" +#include "gap_internal.h" +#include "l2cap_internal.h" +#include "smp.h" + +/* #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_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_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) +#endif + +#if defined(CONFIG_BLUETOOTH_SMP) || defined(CONFIG_BLUETOOTH_BREDR) +const struct bt_conn_auth_cb *bt_auth; +#endif /* CONFIG_BLUETOOTH_SMP || CONFIG_BLUETOOTH_BREDR */ + +static struct bt_conn conns[CONFIG_BLUETOOTH_MAX_CONN]; +static struct bt_conn_cb *callback_list; + +static void notify_connected(struct bt_conn *conn) +{ + struct bt_conn_cb *cb; + + for (cb = callback_list; cb; cb = cb->_next) { + if (cb->connected) { + cb->connected(conn, conn->err); + } + } +} + +static void notify_disconnected(struct bt_conn *conn) +{ + struct bt_conn_cb *cb; + + for (cb = callback_list; cb; cb = cb->_next) { + if (cb->disconnected) { + cb->disconnected(conn, conn->err); + } + } +} + +void notify_le_param_updated(struct bt_conn *conn) +{ + struct bt_conn_cb *cb; + + for (cb = callback_list; cb; cb = cb->_next) { + if (cb->le_param_updated) { + cb->le_param_updated(conn, conn->le.interval, + conn->le.latency, + conn->le.timeout); + } + } +} + +#if defined(CONFIG_BLUETOOTH_SMP) + +void bt_conn_security_changed(struct bt_conn *conn) +{ + struct bt_conn_cb *cb; + + for (cb = callback_list; cb; cb = cb->_next) { + if (cb->security_changed) { + cb->security_changed(conn, conn->sec_level); + } + } +} + +static int start_security(struct bt_conn *conn) +{ + switch (conn->role) { +#if defined(CONFIG_BLUETOOTH_CENTRAL) + case BT_HCI_ROLE_MASTER: + { +#ifdef NOT_APPLICABLE_NBLE + if (!conn->keys) { + conn->keys = bt_keys_find(BT_KEYS_LTK_P256, + &conn->le.dst); + if (!conn->keys) { + conn->keys = bt_keys_find(BT_KEYS_LTK, + &conn->le.dst); + } + } + + if (!conn->keys || + !(conn->keys->keys & (BT_KEYS_LTK | BT_KEYS_LTK_P256))) { + return bt_smp_send_pairing_req(conn); + } + + if (conn->required_sec_level > BT_SECURITY_MEDIUM && + !atomic_test_bit(&conn->keys->flags, + BT_KEYS_AUTHENTICATED)) { + return bt_smp_send_pairing_req(conn); + } + + if (conn->required_sec_level > BT_SECURITY_HIGH && + !atomic_test_bit(&conn->keys->flags, + BT_KEYS_AUTHENTICATED) && + !(conn->keys->keys & BT_KEYS_LTK_P256)) { + return bt_smp_send_pairing_req(conn); + } + + /* LE SC LTK and legacy master LTK are stored in same place */ + return bt_conn_le_start_encryption(conn, conn->keys->ltk.rand, + conn->keys->ltk.ediv, + conn->keys->ltk.val, + conn->keys->enc_size); +#endif + return bt_smp_send_pairing_req(conn); + } +#endif /* CONFIG_BLUETOOTH_CENTRAL */ +#if defined(CONFIG_BLUETOOTH_PERIPHERAL) + case BT_HCI_ROLE_SLAVE: + return bt_smp_send_security_req(conn); +#endif /* CONFIG_BLUETOOTH_PERIPHERAL */ + default: + return -EINVAL; + } +} + +int bt_conn_security(struct bt_conn *conn, bt_security_t sec) +{ + int err; + + if (conn->state != BT_CONN_CONNECTED) { + return -ENOTCONN; + } + +#if defined(CONFIG_BLUETOOTH_SMP_SC_ONLY) + if (sec < BT_SECURITY_FIPS) { + return -EOPNOTSUPP; + } +#endif/* CONFIG_BLUETOOTH_SMP_SC_ONLY */ + + /* nothing to do */ + if (conn->sec_level >= sec || conn->required_sec_level >= sec) { + return 0; + } + + conn->required_sec_level = sec; + + err = start_security(conn); + + /* reset required security level in case of error */ + if (err) { + conn->required_sec_level = conn->sec_level; + } + return err; +} +#endif /* CONFIG_BLUETOOTH_SMP */ + +void bt_conn_cb_register(struct bt_conn_cb *cb) +{ + cb->_next = callback_list; + callback_list = cb; +} + +static struct bt_conn *conn_new(void) +{ + struct bt_conn *conn = NULL; + int i; + + for (i = 0; i < ARRAY_SIZE(conns); i++) { + if (!atomic_get(&conns[i].ref)) { + conn = &conns[i]; + break; + } + } + + if (!conn) { + return NULL; + } + + memset(conn, 0, sizeof(*conn)); + + atomic_set(&conn->ref, 1); + + return conn; +} + +struct bt_conn *bt_conn_add_le(const bt_addr_le_t *peer) +{ + struct bt_conn *conn = conn_new(); + + if (!conn) { + return NULL; + } + + bt_addr_le_copy(&conn->le.dst, peer); +#if defined(CONFIG_BLUETOOTH_SMP) + conn->sec_level = BT_SECURITY_LOW; + conn->required_sec_level = BT_SECURITY_LOW; +#endif /* CONFIG_BLUETOOTH_SMP */ + conn->type = BT_CONN_TYPE_LE; + conn->le.interval_min = BT_GAP_INIT_CONN_INT_MIN; + conn->le.interval_max = BT_GAP_INIT_CONN_INT_MAX; + + return conn; +} + +#if defined(CONFIG_BLUETOOTH_BREDR) +struct bt_conn *bt_conn_lookup_addr_br(const bt_addr_t *peer) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(conns); i++) { + if (!atomic_get(&conns[i].ref)) { + continue; + } + + if (conns[i].type != BT_CONN_TYPE_BR) { + continue; + } + + if (!bt_addr_cmp(peer, &conns[i].br.dst)) { + return bt_conn_ref(&conns[i]); + } + } + + return NULL; +} + +struct bt_conn *bt_conn_add_br(const bt_addr_t *peer) +{ + struct bt_conn *conn = conn_new(); + + if (!conn) { + return NULL; + } + + bt_addr_copy(&conn->br.dst, peer); + conn->type = BT_CONN_TYPE_BR; + + return conn; +} +#endif + +void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state) +{ + bt_conn_state_t old_state; + + BT_DBG("conn state %d -> %d, err: %d", conn->state, state, conn->err); + + if (conn->state == state) { + BT_DBG("no transition"); + return; + } + + old_state = conn->state; + conn->state = state; + + /* Actions needed for exiting the old state */ + switch (old_state) { + case BT_CONN_DISCONNECTED: + /* Take a reference for the first state transition after + * bt_conn_add_le() and keep it until reaching DISCONNECTED + * again. + */ + bt_conn_ref(conn); + break; + case BT_CONN_CONNECT: +#if 0 + if (conn->timeout) { + fiber_delayed_start_cancel(conn->timeout); + conn->timeout = NULL; + + /* Drop the reference taken by timeout fiber */ + bt_conn_unref(conn); + } +#endif + break; + default: + break; + } + + /* Actions needed for entering the new state */ + switch (conn->state) { + case BT_CONN_CONNECTED: + bt_l2cap_connected(conn); + notify_connected(conn); + break; + case BT_CONN_DISCONNECTED: + /* Notify disconnection and queue a dummy buffer to wake + * up and stop the tx fiber for states where it was + * running. + */ + if (old_state == BT_CONN_CONNECTED || + old_state == BT_CONN_DISCONNECT) { + bt_l2cap_disconnected(conn); + notify_disconnected(conn); + } else if (old_state == BT_CONN_CONNECT) { + /* conn->err will be set in this case */ + notify_connected(conn); + } + + /* Release the reference we took for the very first + * state transition. + */ + bt_conn_unref(conn); + + break; + case BT_CONN_CONNECT_SCAN: + break; + case BT_CONN_CONNECT: + break; + case BT_CONN_DISCONNECT: + break; + default: + + break; + } +} + +struct bt_conn *bt_conn_lookup_handle(uint16_t handle) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(conns); i++) { + if (!atomic_get(&conns[i].ref)) { + continue; + } + /* We only care about connections with a valid handle */ + if (conns[i].state != BT_CONN_CONNECTED && + conns[i].state != BT_CONN_DISCONNECT) { + continue; + } + + if (conns[i].handle == handle) { + return bt_conn_ref(&conns[i]); + } + } + + return NULL; +} + +struct bt_conn *bt_conn_lookup_addr_le(const bt_addr_le_t *peer) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(conns); i++) { + if (!atomic_get(&conns[i].ref)) { + continue; + } + + if (conns[i].type != BT_CONN_TYPE_LE) { + continue; + } + + if (!bt_addr_le_cmp(peer, &conns[i].le.dst)) { + return bt_conn_ref(&conns[i]); + } + } + + return NULL; +} + +struct bt_conn *bt_conn_lookup_state_le(const bt_addr_le_t *peer, + const bt_conn_state_t state) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(conns); i++) { + if (!atomic_get(&conns[i].ref)) { + continue; + } + + if (conns[i].type != BT_CONN_TYPE_LE) { + continue; + } + + if (bt_addr_le_cmp(peer, BT_ADDR_LE_ANY) && + bt_addr_le_cmp(peer, &conns[i].le.dst)) { + continue; + } + + if (conns[i].state == state) { + return bt_conn_ref(&conns[i]); + } + } + + return NULL; +} + +struct bt_conn *bt_conn_ref(struct bt_conn *conn) +{ + atomic_inc(&conn->ref); + + return conn; +} + +void bt_conn_unref(struct bt_conn *conn) +{ + atomic_dec(&conn->ref); +} + +const bt_addr_le_t *bt_conn_get_dst(const struct bt_conn *conn) +{ + return &conn->le.dst; +} + +int bt_conn_get_info(const struct bt_conn *conn, struct bt_conn_info *info) +{ + info->type = conn->type; + info->role = conn->role; + + 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; + info->le.timeout = conn->le.timeout; + + return 0; +#if defined(CONFIG_BLUETOOTH_BREDR) + case BT_CONN_TYPE_BR: + info->br.dst = &conn->br.dst; + return 0; +#endif + } + + return -EINVAL; +} + +static int bt_hci_disconnect(struct bt_conn *conn, uint8_t reason) +{ + struct nble_gap_disconnect_req_params ble_gap_disconnect; + + ble_gap_disconnect.conn_handle = conn->handle; + ble_gap_disconnect.reason = reason; + nble_gap_disconnect_req(&ble_gap_disconnect); + + bt_conn_set_state(conn, BT_CONN_DISCONNECT); + return 0; +} + +static int bt_hci_connect_le_cancel(struct bt_conn *conn) +{ + nble_gap_cancel_connect_req(conn); + return 0; +} + +void on_nble_gap_cancel_connect_rsp(const struct nble_response *params) +{ + struct bt_conn *conn = params->user_data; + + conn->err = BT_HCI_ERR_INSUFFICIENT_RESOURCES; + bt_conn_set_state(conn, BT_CONN_DISCONNECTED); +} + +int bt_conn_disconnect(struct bt_conn *conn, uint8_t reason) +{ +#if defined(CONFIG_BLUETOOTH_CENTRAL) + /* Disconnection is initiated by us, so auto connection shall + * be disabled. Otherwise the passive scan would be enabled + * and we could send LE Create Connection as soon as the remote + * starts advertising. + */ + if (conn->type == BT_CONN_TYPE_LE) { + bt_le_set_auto_conn(&conn->le.dst, NULL); + } +#endif + + switch (conn->state) { + 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 */ + return 0; + case BT_CONN_CONNECT: + return bt_hci_connect_le_cancel(conn); + case BT_CONN_CONNECTED: + return bt_hci_disconnect(conn, reason); + case BT_CONN_DISCONNECT: + return 0; + case BT_CONN_DISCONNECTED: + default: + return -ENOTCONN; + } +} + +static bool valid_adv_params(const struct nble_gap_adv_params *params) +{ + 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 { + return false; + } + + if (params->interval_min > params->interval_max) + return false; + + if (params->interval_max > 0x4000) + return false; + + return true; +} + +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 = { + .interval_max = param->interval_max, + .interval_min = param->interval_min, + .type = param->type, + .timeout = 0, + .filter_policy = 0 + }; + + bt_addr_le_copy(¶ms.peer_bda, peer); + + if (!valid_adv_params(¶ms)) { + return NULL; + } + + if (param->type == BT_LE_ADV_DIRECT_IND_LOW_DUTY) { + params.type = BT_LE_ADV_DIRECT_IND; + } + + if (atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { + return NULL; + } + + conn = bt_conn_add_le(¶ms.peer_bda); + + if (!conn) { + return NULL; + } + + bt_conn_set_state(conn, BT_CONN_CONNECT); + + nble_gap_set_adv_params_req(¶ms); + nble_gap_start_adv_req(); + + 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) +{ + struct bt_conn *conn = params->user_data; + + /* If the connection request was not issued successfully */ + if (params->status) { + conn->err = BT_HCI_ERR_UNACCEPT_CONN_PARAMS; + bt_conn_set_state(conn, BT_CONN_DISCONNECTED); + } +} + +struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer, + const struct bt_le_conn_param *param) +{ + struct bt_conn *conn; + + 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; */ + + conn = bt_conn_lookup_addr_le(peer); + if (conn) { + switch (conn->state) { + case BT_CONN_CONNECT_SCAN: + bt_conn_set_param_le(conn, param); + return conn; + case BT_CONN_CONNECT: + case BT_CONN_CONNECTED: + return conn; + default: + bt_conn_unref(conn); + return NULL; + } + } + + 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_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); + +done: + return conn; +} +#else + +void on_nble_gap_connect_rsp(const struct nble_response *params) +{ +} + +#endif /* CONFIG_BLUETOOTH_CENTRAL */ + +int bt_conn_le_param_update(struct bt_conn *conn, const struct bt_le_conn_param *param) +{ + return bt_conn_update_param_le(conn, param); +} + +#if defined(CONFIG_BLUETOOTH_SMP) || defined(CONFIG_BLUETOOTH_BREDR) +uint8_t bt_conn_enc_key_size(struct bt_conn *conn) +{ + return 0; +} + +int bt_conn_auth_cb_register(const struct bt_conn_auth_cb *cb) +{ + if (!cb) { + bt_auth = NULL; + return 0; + } + + /* cancel callback should always be provided */ + if (!cb->cancel) { + return -EINVAL; + } + + if (bt_auth) { + return -EALREADY; + } + + bt_auth = cb; + return 0; +} + +#if defined(CONFIG_BLUETOOTH_BREDR) +static int pin_code_neg_reply(const bt_addr_t *bdaddr) +{ + struct bt_hci_cp_pin_code_neg_reply *cp; + struct net_buf *buf; + + BT_DBG(""); + + buf = bt_hci_cmd_create(BT_HCI_OP_PIN_CODE_NEG_REPLY, sizeof(*cp)); + if (!buf) { + return -ENOBUFS; + } + + cp = net_buf_add(buf, sizeof(*cp)); + bt_addr_copy(&cp->bdaddr, bdaddr); + + return bt_hci_cmd_send_sync(BT_HCI_OP_PIN_CODE_NEG_REPLY, buf, NULL); +} + +static int pin_code_reply(struct bt_conn *conn, const char *pin, uint8_t len) +{ + struct bt_hci_cp_pin_code_reply *cp; + struct net_buf *buf; + + BT_DBG(""); + + buf = bt_hci_cmd_create(BT_HCI_OP_PIN_CODE_REPLY, sizeof(*cp)); + if (!buf) { + return -ENOBUFS; + } + + cp = net_buf_add(buf, sizeof(*cp)); + + bt_addr_copy(&cp->bdaddr, &conn->br.dst); + cp->pin_len = len; + strncpy(cp->pin_code, pin, sizeof(cp->pin_code)); + + return bt_hci_cmd_send_sync(BT_HCI_OP_PIN_CODE_REPLY, buf, NULL); +} + +int bt_conn_auth_pincode_entry(struct bt_conn *conn, const char *pin) +{ + size_t len; + + if (!bt_auth) { + return -EINVAL; + } + + if (conn->type != BT_CONN_TYPE_BR) { + return -EINVAL; + } + + len = strlen(pin); + if (len > 16) { + return -EINVAL; + } + + if (conn->required_sec_level == BT_SECURITY_HIGH && len < 16) { + BT_WARN("PIN code for %s is not 16 bytes wide", + bt_addr_str(&conn->br.dst)); + return -EPERM; + } + + return pin_code_reply(conn, pin, len); +} + +void bt_conn_pin_code_req(struct bt_conn *conn) +{ + if (bt_auth && bt_auth->pincode_entry) { + bool secure = false; + + if (conn->required_sec_level == BT_SECURITY_HIGH) { + secure = true; + } + + bt_auth->pincode_entry(conn, secure); + } else { + pin_code_neg_reply(&conn->br.dst); + } + +} +#endif /* CONFIG_BLUETOOTH_BREDR */ + +int bt_conn_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey) +{ + if (!bt_auth) { + return -EINVAL; + } +#if defined(CONFIG_BLUETOOTH_SMP) + if (conn->type == BT_CONN_TYPE_LE) { + return bt_smp_auth_passkey_entry(conn, passkey); + } +#endif /* CONFIG_BLUETOOTH_SMP */ + + return -EINVAL; +} + +int bt_conn_auth_passkey_confirm(struct bt_conn *conn, bool match) +{ + 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); + } +#endif /* CONFIG_BLUETOOTH_SMP */ + + return -EINVAL; +} + +int bt_conn_auth_cancel(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_cancel(conn); + } +#endif /* CONFIG_BLUETOOTH_SMP */ +#if defined(CONFIG_BLUETOOTH_BREDR) + if (conn->type == BT_CONN_TYPE_BR) { + return pin_code_neg_reply(&conn->br.dst); + } +#endif /* CONFIG_BLUETOOTH_BREDR */ + + return -EINVAL; +} + +int bt_conn_remove_info(const bt_addr_le_t *addr) +{ + struct bt_conn *conn; + + /* TODO: implement address specific removal */ + if (bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) + 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); +} +#endif /* CONFIG_BLUETOOTH_SMP || CONFIG_BLUETOOTH_BREDR */ + +int bt_conn_init(void) +{ + int err; +#if NOT_USED_FOR_NOW + + net_buf_pool_init(frag_pool); + net_buf_pool_init(dummy_pool); + + bt_att_init(); +#endif + + err = bt_smp_init(); + if (err) { + return err; + } + +#if NOT_USED_FOR_NOW + bt_l2cap_init(); + + background_scan_init(); +#endif + return 0; +} + +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; +#if 0 + struct hci_cp_le_conn_update *conn_update; + struct net_buf *buf; + + buf = bt_hci_cmd_create(BT_HCI_OP_LE_CONN_UPDATE, + sizeof(*conn_update)); + if (!buf) { + return -ENOBUFS; + } + + conn_update = net_buf_add(buf, sizeof(*conn_update)); + memset(conn_update, 0, sizeof(*conn_update)); + conn_update->handle = sys_cpu_to_le16(conn->handle); + conn_update->conn_interval_min = sys_cpu_to_le16(param->interval_min); + conn_update->conn_interval_max = sys_cpu_to_le16(param->interval_max); + 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; + + nble_gap_conn_update_req(&ble_gap_connect_update); + + 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 new file mode 100644 index 00000000..04c08839 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble/conn_internal.h @@ -0,0 +1,125 @@ +/* + * 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. + */ + +typedef enum { + BT_CONN_DISCONNECTED, + BT_CONN_CONNECT_SCAN, + BT_CONN_CONNECT, + BT_CONN_CONNECTED, + BT_CONN_DISCONNECT, +} bt_conn_state_t; + +/* bt_conn flags: the flags defined here represent connection parameters */ +enum { + BT_CONN_AUTO_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; + + uint16_t latency; + uint16_t timeout; +#if 0 + uint8_t features[8]; +#endif +}; + +#if defined(CONFIG_BLUETOOTH_BREDR) +struct bt_conn_br { + bt_addr_t dst; +}; +#endif + +struct bt_conn { + uint16_t handle; + uint8_t type; + uint8_t role; + +#if defined(CONFIG_BLUETOOTH_SMP) + uint8_t encrypt; + bt_security_t sec_level; + bt_security_t required_sec_level; +#endif /* CONFIG_BLUETOOTH_SMP */ + + atomic_t ref; + + /* Connection error or reason for disconnect */ + uint8_t err; + + bt_conn_state_t state; + union { + struct bt_conn_le le; +#if defined(CONFIG_BLUETOOTH_BREDR) + struct bt_conn_br br; +#endif + }; +}; + +/* Add a new LE connection */ +struct bt_conn *bt_conn_add_le(const bt_addr_le_t *peer); + +#if defined(CONFIG_BLUETOOTH_BREDR) +/* Add a new BR/EDR connection */ +struct bt_conn *bt_conn_add_br(const bt_addr_t *peer); + +/* Look up an existing connection by BT address */ +struct bt_conn *bt_conn_lookup_addr_br(const bt_addr_t *peer); +#endif + +/* Look up an existing connection */ +struct bt_conn *bt_conn_lookup_handle(uint16_t handle); + +/* Look up a connection state. For BT_ADDR_LE_ANY, returns the first connection + * with the specific state + */ +struct bt_conn *bt_conn_lookup_state_le(const bt_addr_le_t *peer, + const bt_conn_state_t state); + +/* Set connection object in certain state and perform action related to state */ +void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state); + +void bt_conn_set_param_le(struct bt_conn *conn, + const struct bt_le_conn_param *param); + +int bt_conn_update_param_le(struct bt_conn *conn, + const struct bt_le_conn_param *param); + +int bt_conn_le_conn_update(struct bt_conn *conn, + const struct bt_le_conn_param *param); + +void notify_le_param_updated(struct bt_conn *conn); + +#if defined(CONFIG_BLUETOOTH_SMP) +/* rand and ediv should be in BT order */ +int bt_conn_le_start_encryption(struct bt_conn *conn, uint64_t rand, + uint16_t ediv, const uint8_t *ltk, size_t len); + +/* Notify higher layers that RPA was resolved */ +void bt_conn_identity_resolved(struct bt_conn *conn); + +/* Notify higher layers that connection security changed */ +void bt_conn_security_changed(struct bt_conn *conn); +#endif /* CONFIG_BLUETOOTH_SMP */ +/* Initialize connection management */ +int bt_conn_init(void); diff --git a/system/libarc32_arduino101/framework/src/services/ble/dtm_tcmd.c b/system/libarc32_arduino101/framework/src/services/ble/dtm_tcmd.c new file mode 100644 index 00000000..4a0c5b0c --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble/dtm_tcmd.c @@ -0,0 +1,12 @@ + +#include +#include "uart.h" +#include "ipc_uart_ns16550.h" + +void on_nble_gap_dtm_init_rsp(void *user_data) +{ +#ifdef CONFIG_UART_NS16550 + uart_ipc_disable(); +#endif +} + diff --git a/system/libarc32_arduino101/framework/src/services/ble/gap.c b/system/libarc32_arduino101/framework/src/services/ble/gap.c new file mode 100644 index 00000000..4cf71d47 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble/gap.c @@ -0,0 +1,912 @@ +/* + * 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 "gap_internal.h" +#include "conn_internal.h" + +#include "hci_core.h" + +#if defined(CONFIG_BLUETOOTH_SMP) +#include "smp.h" +#endif /* CONFIG_BLUETOOTH_SMP */ + +/* #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_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_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; + +struct bt_dev bt_dev; + +static int set_advertise_enable(void) +{ +#if 0 + struct net_buf *buf; + int err; +#endif + if (atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { + return 0; + } +#if 0 + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_ENABLE, 1); + if (!buf) { + return -ENOBUFS; + } + + net_buf_add_u8(buf, BT_HCI_LE_ADV_ENABLE); + err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_ADV_ENABLE, buf, NULL); + if (err) { + return err; + } +#endif + nble_gap_start_adv_req(); + + return 0; +} + +static int set_advertise_disable(void) +{ +#if 0 + struct net_buf *buf; + int err; +#endif + if (!atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) { + return 0; + } +#if 0 + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_ENABLE, 1); + if (!buf) { + return -ENOBUFS; + } + + net_buf_add_u8(buf, BT_HCI_LE_ADV_DISABLE); + err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_ADV_ENABLE, buf, NULL); + if (err) { + return err; + } +#endif + nble_gap_stop_adv_req(NULL); + + atomic_clear_bit(bt_dev.flags, BT_DEV_ADVERTISING); + return 0; +} + +void ble_gap_get_bonding_info(ble_bond_info_cb_t func, void *user_data, + bool include_bonded_addrs) +{ + 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); +} + +void on_nble_gap_start_advertise_rsp(const struct nble_response *params) +{ + if (params->status == 0) + atomic_set_bit(bt_dev.flags, BT_DEV_ADVERTISING); + else + BT_WARN("start advertise failed with %d", params->status); +} + +void on_nble_gap_disconnect_evt(const struct nble_gap_disconnect_evt *evt) +{ + struct bt_conn *conn; + +#if 0 + /* Nordic has no disconnection error */ + if (evt->status) { + return; + } +#endif + + conn = bt_conn_lookup_handle(evt->conn_handle); + if (!conn) { + BT_DBG("Unable to look up conn with handle %u", + evt->conn_handle); + return; + } +#if 0 + /* Check stacks usage (no-ops if not enabled) */ + stack_analyze("rx stack", rx_fiber_stack, sizeof(rx_fiber_stack)); + stack_analyze("cmd rx stack", rx_prio_fiber_stack, + sizeof(rx_prio_fiber_stack)); + stack_analyze("cmd tx stack", cmd_tx_fiber_stack, + sizeof(cmd_tx_fiber_stack)); + stack_analyze("conn tx stack", conn->stack, sizeof(conn->stack)); + +#endif + + conn->err = evt->hci_reason; + bt_conn_set_state(conn, BT_CONN_DISCONNECTED); + conn->handle = 0; + +#if 0 + /* Only LE supported */ + if (conn->type != BT_CONN_TYPE_LE) { + bt_conn_unref(conn); + return; + } + /* TODO enabled when autoconn is supported */ + if (atomic_test_bit(conn->flags, BT_CONN_AUTO_CONNECT)) { + bt_conn_set_state(conn, BT_CONN_CONNECT_SCAN); + bt_le_scan_update(false); + } +#endif + + bt_conn_unref(conn); + if (atomic_test_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING)) { + set_advertise_enable(); + } +} + +void on_nble_gap_connect_evt(const struct nble_gap_connect_evt *evt) +{ + struct bt_conn *conn; + + /* Make lookup to check if there's a connection object in CONNECT state + * associated with passed peer LE address. + */ + conn = bt_conn_lookup_state_le(&evt->peer_bda, BT_CONN_CONNECT); + +#if 0 + /* Nordic has no connection error */ + if (evt->status) { + if (!conn) { + return; + } + + conn->err = BT_HCI_ERR_UNACCEPT_CONN_PARAMS; + bt_conn_set_state(conn, BT_CONN_DISCONNECTED); + + /* Drop the reference got by lookup call in CONNECT state. + * We are now in DISCONNECTED state since no successful LE + * link been made. + */ + bt_conn_unref(conn); + + return; + } +#endif + /* + * clear advertising even if we are not able to add connection object + * to keep host in sync with controller state + */ + if (evt->role_slave == BT_CONN_ROLE_SLAVE) { + atomic_clear_bit(bt_dev.flags, BT_DEV_ADVERTISING); + } + + if (!conn) { + conn = bt_conn_add_le(&evt->peer_bda); + } + + if (!conn) { + BT_DBG("Unable to add new conn for handle %u", + evt->conn_handle); + return; + } + + conn->handle = evt->conn_handle; + bt_addr_le_copy(&conn->le.dst, &evt->peer_bda); + conn->le.interval = evt->conn_values.interval; + conn->le.latency = evt->conn_values.latency; + 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); + } else { + bt_addr_le_copy(&conn->le.init_addr, &evt->peer_addr); + bt_addr_le_copy(&conn->le.resp_addr, &src); + } +#endif + bt_conn_set_state(conn, BT_CONN_CONNECTED); + + /* Note: Connection update removed because Windows interop and BT spec recommendations */ + + bt_conn_unref(conn); +#if 0 + 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) +{ +#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; + uint16_t handle, interval; + + handle = evt->conn_handle; + interval = evt->conn_values.interval; + +/* BT_DBG("status %u, handle %u", evt->status, handle); */ + + conn = bt_conn_lookup_handle(handle); + if (!conn) { +/* BT_ERR("Unable to lookup conn for handle %u", handle); */ + return; + } + +/* if (!evt->status) { */ + conn->le.interval = interval; + conn->le.latency = evt->conn_values.latency; + conn->le.timeout = evt->conn_values.supervision_to; + notify_le_param_updated(conn); +/* } */ + + + bt_conn_unref(conn); +} + +void bt_conn_set_param_le(struct bt_conn *conn, + const struct bt_le_conn_param *param) +{ + conn->le.interval_min = param->interval_min; + conn->le.interval_max = param->interval_max; + conn->le.latency = param->latency; + conn->le.timeout = param->timeout; +} +int bt_conn_update_param_le(struct bt_conn *conn, + const struct bt_le_conn_param *param) +{ +#if 0 + BT_DBG("conn %p features 0x%x params (%d-%d %d %d)", conn, + conn->le.features[0], param->interval_min, param->interval_max, + param->latency, param->timeout); +#endif + /* Check if there's a need to update conn params */ + if (conn->le.interval >= param->interval_min && + conn->le.interval <= param->interval_max) { + return -EALREADY; + } +#if 0 + if ((conn->role == BT_HCI_ROLE_SLAVE) && + !(bt_dev.le.features[0] & BT_HCI_LE_CONN_PARAM_REQ_PROC)) { + return bt_l2cap_update_conn_param(conn, param); + } + + if ((conn->le.features[0] & BT_HCI_LE_CONN_PARAM_REQ_PROC) && + (bt_dev.le.features[0] & BT_HCI_LE_CONN_PARAM_REQ_PROC)) { +#endif + return bt_conn_le_conn_update(conn, param); +#if 0 + } + return -EBUSY; +#endif +} + +void on_nble_gap_scan_start_stop_rsp(const struct nble_response *rsp) +{ + 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) */ +} + +static int bt_hci_stop_scanning(void) +{ +#ifdef NOT_USED_FOR_NOW + struct net_buf *buf, *rsp; + struct bt_hci_cp_le_set_scan_enable *scan_enable; + int err; + + if (!atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING)) { + return -EALREADY; + } + + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_SCAN_ENABLE, + sizeof(*scan_enable)); + if (!buf) { + return -ENOBUFS; + } + + scan_enable = net_buf_add(buf, sizeof(*scan_enable)); + memset(scan_enable, 0, sizeof(*scan_enable)); + scan_enable->filter_dup = BT_HCI_LE_SCAN_FILTER_DUP_DISABLE; + scan_enable->enable = BT_HCI_LE_SCAN_DISABLE; + + err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_SCAN_ENABLE, buf, &rsp); + if (err) { + return err; + } + + /* Update scan state in case of success (0) status */ + err = rsp->data[0]; + if (!err) { + atomic_clear_bit(bt_dev.flags, BT_DEV_SCANNING); + } + + net_buf_unref(rsp); + + return err; +#endif + + nble_gap_stop_scan_req(); + + return 0; +} + +#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 */ + + +static int start_le_scan(uint8_t scan_type, uint16_t interval, uint16_t window, + uint8_t filter_dup) +{ + struct nble_gap_scan_params params = { + .interval = interval, + .window = window, + .scan_type = scan_type, + }; + +#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; + + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_SCAN_PARAMS, + sizeof(*set_param)); + if (!buf) { + return -ENOBUFS; + } + + + set_param = net_buf_add(buf, sizeof(*set_param)); + memset(set_param, 0, sizeof(*set_param)); + set_param->scan_type = scan_type; + + /* 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 (scan_type == BT_HCI_LE_SCAN_ACTIVE) { + err = le_set_nrpa(); + if (err) { + net_buf_unref(buf); + return err; + } + + set_param->addr_type = BT_ADDR_LE_RANDOM; + } else { + set_param->addr_type = BT_ADDR_LE_PUBLIC; + } + + 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; + } + + 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; + + err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_SCAN_ENABLE, buf, &rsp); + 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); + } + + net_buf_unref(rsp); +#endif + + 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) +{ +#if defined(CONFIG_BLUETOOTH_CENTRAL) + uint16_t interval, window; + struct bt_conn *conn; +#endif /* CONFIG_BLUETOOTH_CENTRAL */ + + if (atomic_test_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) { + return 0; + } + + if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING)) { + int err; + + err = bt_hci_stop_scanning(); + if (err) { + return err; + } + } + +#if defined(CONFIG_BLUETOOTH_CENTRAL) + conn = bt_conn_lookup_state_le(NULL, BT_CONN_CONNECT_SCAN); + if (!conn) { + return 0; + } + + bt_conn_unref(conn); + + if (fast_scan) { + interval = BT_GAP_SCAN_FAST_INTERVAL; + window = BT_GAP_SCAN_FAST_WINDOW; + } else { + interval = BT_GAP_SCAN_SLOW_INTERVAL_1; + window = BT_GAP_SCAN_SLOW_WINDOW_1; + } + + return start_le_scan(BT_HCI_LE_SCAN_PASSIVE, interval, window, 0x01); +#else + return 0; +#endif /* CONFIG_BLUETOOTH_CENTRAL */ +} +#endif + +static int bt_init(void) +{ +#if NOT_USED_FOR_NOW + struct bt_driver *drv = bt_dev.drv; +#endif + int err = 0; + +#if NOT_USED_FOR_NOW + err = drv->open(); + if (err) { + BT_ERR("HCI driver open failed (%d)", err); + return err; + } + + err = hci_init(); +#endif + + if (!err) { + err = bt_conn_init(); + } + + scan_dev_found_cb = NULL; + if (!err) { + atomic_set_bit(bt_dev.flags, BT_DEV_READY); +#if 0 + bt_le_scan_update(false); +#endif + } + + return err; +} + +void on_nble_up(void) +{ + BT_DBG("%s", __FUNCTION__); + if (bt_ready_cb) + bt_ready_cb(bt_init()); +} + +extern void on_nble_curie_init(void); + +int bt_enable(bt_ready_cb_t cb) +{ + bt_ready_cb = cb; + + on_nble_curie_init(); + + if (!cb) { + return bt_init(); + } + + return 0; +} + + +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->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, + const struct bt_data *ad, size_t ad_len) +{ + int i; + + for (i = 0; i < ad_len; i++) { + /* Check if ad fit in the remaining buffer */ + if (p_ad_data->len + ad[i].data_len + 2 > 31) { + return -EINVAL; + } + + p_ad_data->data[p_ad_data->len++] = ad[i].data_len + 1; + p_ad_data->data[p_ad_data->len++] = ad[i].type; + + memcpy(&p_ad_data->data[p_ad_data->len], ad[i].data, + ad[i].data_len); + p_ad_data->len += ad[i].data_len; + } + + return 0; +} + +int bt_le_adv_start(const struct bt_le_adv_param *param, + const struct bt_data *ad, size_t ad_len, + 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; + + 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; + } + + err = set_advertise_disable(); + if (err) { + return err; + } + err = set_ad(&data.ad, ad, ad_len); + if (err) { + return err; + } + + /* + * Don't bother with scan response if the advertising type isn't + * a scannable one. + */ + if (param->type == BT_LE_ADV_IND || param->type == BT_LE_ADV_SCAN_IND) { + err = set_ad(&data.sd, sd, sd_len); + if (err) { + return err; + } + } + nble_gap_set_adv_data_req(&data); + + /* Timeout is handled by application timer */ + set_param.timeout = 0; + /* forced to none currently (no whitelist support) */ + set_param.filter_policy = 0; + set_param.interval_max = param->interval_max; + set_param.interval_min = param->interval_min; + set_param.type = param->type; + 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); + return err; + } + + set_param->own_addr_type = BT_ADDR_LE_RANDOM; + } else { + set_param->own_addr_type = BT_ADDR_LE_PUBLIC; + } + + bt_hci_cmd_send(BT_HCI_OP_LE_SET_ADV_PARAMETERS, buf); +#endif + + err = set_advertise_enable(); + if (err) { + return err; + } + + atomic_set_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING); + + return 0; +} + +void on_nble_gap_dir_adv_timeout_evt(const struct nble_gap_dir_adv_timeout_evt *p_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; + bt_conn_set_state(conn, BT_CONN_DISCONNECTED); + bt_conn_unref(conn); + } +} + +int bt_le_adv_stop(void) +{ + int err; + + if (!atomic_test_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING)) { + return -EALREADY; + } + + err = set_advertise_disable(); + if (err) { + return err; + } + atomic_clear_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING); + + return 0; +} + +static bool valid_le_scan_param(const struct bt_le_scan_param *param) +{ + if (param->type != BT_HCI_LE_SCAN_PASSIVE && + param->type != BT_HCI_LE_SCAN_ACTIVE) { + return false; + } + + if (/* param->filter_dup != BT_HCI_LE_SCAN_FILTER_DUP_DISABLE */ + /* && nble always filters duplicates */ + param->filter_dup != BT_HCI_LE_SCAN_FILTER_DUP_ENABLE) { + return false; + } + + if (param->interval < 0x0004 || param->interval > 0x4000) { + return false; + } + + if (param->window < 0x0004 || param->window > 0x4000) { + return false; + } + + if (param->window > param->interval) { + return false; + } + + return true; +} + +int bt_le_scan_start(const struct bt_le_scan_param *param, bt_le_scan_cb_t cb) +{ + + int err; + + /* Check that the parameters have valid values */ + 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; + } + + if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING)) { + err = bt_hci_stop_scanning(); + if (err) { + atomic_clear_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN); + 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; + } + + scan_dev_found_cb = cb; + + return 0; +} + +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)) +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, + struct bt_conn *conn, + rssi_report_resp_t resp_cb, rssi_report_t evt_cb) +{ + rssi_report_cb = evt_cb; + + params->conn_handle = conn->handle; + + nble_gap_set_rssi_report_req(params, resp_cb); +} + +void on_nble_gap_set_rssi_report_rsp(const struct nble_response *params) +{ + rssi_report_resp_t resp_cb = params->user_data; + + if (resp_cb) + resp_cb(params->status); +} + +void on_nble_gap_rssi_evt(const struct nble_gap_rssi_evt *event) +{ + if (rssi_report_cb) + rssi_report_cb(event->rssi_data); +} + +void ble_gap_set_tx_power(int8_t tx_power) +{ + struct nble_gap_tx_power_params params = { + .tx_power = tx_power, + }; + nble_gap_tx_power_req(¶ms); +} + +void on_nble_gap_tx_power_rsp(const struct nble_response *params) +{ +} + +void ble_gap_get_version(ble_get_version_cb_t func) +{ + struct nble_gap_get_version_param params; + + params.cb = func; + + nble_get_version_req(¶ms); +} + +void on_nble_get_version_rsp(const struct nble_version_response *par) +{ + struct nble_gap_get_version_param param = par->params; + ble_get_version_cb_t cb = param.cb; + + if (cb) { + cb(&par->ver); + } +} + +void bt_le_set_device_name(char *device_name, int len) +{ + struct nble_gap_service_write_params gap_service_params; + if (len > 20) + len = 20; + memset(&gap_service_params, 0, sizeof(gap_service_params)); + gap_service_params.attr_type = NBLE_GAP_SVC_ATTR_NAME; + 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); +} + diff --git a/system/libarc32_arduino101/framework/src/services/ble/gatt.c b/system/libarc32_arduino101/framework/src/services/ble/gatt.c new file mode 100644 index 00000000..d3ef4c09 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble/gatt.c @@ -0,0 +1,1561 @@ +/* + * 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 +#include "gatt_internal.h" +#include "hci_core.h" +#include "conn_internal.h" + +/* #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_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_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) +#endif + +#define N_BLE_BUF_SIZE 512 + +struct ble_gatt_service { + struct bt_gatt_attr *attrs; /* Pointer to the array of attributes */ + uint16_t attr_count; /* Number of attributes in the array */ +}; + +struct ble_gatts_flush_all { + struct bt_conn *conn; + int status; + uint8_t flag; +}; + +static struct ble_gatt_service db[CONFIG_BT_GATT_BLE_MAX_SERVICES]; + +static uint8_t db_cnt; + +#if defined(CONFIG_BLUETOOTH_GATT_CLIENT) +static struct bt_gatt_subscribe_params *subscriptions; +#endif + +/** + * Copy a UUID in a buffer using the smallest memory length + * @param buf Pointer to the memory where the UUID shall be copied + * @param uuid Pointer to the UUID to copy + * @return The length required to store the UUID in the memory + */ +static uint8_t bt_gatt_uuid_memcpy(uint8_t *buf, + const struct bt_uuid *uuid) +{ + uint8_t *ptr = buf; + + /* Store the type of the UUID */ + *ptr = uuid->type; + ptr++; + + /* Store the UUID data */ + if (uuid->type == BT_UUID_TYPE_16) { + uint16_t le16; + + le16 = sys_cpu_to_le16(BT_UUID_16(uuid)->val); + memcpy(ptr, &le16, sizeof(le16)); + ptr += sizeof(le16); + } else { + memcpy(ptr, BT_UUID_128(uuid)->val, + sizeof(BT_UUID_128(uuid)->val)); + ptr += sizeof(BT_UUID_128(uuid)->val); + } + return ptr - buf; +} + +/* These attributes need the value to be read */ +static struct bt_uuid *whitelist[] = { + BT_UUID_GATT_PRIMARY, + BT_UUID_GATT_SECONDARY, + BT_UUID_GATT_INCLUDE, + BT_UUID_GATT_CHRC, + BT_UUID_GATT_CEP, + BT_UUID_GATT_CUD, + BT_UUID_GATT_CPF, + BT_UUID_GAP_DEVICE_NAME, + BT_UUID_GAP_APPEARANCE, + BT_UUID_GAP_PPCP +}; + +static int attr_read(struct bt_gatt_attr *attr, uint8_t *data, size_t len) +{ + uint8_t i; + int data_size; + + if (!data || len < 0) { + return -ENOMEM; + } + + data_size = bt_gatt_uuid_memcpy(data, attr->uuid); + + for (i = 0; i < ARRAY_SIZE(whitelist); i++) { + if (!bt_uuid_cmp(attr->uuid, whitelist[i])) { + int read; + + read = attr->read(NULL, attr, data + data_size, len, + 0); + if (read < 0) { + return read; + } + + data_size += read; + break; + } + } + + return data_size; +} + +int bt_gatt_register(struct bt_gatt_attr *attrs, size_t count) +{ + size_t attr_table_size, i; + struct nble_gatt_register_req param; + /* TODO: Replace the following with net_buf */ + uint8_t attr_table[N_BLE_BUF_SIZE]; + + if (!attrs || !count) { + return -EINVAL; + } + BT_ASSERT(db_cnt < ARRAY_SIZE(db)); + + db[db_cnt].attrs = attrs; + db[db_cnt].attr_count = count; + db_cnt++; + param.attr_base = attrs; + param.attr_count = count; + + attr_table_size = 0; + + for (i = 0; i < count; i++) { + struct bt_gatt_attr *attr = &attrs[i]; + struct ble_gatt_attr *att; + int data_size; + + if (attr_table_size + sizeof(*att) > sizeof(attr_table)) { + return -ENOMEM; + } + + att = (void *)&attr_table[attr_table_size]; + att->perm = attr->perm; + + /* Read attribute data */ + data_size = attr_read(attr, att->data, + sizeof(attr_table) - + (attr_table_size + sizeof(*att))); + if (data_size < 0) { + return data_size; + } + att->data_size = data_size; + + BT_DBG("table size = %u attr data_size = %u", attr_table_size, + att->data_size); + + /* Compute the new element size and align it on upper 4 bytes + * boundary. + */ + attr_table_size += (sizeof(*att) + att->data_size + 3) & ~3; + } + + nble_gatt_register_req(¶m, attr_table, attr_table_size); + return 0; +} + +void on_nble_gatt_register_rsp(const struct nble_gatt_register_rsp *rsp, + const struct nble_gatt_attr_handles *handles, uint8_t len) +{ + + if (rsp->status != 0) { + BT_ERR("failure registering table: %d - %u - %p", rsp->status, + rsp->attr_count, rsp->attr_base); + } +#ifdef BT_GATT_DEBUG + BT_DBG("register rsp : s=%d - b=%p - c=%u", rsp->status, + rsp->attr_base, rsp->attr_count); + { + int i; + + for (i = 0; i < rsp->attr_count; i++) { + if (handles[i].handle != 0) { + BT_DBG("gatt: i %d, h %d, type %d, u16 0x%x", + i, handles[i].handle, + rsp->attr_base[i].uuid->type, + BT_UUID_16(rsp->attr_base[i].uuid)->val); + } + } + } +#endif +} + +ssize_t bt_gatt_attr_read(struct bt_conn *conn, const struct bt_gatt_attr *attr, + void *buf, uint16_t buf_len, uint16_t offset, + const void *value, uint16_t value_len) +{ + uint16_t len; + + if (offset > value_len) { + return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET); + } + + len = min(buf_len, value_len - offset); + + BT_DBG("handle 0x%04x offset %u length %u", attr->handle, offset, + len); + + memcpy(buf, value + offset, len); + + return len; +} + +ssize_t bt_gatt_attr_read_service(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + void *buf, uint16_t len, uint16_t offset) +{ + struct bt_uuid *uuid = attr->user_data; + + if (uuid->type == BT_UUID_TYPE_16) { + uint16_t uuid16 = sys_cpu_to_le16(BT_UUID_16(uuid)->val); + + return bt_gatt_attr_read(conn, attr, buf, len, offset, + &uuid16, 2); + } + + return bt_gatt_attr_read(conn, attr, buf, len, offset, + 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; + + 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) { + pdu.uuid16 = sys_cpu_to_le16(BT_UUID_16(incl->uuid)->val); + value_len += sizeof(pdu.uuid16); + } + + return bt_gatt_attr_read(conn, attr, buf, len, offset, &pdu, value_len); +} + +struct gatt_chrc { + uint8_t properties; + uint16_t value_handle; + union { + uint16_t uuid16; + uint8_t uuid[16]; + }; +} __packed; + +ssize_t bt_gatt_attr_read_chrc(struct bt_conn *conn, + const struct bt_gatt_attr *attr, void *buf, + uint16_t len, uint16_t offset) +{ + struct bt_gatt_chrc *chrc = attr->user_data; + struct gatt_chrc pdu; + uint8_t value_len; + + pdu.properties = chrc->properties; + /* BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part G] page 534: + * 3.3.2 Characteristic Value Declaration + * The Characteristic Value declaration contains the value of the + * characteristic. It is the first Attribute after the characteristic + * declaration. All characteristic definitions shall have a + * Characteristic Value declaration. + */ +#if 0 + next = bt_gatt_attr_next(attr); + if (!next) { + BT_WARN("No value for characteristic at 0x%04x", attr->handle); + pdu.value_handle = 0x0000; + } else { + pdu.value_handle = sys_cpu_to_le16(next->handle); + } +#else + pdu.value_handle = 0x0000; +#endif + value_len = sizeof(pdu.properties) + sizeof(pdu.value_handle); + + if (chrc->uuid->type == BT_UUID_TYPE_16) { + 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); + value_len += 16; + } + + return bt_gatt_attr_read(conn, attr, buf, len, offset, &pdu, value_len); +} + +void bt_gatt_foreach_attr(uint16_t start_handle, uint16_t end_handle, + bt_gatt_attr_func_t func, void *user_data) +{ + + const struct bt_gatt_attr *attr; + + BT_ASSERT(start_handle == 1 && end_handle == 0xFFFF); + + for (attr = db[0].attrs; attr; attr = bt_gatt_attr_next(attr)) { +#if 0 + /* Check if attribute handle is within range */ + if (attr->handle < start_handle || attr->handle > end_handle) { + continue; + } +#endif + + if (func(attr, user_data) == BT_GATT_ITER_STOP) { + break; + } + } +} + +struct bt_gatt_attr *bt_gatt_attr_next(const struct bt_gatt_attr *attr) +{ + struct ble_gatt_service *svc, *svc_last; + + svc_last = &db[db_cnt]; + + for (svc = db; svc < svc_last; svc++) { + if (attr >= svc->attrs && attr < &svc->attrs[svc->attr_count]) { + int index = attr - &svc->attrs[0]; + + if (index < (svc->attr_count - 1)) { + return (struct bt_gatt_attr *)&attr[1]; + } else if ((svc + 1) < svc_last) { + return (svc + 1)->attrs; + } else { + return NULL; + } + } + } + /* Normally, we should not reach here */ + return NULL; +} + +ssize_t bt_gatt_attr_read_ccc(struct bt_conn *conn, + const struct bt_gatt_attr *attr, void *buf, + uint16_t len, uint16_t offset) +{ + return BT_GATT_ERR(BT_ATT_ERR_NOT_SUPPORTED); + +#if 0 + struct _bt_gatt_ccc *ccc = attr->user_data; + uint16_t value; + size_t i; + + for (i = 0; i < ccc->cfg_len; i++) { + if (bt_addr_le_cmp(&ccc->cfg[i].peer, &conn->le.dst)) { + continue; + } + + value = sys_cpu_to_le16(ccc->cfg[i].value); + break; + } + + /* Default to disable if there is no cfg for the peer */ + if (i == ccc->cfg_len) { + value = 0x0000; + } + + return bt_gatt_attr_read(conn, attr, buf, len, offset, &value, + sizeof(value)); +#endif +} + +static void gatt_ccc_changed(struct _bt_gatt_ccc *ccc) +{ + int i; + uint16_t value = 0x0000; + + for (i = 0; i < ccc->cfg_len; i++) { + if (ccc->cfg[i].value > value) { + value = ccc->cfg[i].value; + } + } + + BT_DBG("ccc %p value 0x%04x", ccc, value); + + if (value != ccc->value) { + ccc->value = value; + if (ccc->cfg_changed) + ccc->cfg_changed(value); + } +} + +#if defined(CONFIG_BLUETOOTH_GATT_CLIENT) +static bool is_bonded(const bt_addr_le_t *addr) +{ +#if defined(CONFIG_BLUETOOTH_SMP) + struct bt_conn *conn = bt_conn_lookup_addr_le(addr); + + /* + * this is a temporary workaround. if encrypt is set, we know we are + * paired. nble does not yet report if device is bonded. + */ + if (conn) { + uint8_t encrypt = conn->encrypt; + + bt_conn_unref(conn); + + return encrypt; + } + return false; +#else + return false; +#endif /* defined(CONFIG_BLUETOOTH_SMP) */ +} +#endif + +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) +{ + 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)) { + break; + } + } + + //BT_DBG("%s3", __FUNCTION__); + + if (i == ccc->cfg_len) { + for (i = 0; i < ccc->cfg_len; i++) { + /* Check for unused configuration */ + if (!ccc->cfg[i].valid) { + bt_addr_le_copy(&ccc->cfg[i].peer, &conn->le.dst); +#if NOT_USED_FOR_THE_TIME_BEING + /* Only set valid if bonded */ + ccc->cfg[i].valid = is_bonded(&conn->le.dst); +#endif + break; + } + } + + if ((i == ccc->cfg_len) && (ccc->cfg_len)) { + BT_WARN("No space to store CCC cfg"); + return -ENOMEM; + } + } + + //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); + + /* Update cfg if don't match */ + if (ccc->value != *data) { + gatt_ccc_changed(ccc); + } + + return len; +} + +ssize_t bt_gatt_attr_read_cep(struct bt_conn *conn, + const struct bt_gatt_attr *attr, void *buf, + uint16_t len, uint16_t offset) +{ + struct bt_gatt_cep *value = attr->user_data; + uint16_t props = sys_cpu_to_le16(value->properties); + + return bt_gatt_attr_read(conn, attr, buf, len, offset, &props, + sizeof(props)); +} + +ssize_t bt_gatt_attr_read_cud(struct bt_conn *conn, + const struct bt_gatt_attr *attr, void *buf, + uint16_t len, uint16_t offset) +{ + char *value = attr->user_data; + + return bt_gatt_attr_read(conn, attr, buf, len, offset, value, strlen(value)); +} + +ssize_t bt_gatt_attr_read_cpf(struct bt_conn *conn, + const struct bt_gatt_attr *attr, void *buf, + uint16_t len, uint16_t offset) +{ + struct bt_gatt_cpf *value = attr->user_data; + + return bt_gatt_attr_read(conn, attr, buf, len, offset, value, + sizeof(*value)); +} + +struct notify_data { + uint16_t state; + uint16_t type; + const struct bt_gatt_attr *attr; + const void *data; + uint16_t len; + bt_gatt_notify_sent_func_t notify_cb; + struct bt_gatt_indicate_params *params; +}; + +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; + + notif.conn_handle = conn->handle; + notif.params.attr = attr; + notif.params.offset = 0; + notif.cback = cb; + + nble_gatt_send_notif_req(¬if, data, len); + + return 0; +} + +void on_nble_gatts_send_notif_rsp(const struct nble_gatt_notif_rsp *rsp) +{ + struct bt_conn *conn; + + conn = bt_conn_lookup_handle(rsp->conn_handle); + + if (conn) { + if (rsp->cback) { + rsp->cback(conn, rsp->attr, rsp->status); + } + bt_conn_unref(conn); + } +} + +void on_nble_gatts_send_ind_rsp(const struct nble_gatt_ind_rsp *rsp) +{ + struct bt_conn *conn; + + conn = bt_conn_lookup_handle(rsp->conn_handle); + + if (conn) { + if (rsp->cback) { + rsp->cback(conn, rsp->attr, rsp->status); + } + bt_conn_unref(conn); + } +} + +static int att_indicate(struct bt_conn *conn, + struct bt_gatt_indicate_params *params) +{ + struct nble_gatt_send_ind_params ind; + + ind.conn_handle = conn->handle; + ind.cback = params->func; + ind.params.attr = params->attr; + ind.params.offset = 0; + + nble_gatt_send_ind_req(&ind, params->data, params->len); + + return 0; +} + +static uint8_t notify_cb(const struct bt_gatt_attr *attr, void *user_data) +{ + struct notify_data *data = user_data; + struct _bt_gatt_ccc *ccc; + size_t i; + + /* Check if the attribute was reached */ + if (data->state == 0) { + if (attr == data->attr) + data->state = 1; + return BT_GATT_ITER_CONTINUE; + } + + if (bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CCC)) { + /* Stop if we reach the next characteristic */ + if (!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CHRC)) { + return BT_GATT_ITER_STOP; + } + return BT_GATT_ITER_CONTINUE; + } + + /* Check attribute user_data must be of type struct _bt_gatt_ccc */ + if (attr->write != bt_gatt_attr_write_ccc) { + return BT_GATT_ITER_CONTINUE; + } + + ccc = attr->user_data; + + /* Notify all peers configured */ + for (i = 0; i < ccc->cfg_len; i++) { + struct bt_conn *conn; + int err; + + if (ccc->value != data->type) { + continue; + } + + conn = bt_conn_lookup_addr_le(&ccc->cfg[i].peer); + if (!conn || conn->state != BT_CONN_CONNECTED) {//Bug here + continue; + } + + if (data->type == BT_GATT_CCC_INDICATE) { + err = att_indicate(conn, data->params); + + } else { + err = att_notify(conn, data->attr, data->data, + data->len, data->notify_cb); + } + + bt_conn_unref(conn); + + if (err < 0) { + return BT_GATT_ITER_STOP; + } + } + + return BT_GATT_ITER_CONTINUE; +} + +int bt_gatt_notify(struct bt_conn *conn, const struct bt_gatt_attr *attr, + const void *data, uint16_t len, + bt_gatt_notify_sent_func_t cb) +{ + struct notify_data nfy; + + if (!attr) { + return -EINVAL; + } + + if (conn) { + return att_notify(conn, attr, data, len, cb); + } + + nfy.state = 0; + nfy.attr = attr; + nfy.type = BT_GATT_CCC_NOTIFY; + nfy.data = data; + nfy.len = len; + nfy.notify_cb = cb; + + bt_gatt_foreach_attr(1, 0xffff, notify_cb, &nfy); + + return 0; +} + +int bt_gatt_indicate(struct bt_conn *conn, + struct bt_gatt_indicate_params *params) +{ + struct notify_data nfy; + + if (!params || !params->attr) { + return -EINVAL; + } + + if (conn) { + return att_indicate(conn, params); + } + + nfy.state = 0; + nfy.type = BT_GATT_CCC_INDICATE; + nfy.params = params; + + bt_gatt_foreach_attr(1, 0xffff, notify_cb, &nfy); + + return 0; +} + +static uint8_t connected_cb(const struct bt_gatt_attr *attr, void *user_data) +{ + struct bt_conn *conn = user_data; + struct _bt_gatt_ccc *ccc; + size_t i; + + /* Check attribute user_data must be of type struct _bt_gatt_ccc */ + if (attr->write != bt_gatt_attr_write_ccc) { + return BT_GATT_ITER_CONTINUE; + } + + ccc = attr->user_data; + + /* If already enabled skip */ + if (ccc->value) { + return BT_GATT_ITER_CONTINUE; + } + + for (i = 0; i < ccc->cfg_len; i++) { + /* Ignore configuration for different peer */ + if (bt_addr_le_cmp(&conn->le.dst, &ccc->cfg[i].peer)) { + continue; + } + + if (ccc->cfg[i].value) { + gatt_ccc_changed(ccc); + return BT_GATT_ITER_CONTINUE; + } + } + + return BT_GATT_ITER_CONTINUE; +} + +static uint8_t disconnected_cb(const struct bt_gatt_attr *attr, void *user_data) +{ + struct bt_conn *conn = user_data; + struct _bt_gatt_ccc *ccc; + size_t i; + + /* Check attribute user_data must be of type struct _bt_gatt_ccc */ + if (attr->write != bt_gatt_attr_write_ccc) { + return BT_GATT_ITER_CONTINUE; + } + + ccc = attr->user_data; + + /* If already disabled skip */ + if (!ccc->value) { + return BT_GATT_ITER_CONTINUE; + } + + for (i = 0; i < ccc->cfg_len; i++) { + /* Ignore configurations with disabled value */ + if (!ccc->cfg[i].value) { + continue; + } + + if (bt_addr_le_cmp(&conn->le.dst, &ccc->cfg[i].peer)) { + struct bt_conn *tmp; + + /* Skip if there is another peer connected */ + tmp = bt_conn_lookup_addr_le(&ccc->cfg[i].peer); + if (tmp) { + if (tmp->state == BT_CONN_CONNECTED) { + bt_conn_unref(tmp); + return BT_GATT_ITER_CONTINUE; + } + + bt_conn_unref(tmp); + } + } + } + + /* Reset value while disconnected */ + memset(&ccc->value, 0, sizeof(ccc->value)); + + if (ccc->cfg_changed) { + ccc->cfg_changed(ccc->value); + } + + BT_DBG("ccc %p reseted", ccc); + + return BT_GATT_ITER_CONTINUE; +} + +void on_nble_gatts_write_evt(const struct nble_gatt_wr_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; + + //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); + + 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__); + + goto reply; + } + + //BT_DBG("%s1", __FUNCTION__); + + /* 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); + + 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; + + nble_gatts_wr_reply_req(&reply_data); + } + + if (conn) + bt_conn_unref(conn); +} + +static uint8_t flush_all(const struct bt_gatt_attr *attr, void *user_data) +{ + 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; + } + + return BT_GATT_ITER_CONTINUE; +} + +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, + }; + + bt_gatt_foreach_attr(0x0001, 0xFFFF, flush_all, &flush_data); + + struct nble_gatts_wr_reply_params reply_data = { + .conn_handle = evt->conn_handle, + .status = flush_data.status, + }; + nble_gatts_wr_reply_req(&reply_data); + + bt_conn_unref(flush_data.conn); +} + +void on_nble_gatts_read_evt(const struct nble_gatt_rd_evt *evt) +{ + struct nble_gatts_rd_reply_params reply_data; + 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 */ + uint8_t data[BLE_GATT_MTU_SIZE - 1] = { 0 }; + int len; + + attr = evt->attr; + + BT_DBG("read_evt %p", attr); + + memset(&reply_data, 0, sizeof(reply_data)); + + if (attr->read) { + struct bt_conn *conn = bt_conn_lookup_handle(evt->conn_handle); + + len = attr->read(conn, attr, data, sizeof(data), evt->offset); + + if (conn) + bt_conn_unref(conn); + + } else { + len = BT_GATT_ERR(BT_ATT_ERR_READ_NOT_PERMITTED); + } + + /* status >= 0 is considered as success by nble */ + reply_data.status = len; + + if (len < 0) { + len = 0; + } + + reply_data.conn_handle = evt->conn_handle; + + /* offset is needed by nble even in error case */ + reply_data.offset = evt->offset; + + nble_gatts_rd_reply_req(&reply_data, 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) +{ + 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) == + BT_GATT_ITER_STOP) { + bt_gatt_unsubscribe(conn, params); + } + } + bt_conn_unref(conn); + } +} + +static void gatt_subscription_remove(struct bt_conn *conn, + struct bt_gatt_subscribe_params *prev, + struct bt_gatt_subscribe_params *params) +{ + /* Remove subscription from the list*/ + if (!prev) { + subscriptions = params->_next; + } else { + prev->_next = params->_next; + } + + params->notify(conn, params, NULL, 0); +} + +static void remove_subscribtions(struct bt_conn *conn) +{ + struct bt_gatt_subscribe_params *params, *prev; + + /* Lookup existing subscriptions */ + for (params = subscriptions, prev = NULL; params; + prev = params, params = params->_next) { + if (bt_addr_le_cmp(¶ms->_peer, &conn->le.dst)) { + continue; + } + + /* Remove subscription */ + gatt_subscription_remove(conn, prev, params); + } +} + +int bt_gatt_exchange_mtu(struct bt_conn *conn, bt_gatt_rsp_func_t func) +{ + return -EINVAL; +} + +void on_nble_gattc_discover_rsp(const struct nble_gattc_discover_rsp *rsp, + const uint8_t *data, uint8_t data_len) +{ + size_t i; + uint8_t attr_count; + uint16_t last_handle; + int status = BT_GATT_ITER_STOP; + struct bt_gatt_discover_params *params; + struct bt_gatt_service svc_value; + struct bt_gatt_include inc_value; + struct bt_conn *conn = bt_conn_lookup_handle(rsp->conn_handle); + + BT_ASSERT(conn); + + params = rsp->user_data; + + BT_DBG("disc_rsp: s=%d", rsp->status); + + if (rsp->status) + goto complete; + + if (rsp->type == BT_GATT_DISCOVER_PRIMARY) { + attr_count = (data_len / sizeof(struct nble_gattc_primary)); + } else if (rsp->type == BT_GATT_DISCOVER_INCLUDE) { + attr_count = (data_len / sizeof(struct nble_gattc_included)); + } else if (rsp->type == BT_GATT_DISCOVER_CHARACTERISTIC) { + attr_count = (data_len / sizeof(struct nble_gattc_characteristic)); + } else if (rsp->type == BT_GATT_DISCOVER_DESCRIPTOR) { + attr_count = (data_len / sizeof(struct nble_gattc_descriptor)); + } else + goto complete; + BT_DBG("disc_rsp: c=%d", attr_count); + last_handle = params->end_handle; + for (i = 0; i < attr_count; i++) { + struct bt_gatt_attr *attr = NULL; + + if (rsp->type == BT_GATT_DISCOVER_PRIMARY) { + const struct nble_gattc_primary *gattr = + (void *)&data[i * sizeof(*gattr)]; + if ((gattr->range.start_handle < params->start_handle) && + (gattr->range.end_handle > params->end_handle)) { + /* + * Only the attributes with attribute handles + * between and including the Starting + * Handle and the Ending Handle is returned + */ + goto complete; + } + svc_value.end_handle = gattr->range.end_handle; + svc_value.uuid = params->uuid; + attr = (&(struct bt_gatt_attr)BT_GATT_PRIMARY_SERVICE(&svc_value)); + attr->handle = gattr->handle; + last_handle = svc_value.end_handle; + } else if (rsp->type == BT_GATT_DISCOVER_INCLUDE) { + const struct nble_gattc_included *gattr = + (void *)&data[i * sizeof(*gattr)]; + + inc_value.start_handle = gattr->range.start_handle; + inc_value.end_handle = gattr->range.end_handle; + /* + * 4.5.1 If the service UUID is a 16-bit Bluetooth UUID + * it is also returned in the response. + */ + switch (gattr->uuid.uuid.type) { + case BT_UUID_TYPE_16: + inc_value.uuid = &gattr->uuid.uuid; + break; + case BT_UUID_TYPE_128: + /* Data is not available at this point */ + break; + } + attr = (&(struct bt_gatt_attr) + BT_GATT_INCLUDE_SERVICE(&inc_value)); + attr->handle = gattr->handle; + last_handle = gattr->handle; + } else if (rsp->type == BT_GATT_DISCOVER_CHARACTERISTIC) { + const struct nble_gattc_characteristic *gattr = + (void *)&data[i * sizeof(*gattr)]; + attr = (&(struct bt_gatt_attr) + BT_GATT_CHARACTERISTIC(&gattr->uuid.uuid, + 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)]; + + attr = (&(struct bt_gatt_attr) + BT_GATT_DESCRIPTOR(&gattr->uuid.uuid, 0, NULL, NULL, NULL)); + attr->handle = gattr->handle; + last_handle = gattr->handle; + } else { + /* Error case */ + goto complete; + } + status = params->func(conn, attr, params); + if (status == BT_GATT_ITER_STOP) { + /* Not required to call complete */ + goto done; + } + } + if (last_handle < UINT16_MAX) { + last_handle++; + } + BT_DBG("disc_rsp: l=%d", last_handle); + params->start_handle = last_handle; + if (params->start_handle < params->end_handle) { + if (!bt_gatt_discover(conn, params)) + goto not_done; + } + +complete: + /* Indicate that there are no more attributes found */ + params->func(conn, NULL, params); + +done: + BT_DBG("disc_rsp: done"); + +not_done: + bt_conn_unref(conn); +} + +int bt_gatt_discover(struct bt_conn *conn, + struct bt_gatt_discover_params *params) +{ + struct nble_discover_params discover_params; + + if (!conn || !params || !params->func || !params->start_handle || + !params->end_handle || params->start_handle > params->end_handle) { + return -EINVAL; + } + + if (conn->state != BT_CONN_CONNECTED) { + return -EINVAL; + } + + BT_DBG("disc: %d", params->start_handle); + + memset(&discover_params, 0, sizeof(discover_params)); + + 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; + } + break; + + case BT_GATT_DISCOVER_INCLUDE: + case BT_GATT_DISCOVER_DESCRIPTOR: + break; + default: + 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; + + discover_params.user_data = params; + + nble_gattc_discover_req(&discover_params); + + return 0; +} + +void on_nble_gattc_read_multiple_rsp(const struct ble_gattc_read_rsp *rsp, + uint8_t *pdu, uint8_t length) +{ + struct bt_gatt_read_params *params; + struct bt_conn *conn = bt_conn_lookup_handle(rsp->conn_handle); + + BT_ASSERT(conn); + + params = rsp->user_data; + + BT_DBG("err 0x%02x", rsp->status); + + if (rsp->status) { + params->func(conn, rsp->status, params, NULL, 0); + bt_conn_unref(conn); + return; + } + + params->func(conn, 0, params, pdu, length); + + /* mark read as complete since read multiple is single response */ + params->func(conn, 0, params, NULL, 0); + + bt_conn_unref(conn); +} + +void on_nble_gattc_read_rsp(const struct ble_gattc_read_rsp *rsp, + uint8_t *pdu, uint8_t length) +{ + struct bt_gatt_read_params *params; + struct bt_conn *conn = bt_conn_lookup_handle(rsp->conn_handle); + + BT_ASSERT(conn); + + params = rsp->user_data; + + if (rsp->status) { + params->func(conn, rsp->status, params, NULL, 0); + bt_conn_unref(conn); + return; + } + + if (params->func(conn, 0, params, pdu, length) == BT_GATT_ITER_STOP) { + bt_conn_unref(conn); + return; + } + + /* + * Core Spec 4.2, Vol. 3, Part G, 4.8.1 + * If the Characteristic Value is greater than (ATT_MTU – 1) octets + * 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) { + params->func(conn, 0, params, NULL, 0); + bt_conn_unref(conn); + return; + } + + params->single.offset += length; + + /* Continue reading the attribute */ + if (bt_gatt_read(conn, params)) { + params->func(conn, BT_ATT_ERR_UNLIKELY, params, NULL, 0); + } + bt_conn_unref(conn); +} + +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; + + if (!conn || conn->state != BT_CONN_CONNECTED || !params || + params->handle_count == 0 || !params->func) { + return -EINVAL; + } + + single_req.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; + + nble_gattc_read_req(&single_req); + } else { + mutiple_req.conn_handle = conn->handle; + mutiple_req.user_data = params; + + nble_gattc_read_multiple_req(&mutiple_req, params->handles, 2 * params->handle_count); + } + return 0; +} + +static void on_write_no_rsp_complete(struct bt_conn *conn, uint8_t err, + const void *data) +{ +} + +static void on_write_complete(struct bt_conn *conn, uint8_t err, + const struct bt_gatt_write_params *wr_params) +{ + bt_gatt_write_rsp_func_t func = wr_params->user_data[0]; + const void *data = wr_params->user_data[1]; + + BT_ASSERT(func); + func(conn, err, data); +} + +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 ble_gattc_write_params req; + + req.conn_handle = conn->handle; + req.handle = handle; + req.offset = offset; + req.with_resp = with_resp; + req.wr_params = *wr_params; + + nble_gattc_write_req(&req, data, length); + + return 0; +} + +void on_nble_gattc_write_rsp(const struct ble_gattc_write_rsp *rsp) +{ + + struct bt_conn *conn = bt_conn_lookup_handle(rsp->conn_handle); + + BT_ASSERT(conn); + + if (rsp->wr_params.func) { + rsp->wr_params.func(conn, rsp->status, &rsp->wr_params); + } + + 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); +} + +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) +{ + struct bt_gatt_write_params wr_params; + + if (!conn || conn->state != BT_CONN_CONNECTED || !handle || !func) { + return -EINVAL; + } + + wr_params.func = on_write_complete; + wr_params.user_data[0] = func; + wr_params.user_data[1] = (void *)data; + + return _bt_gatt_write(conn, handle, + (func == on_write_no_rsp_complete) + ? false : true, + offset, data, length, &wr_params); +} + +static void gatt_subscription_add(struct bt_conn *conn, + struct bt_gatt_subscribe_params *params) +{ + bt_addr_le_copy(¶ms->_peer, &conn->le.dst); + + /* Prepend subscription */ + params->_next = subscriptions; + subscriptions = params; +} + +static void att_write_ccc_rsp(struct bt_conn *conn, uint8_t err, + const struct bt_gatt_write_params *wr_params) +{ + struct bt_gatt_subscribe_params *params = wr_params->user_data[0]; + + /* if write to CCC failed we remove subscription and notify app */ + if (err) { + struct bt_gatt_subscribe_params *cur, *prev; + + for (cur = subscriptions, prev = NULL; cur; + prev = cur, cur = cur->_next) { + + if (cur == params) { + gatt_subscription_remove(conn, prev, params); + break; + } + } + } +} + +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; + + wr_params.func = func; + wr_params.user_data[0] = params; + + BT_DBG("handle 0x%04x value 0x%04x", handle, value); + + return _bt_gatt_write(conn, handle, true, 0, &value, sizeof(value), + &wr_params); +} + +int bt_gatt_subscribe(struct bt_conn *conn, + struct bt_gatt_subscribe_params *params) +{ + struct bt_gatt_subscribe_params *tmp; + bool has_subscription = false; + + if (!conn || conn->state != BT_CONN_CONNECTED) { + return -ENOTCONN; + } + + if (!params || !params->notify || + !params->value || !params->ccc_handle) { + return -EINVAL; + } + + /* Lookup existing subscriptions */ + for (tmp = subscriptions; tmp; tmp = tmp->_next) { + /* Fail if entry already exists */ + if (tmp == params) { + return -EALREADY; + } + + /* Check if another subscription exists */ + if (!bt_addr_le_cmp(&tmp->_peer, &conn->le.dst) && + tmp->value_handle == params->value_handle && + tmp->value >= params->value) { + has_subscription = true; + } + } + + /* Skip write if already subscribed */ + if (!has_subscription) { + int err; + + err = gatt_write_ccc(conn, params->ccc_handle, params->value, + att_write_ccc_rsp, params); + if (err) { + return err; + } + } + + /* + * Add subscription before write complete as some implementation were + * reported to send notification before reply to CCC write. + */ + gatt_subscription_add(conn, params); + + return 0; +} + +int bt_gatt_unsubscribe(struct bt_conn *conn, + struct bt_gatt_subscribe_params *params) +{ + struct bt_gatt_subscribe_params *tmp; + bool has_subscription = false, found = false; + + if (!conn || conn->state != BT_CONN_CONNECTED) { + return -ENOTCONN; + } + + if (!params) { + return -EINVAL; + } + + /* Check head */ + if (subscriptions == params) { + subscriptions = params->_next; + found = true; + } + + /* Lookup existing subscriptions */ + for (tmp = subscriptions; tmp; tmp = tmp->_next) { + /* Remove subscription */ + if (tmp->_next == params) { + tmp->_next = params->_next; + found = true; + } + + /* Check if there still remains any other subscription */ + if (!bt_addr_le_cmp(&tmp->_peer, &conn->le.dst) && + tmp->value_handle == params->value_handle) { + has_subscription = true; + } + } + + if (!found) { + return -EINVAL; + } + + if (has_subscription) { + return 0; + } + + params->value = 0; + + return gatt_write_ccc(conn, params->ccc_handle, params->value, NULL, + NULL); +} + +static void add_subscriptions(struct bt_conn *conn) +{ + struct bt_gatt_subscribe_params *params, *prev; + + /* Lookup existing subscriptions */ + for (params = subscriptions, prev = NULL; params; + prev = params, params = params->_next) { + if (bt_addr_le_cmp(¶ms->_peer, &conn->le.dst)) { + continue; + } + + /* Force write to CCC to workaround devices that don't track + * it properly. + */ + gatt_write_ccc(conn, params->ccc_handle, params->value, + att_write_ccc_rsp, params); + } +} +#else + +void on_nble_gattc_discover_rsp(const struct nble_gattc_discover_rsp *rsp, + 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_value_evt(const struct ble_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_multiple_rsp(const struct ble_gattc_read_rsp *rsp, + uint8_t *data, uint8_t data_len) +{ +} + +#endif + +void bt_gatt_connected(struct bt_conn *conn) +{ + BT_DBG("conn %p", conn); + bt_gatt_foreach_attr(0x0001, 0xffff, connected_cb, conn); +#if defined(CONFIG_BLUETOOTH_GATT_CLIENT) + add_subscriptions(conn); +#endif /* CONFIG_BLUETOOTH_GATT_CLIENT */ +} + +void bt_gatt_disconnected(struct bt_conn *conn) +{ + BT_DBG("conn %p", conn); + 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)) { + return; + } + + remove_subscribtions(conn); +#endif /* CONFIG_BLUETOOTH_GATT_CLIENT */ +} diff --git a/system/libarc32_arduino101/framework/src/services/ble/hci_core.h b/system/libarc32_arduino101/framework/src/services/ble/hci_core.h new file mode 100644 index 00000000..dc7374b0 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble/hci_core.h @@ -0,0 +1,70 @@ +/* + * 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. + */ + +/* State tracking for the local Bluetooth controller */ +struct bt_dev { + atomic_t flags[1]; +}; +extern struct bt_dev bt_dev; + +#if defined(CONFIG_BLUETOOTH_SMP) || defined(CONFIG_BLUETOOTH_BREDR) +extern const struct bt_conn_auth_cb *bt_auth; +#endif /* CONFIG_BLUETOOTH_SMP || CONFIG_BLUETOOTH_BREDR */ + +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) + return true; + + return false; +} + +static inline bool bt_addr_le_is_identity(const bt_addr_le_t *addr) +{ + if (addr->type == BT_ADDR_LE_PUBLIC) + return true; + + /* Check for Random Static address type */ + if ((addr->val[5] & 0xc0) == 0xc0) + return true; + + return false; +} + +static inline bool bt_le_conn_params_valid(uint16_t min, uint16_t max, + uint16_t latency, uint16_t timeout) +{ + if (min > max || min < 6 || max > 3200) { + return false; + } + + /* Limits according to BT Core spec 4.2 [Vol 2, Part E, 7.8.12] */ + if (timeout < 10 || timeout > 3200) { + return false; + } + + /* Limits according to BT Core spec 4.2 [Vol 6, Part B, 4.5.1] */ + if (latency > 499 || ((latency + 1) * max) > (timeout * 4)) { + return false; + } + + return true; +} + + diff --git a/system/libarc32_arduino101/framework/src/services/ble/l2cap.c b/system/libarc32_arduino101/framework/src/services/ble/l2cap.c new file mode 100644 index 00000000..488cfd0e --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble/l2cap.c @@ -0,0 +1,62 @@ +/* + * 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 "conn_internal.h" +#include "gatt_internal.h" +#include "smp.h" + +/* #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_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_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) +#endif + +void bt_l2cap_connected(struct bt_conn *conn) +{ + /* TODO Add support for fixed channels on BR/EDR transport */ + if (conn->type != BT_CONN_TYPE_LE) { + return; + } +#if defined(CONFIG_BLUETOOTH_SMP) + bt_smp_connected(conn); +#endif + bt_gatt_connected(conn); +} + +void bt_l2cap_disconnected(struct bt_conn *conn) +{ +#if defined(CONFIG_BLUETOOTH_SMP) + bt_smp_disconnected(conn); +#endif + bt_gatt_disconnected(conn); +} diff --git a/system/libarc32_arduino101/framework/src/services/ble/l2cap_internal.h b/system/libarc32_arduino101/framework/src/services/ble/l2cap_internal.h new file mode 100644 index 00000000..2f593fa5 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble/l2cap_internal.h @@ -0,0 +1,27 @@ +/* + * 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 L2CAP_INTERNAL_H_ +#define L2CAP_INTERNAL_H_ + +/* Notify L2CAP channels of a new connection */ +void bt_l2cap_connected(struct bt_conn *conn); + +/* Notify L2CAP channels of a disconnect event */ +void bt_l2cap_disconnected(struct bt_conn *conn); + + +#endif /* L2CAP_INTERNAL_H_ */ diff --git a/system/libarc32_arduino101/framework/src/services/ble/smp.h b/system/libarc32_arduino101/framework/src/services/ble/smp.h new file mode 100644 index 00000000..4f52c002 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble/smp.h @@ -0,0 +1,100 @@ +/* + * 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. + */ + +#define BT_SMP_ERR_PASSKEY_ENTRY_FAILED 0x01 +#define BT_SMP_ERR_OOB_NOT_AVAIL 0x02 +#define BT_SMP_ERR_AUTH_REQUIREMENTS 0x03 +#define BT_SMP_ERR_CONFIRM_FAILED 0x04 +#define BT_SMP_ERR_PAIRING_NOTSUPP 0x05 +#define BT_SMP_ERR_ENC_KEY_SIZE 0x06 +#define BT_SMP_ERR_CMD_NOTSUPP 0x07 +#define BT_SMP_ERR_UNSPECIFIED 0x08 +#define BT_SMP_ERR_REPEATED_ATTEMPTS 0x09 +#define BT_SMP_ERR_INVALID_PARAMS 0x0a +#define BT_SMP_ERR_DHKEY_CHECK_FAILED 0x0b +#define BT_SMP_ERR_NUMERIC_COMP_FAILED 0x0c +#define BT_SMP_ERR_BREDR_PAIRING_IN_PROGRESS 0x0d +#define BT_SMP_ERR_CROSS_TRANSP_NOT_ALLOWED 0x0e + +#define BT_SMP_IO_DISPLAY_ONLY 0x00 +#define BT_SMP_IO_DISPLAY_YESNO 0x01 +#define BT_SMP_IO_KEYBOARD_ONLY 0x02 +#define BT_SMP_IO_NO_INPUT_OUTPUT 0x03 +#define BT_SMP_IO_KEYBOARD_DISPLAY 0x04 + +#define BT_SMP_OOB_NOT_PRESENT 0x00 +#define BT_SMP_OOB_PRESENT 0x01 + +#define BT_SMP_MIN_ENC_KEY_SIZE 7 +#define BT_SMP_MAX_ENC_KEY_SIZE 16 + +#define BT_SMP_DIST_ENC_KEY 0x01 +#define BT_SMP_DIST_ID_KEY 0x02 +#define BT_SMP_DIST_SIGN 0x04 +#define BT_SMP_DIST_LINK_KEY 0x08 + +#define BT_SMP_DIST_MASK 0x0f + +#define BT_SMP_AUTH_NONE 0x00 +#define BT_SMP_AUTH_BONDING 0x01 +#define BT_SMP_AUTH_MITM 0x04 +#define BT_SMP_AUTH_SC 0x08 + +#if 0 +bool bt_smp_irk_matches(const uint8_t irk[16], const bt_addr_t *addr); +#endif +int bt_smp_send_pairing_req(struct bt_conn *conn); +int bt_smp_send_security_req(struct bt_conn *conn); +#if 0 +void bt_smp_update_keys(struct bt_conn *conn); +bool bt_smp_get_tk(struct bt_conn *conn, uint8_t *tk); + +void bt_smp_dhkey_ready(const uint8_t *dhkey); +void bt_smp_pkey_ready(void); +#endif + +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_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); +#endif + +#if 0 +/** brief Verify signed message + * + * @param conn Bluetooth connection + * @param buf received packet buffer with message and signature + * + * @return 0 in success, error code otherwise + */ +int bt_smp_sign_verify(struct bt_conn *conn, struct net_buf *buf); + +/** brief Sign message + * + * @param conn Bluetooth connection + * @param buf message buffer + * + * @return 0 in success, error code otherwise + */ +int bt_smp_sign(struct bt_conn *conn, struct net_buf *buf); +#endif diff --git a/system/libarc32_arduino101/framework/src/services/ble/smp_null.c b/system/libarc32_arduino101/framework/src/services/ble/smp_null.c new file mode 100644 index 00000000..cdc3a4d5 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble/smp_null.c @@ -0,0 +1,118 @@ +/* + * 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 "smp.h" + +/* nble internal APIs */ +#include "gap_internal.h" + +/* #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_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_ASSERT(cond) ((cond) ? (void)0 : __assert_fail()) +#endif + +/** + * Compile time IO capabilities and OOB support settings for nble. + * + * This compile options must match the application registered callbacks + * (bt_conn_auth_cb_register) + */ +#define NBLE_SMP_IO_CAPS BT_SMP_IO_NO_INPUT_OUTPUT +#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) +{ + return -ENOTSUP; +} +#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) +{ + /* stub */ +} + +void on_nble_gap_sm_passkey_req_evt(const struct nble_gap_sm_passkey_req_evt * p_evt) +{ + /* stub */ +} + +void on_nble_gap_sm_passkey_display_evt( + const struct nble_gap_sm_passkey_disp_evt *p_evt) +{ + /* stub */ +} + +void on_nble_gap_sm_status_evt(const struct nble_gap_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) +{ + 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; +} + +void on_nble_gap_sm_config_rsp(struct nble_gap_sm_config_rsp *p_params) +{ + if (p_params->status) { + BT_ERR("sm_config failed: %d", p_params->status); + } +} + +void on_nble_gap_sm_common_rsp(const struct nble_gap_sm_response *rsp) +{ + if (rsp->status) { + BT_WARN("gap sm request failed: %d", rsp->status); + } +} diff --git a/system/libarc32_arduino101/framework/src/services/ble/uuid.c b/system/libarc32_arduino101/framework/src/services/ble/uuid.c new file mode 100644 index 00000000..dbacfd94 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble/uuid.c @@ -0,0 +1,135 @@ +/* uuid.c - Bluetooth UUID handling */ + +/* + * Copyright (c) 2015 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 +#include + +#include + +#if defined(CONFIG_BLUETOOTH_DEBUG) +#include +#endif /* CONFIG_BLUETOOTH_DEBUG */ + +#define UUID_16_BASE_OFFSET 12 + +/* TODO: Decide whether to continue using BLE format or switch to RFC 4122 */ + +/* Base UUID : 0000[0000]-0000-1000-8000-00805F9B34FB -> + * { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, + * 0x00, 0x10, 0x00, 0x00, [0x00, 0x00], 0x00, 0x00 } + * 0x2800 : 0000[2800]-0000-1000-8000-00805F9B34FB -> + * { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, + * 0x00, 0x10, 0x00, 0x00, [0x00, 0x28], 0x00, 0x00 } + * little endian 0x2800 : [00 28] -> no swapping required + * big endian 0x2800 : [28 00] -> swapping required + */ +static const struct bt_uuid_128 uuid128_base = { + .uuid.type = BT_UUID_TYPE_128, + .val = { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, +}; + +static inline void u16_to_uuid128(void *dst, uint16_t u16) +{ +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u16 = bswap_16(u16); +#endif + memcpy(dst, &u16, 2); +} + +static void uuid_to_uuid128(const struct bt_uuid *src, struct bt_uuid_128 *dst) +{ + switch (src->type) { + case BT_UUID_TYPE_16: + *dst = uuid128_base; + u16_to_uuid128(&dst->val[UUID_16_BASE_OFFSET], + BT_UUID_16(src)->val); + return; + case BT_UUID_TYPE_128: + memcpy(dst, src, sizeof(*dst)); + return; + } +} + +static int uuid128_cmp(const struct bt_uuid *u1, const struct bt_uuid *u2) +{ + struct bt_uuid_128 uuid1, uuid2; + + uuid_to_uuid128(u1, &uuid1); + uuid_to_uuid128(u2, &uuid2); + + return memcmp(uuid1.val, uuid2.val, 16); +} + +int bt_uuid_cmp(const struct bt_uuid *u1, const struct bt_uuid *u2) +{ + /* Convert to 128 bit if types don't match */ + if (u1->type != u2->type) + return uuid128_cmp(u1, u2); + + switch (u1->type) { + case BT_UUID_TYPE_16: + return (int)BT_UUID_16(u1)->val - (int)BT_UUID_16(u2)->val; + case BT_UUID_TYPE_128: + return memcmp(BT_UUID_128(u1)->val, BT_UUID_128(u2)->val, 16); + } + + return -EINVAL; +} + +#if defined(CONFIG_BLUETOOTH_DEBUG) +void bt_uuid_to_str(const struct bt_uuid *uuid, char *str, size_t len) +{ + uint32_t tmp1, tmp5; + uint16_t tmp0, tmp2, tmp3, tmp4; + + switch (uuid->type) { + case BT_UUID_TYPE_16: + snprintf(str, len, "%.4x", BT_UUID_16(uuid)->val); + break; + case BT_UUID_TYPE_128: + memcpy(&tmp0, &BT_UUID_128(uuid)->val[0], sizeof(tmp0)); + memcpy(&tmp1, &BT_UUID_128(uuid)->val[2], sizeof(tmp1)); + memcpy(&tmp2, &BT_UUID_128(uuid)->val[6], sizeof(tmp2)); + memcpy(&tmp3, &BT_UUID_128(uuid)->val[8], sizeof(tmp3)); + memcpy(&tmp4, &BT_UUID_128(uuid)->val[10], sizeof(tmp4)); + memcpy(&tmp5, &BT_UUID_128(uuid)->val[12], sizeof(tmp5)); + + snprintf(str, len, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x", + tmp5, tmp4, tmp3, tmp2, tmp1, tmp0); + break; + default: + memset(str, 0, len); + return; + } +} + +const char *bt_uuid_str(const struct bt_uuid *uuid) +{ + static char str[37]; + + bt_uuid_to_str(uuid, str, sizeof(str)); + + return str; +} +#endif /* CONFIG_BLUETOOTH_DEBUG */ diff --git a/system/libarc32_arduino101/framework/include/services/ble/ble_service_msg.h b/system/libarc32_arduino101/framework/src/services/ble_service/ble_protocol.h similarity index 70% rename from system/libarc32_arduino101/framework/include/services/ble/ble_service_msg.h rename to system/libarc32_arduino101/framework/src/services/ble_service/ble_protocol.h index 6893731a..51109f9d 100644 --- a/system/libarc32_arduino101/framework/include/services/ble/ble_service_msg.h +++ b/system/libarc32_arduino101/framework/src/services/ble_service/ble_protocol.h @@ -28,23 +28,30 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __BLE_SERVICE_MSG_H__ -#define __BLE_SERVICE_MSG_H__ +#ifndef __BLE_PROTOCOL_H__ +#define __BLE_PROTOCOL_H__ -#include "services/services_ids.h" - -/* - * CFW Message ID base definitions for BLE services. +/** + * @defgroup ble_protocol BLE protocol definitions + * + * BT Spec definitions. + * @ingroup ble_service + * @{ + * + * Bluetooth SIG defined macros and enum extracted from Bluetooth Spec 4.2 */ +#define BLE_MAX_DEVICE_NAME 20 /**< Max BLE device name length 20 + NULL, spec size: 248 */ +#define BLE_MAX_ADV_SIZE 31 + +#define BLE_GATT_MTU_SIZE 23 /**< Default MTU size */ + +/** Manufacturer IDs */ +#define INTEL_MANUFACTURER 0x0002 -/* BLE Service Message ID definitions. */ -#define MSG_ID_BLE_BASE BLE_SERVICE_MSG_BASE -#define MSG_ID_BLE_RSP (BLE_SERVICE_MSG_BASE + 0x40) -#define MSG_ID_BLE_EVT (BLE_SERVICE_MSG_BASE + 0x80) +/* HCI status (error) codes as per BT spec */ +#define HCI_REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF 0x15 +#define HCI_LOCAL_HOST_TERMINATED_CONNECTION 0x16 -/* BLE Core Service Message ID base (GAP/GATT) */ -#define MSG_ID_BLE_GAP_BASE BLE_SERVICE_GAP_MSG_BASE -#define MSG_ID_BLE_GAP_RSP (BLE_SERVICE_GAP_MSG_BASE + 0x40) -#define MSG_ID_BLE_GAP_EVT (BLE_SERVICE_GAP_MSG_BASE + 0x80) +/** @} */ #endif 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 new file mode 100644 index 00000000..405c984a --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service.c @@ -0,0 +1,297 @@ +/* + * 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 "os/os.h" + +//#include "util/assert.h" +#include +//#include +#include "cfw/cfw_service.h" +#include "ble_protocol.h" +#include "ble_service_int.h" +#include "ble_service_internal.h" +#include "infra/log.h" + +#include +#include +#include +#include +#include "gap_internal.h" + +#include "nble_driver.h" + +#include "rpc.h" + +#include "util/misc.h" + +struct _ble_service_cb _ble_cb = { 0 }; +volatile uint8_t ble_inited = false; + + +static void ble_client_connected(conn_handle_t *instance); +static void ble_client_disconnected(conn_handle_t *instance); + +#if defined(CONFIG_BLUETOOTH_SMP) +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, +}; + +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); +} + +#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); +} +#endif /* CONFIG_TCMD_BLE_DEBUG */ + +void on_nble_gap_dbg_rsp(const struct nble_debug_resp *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); +#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 */ + rpc_deserialize(rpc->p_data, rpc->len); + bfree(rpc->p_data); + message_free(msg); +} + +static void ble_set_bda_cb(int status, void *user_data) +{ + 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); + } +} + +static void handle_ble_enable(struct ble_enable_req *req, + struct _ble_service_cb *p_cb) +{ + pr_info(LOG_MODULE_BLE, "ble_enable: state %d", p_cb->ble_state); + + p_cb->ble_state = BLE_ST_ENABLED; + + if (req->bda_present) { + struct nble_set_bda_params params; + + 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); + } +} + +static void handle_ble_disable(struct ble_enable_req *req, struct _ble_service_cb *p_cb) +{ + struct ble_enable_rsp *resp; + + pr_debug(LOG_MODULE_BLE, "ble_disable"); + p_cb->ble_state = BLE_ST_DISABLED; + + bt_le_adv_stop(); + + resp = (void *)cfw_alloc_rsp_msg(&req->header, + MSG_ID_BLE_ENABLE_RSP, + sizeof(*resp)); + cfw_send_message(resp); + +} + +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); + } + } + break; +#ifdef CONFIG_TCMD_BLE_DEBUG + 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; + } +out: + 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"); +} + +static void ble_client_disconnected(conn_handle_t *instance) +{ +} + +void ble_bt_rdy(int err) +{ + _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); + } +} + +void ble_cfw_service_init(int service_id, T_QUEUE queue) +{ + _ble_cb.queue = queue; + _ble_cb.ble_state = BLE_ST_NOT_READY; + +#ifdef CONFIG_IPC_UART_NS16550 + nble_driver_configure(queue, handle_msg_id_ble_rpc_callin); +#endif + + ble_inited = false; + + bt_enable(ble_bt_rdy); + do{} + 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); +} + +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 new file mode 100644 index 00000000..e70b15c8 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_api.c @@ -0,0 +1,66 @@ +/* + * 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/ble_service_int.h b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_int.h new file mode 100644 index 00000000..857270c7 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_int.h @@ -0,0 +1,67 @@ +/* + * 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. + */ + +#ifndef BLE_SERVICE_INT_H_ +#define BLE_SERVICE_INT_H_ + +#include + +/* For cfw_service_conn_t, cfw_client_t, T_QUEUE */ +#include "cfw/cfw.h" + +/* Forward declarations */ +struct ble_init_svc_req; +struct ble_init_svc_rsp; +struct bt_conn_cb; +struct bt_gatt_attr; + +enum BLE_STATE { + BLE_ST_NOT_READY = 0, + BLE_ST_DISABLED, + BLE_ST_ENABLED, + BLE_ST_DTM +}; + +struct _ble_service_cb { + T_QUEUE queue; /* Queue for the messages */ + uint8_t ble_state; +}; + +extern struct _ble_service_cb _ble_cb; + +/** Send advertisement timeout event to application */ +void ble_gap_advertisement_timeout(void); + +#ifdef CONFIG_BLE_CORE_TEST +void test_ble_service_init(void); +T_QUEUE get_service_queue(void); +#endif + +#endif /* BLE_SERVICE_INT_H_ */ diff --git a/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_internal.h b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_internal.h new file mode 100644 index 00000000..013043a5 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_internal.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016, 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. + */ + +#ifndef __BLE_SERVICE_INTERNAL_H__ +#define __BLE_SERVICE_INTERNAL_H__ + +// For MSG_ID_BLE_SERVICE_BASE +#include "services/services_ids.h" + +/* BLE High level Message IDs used for request, response, events. */ +enum BLE_MSG_ID_REQ { + MSG_ID_BLE_ENABLE_REQ = MSG_ID_BLE_SERVICE_BASE, /* Message ID for enable request */ + MSG_ID_BLE_SET_NAME_REQ, /* Message ID for set name request */ + MSG_ID_BLE_START_SCAN_REQ, /* Message ID for start scan request */ + MSG_ID_BLE_STOP_SCAN_REQ, /* Message ID for stop scan request */ + MSG_ID_BLE_INIT_SVC_REQ, /* Message ID for init service request */ + + /* BLE debug command */ + MSG_ID_BLE_DBG_REQ, /* Message ID for BLE debug command request */ + + MSG_ID_BLE_REQ_LAST, +}; + +/* Parameters of MSG_ID_BLE_ENABLE_REQ. */ +struct ble_enable_req { + struct cfw_message header; /* Component framework message header, MUST be first element of structure */ + struct bt_le_conn_param central_conn_params; + uint8_t enable; + uint8_t bda_present; + bt_addr_le_t bda; +}; + +struct ble_disconnect_req { + struct cfw_message header; /* Component framework message header, MUST be first element of structure */ + struct bt_conn *conn; /* Connection reference */ + uint8_t reason; /* Reason of the disconnect*/ +}; + +struct ble_connect_req { + struct cfw_message header; /* Component framework message header, MUST be first element of structure */ + struct bt_le_conn_param conn_params; + bt_addr_le_t bd_addr; +}; + +struct ble_init_svc_req { + struct cfw_message header; /* Component framework message header, MUST be first element of structure */ + int (*init_svc)(struct ble_init_svc_req *msg, struct _ble_service_cb *p_cb); + void (*init_svc_complete)(struct ble_init_svc_req *req); + uint8_t status; +}; + +#endif /* __BLE_SERVICE_INTERNAL_H__ */ diff --git a/system/libarc32_arduino101/framework/src/services/ble/ble_service_utils.c b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_utils.c similarity index 50% rename from system/libarc32_arduino101/framework/src/services/ble/ble_service_utils.c rename to system/libarc32_arduino101/framework/src/services/ble_service/ble_service_utils.c index d40c1b72..0275e79b 100644 --- a/system/libarc32_arduino101/framework/src/services/ble/ble_service_utils.c +++ b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_utils.c @@ -31,77 +31,48 @@ #include #include "os/os.h" #include "ble_protocol.h" -#include "services/ble/ble_service_gap_api.h" +#include "ble_service.h" +#include "ble_service_int.h" #include "ble_service_utils.h" -uint8_t ble_sizeof_bt_uuid(const struct bt_uuid * p_uuid) +void uint8_to_ascii(uint8_t in, uint8_t *p) { - return p_uuid->type + 1; + uint8_t hi = (in & 0xF0) >> 4; + uint8_t lo = in & 0x0F; + + if (hi < 0x0A) + *p = '0' + hi; + else + *p = 'A' + (hi - 0x0A); + + p++; + + if (lo < 10) + *p = '0' + lo; + else + *p = 'A' + (lo - 0x0A); } -uint8_t * ble_encode_bt_uuid(const struct bt_uuid * p_uuid, uint8_t * p_data) +void uint8buf_to_ascii(uint8_t * dst, const uint8_t * src, int len) { - // start with the type (length) - UINT8_TO_LESTREAM(p_data, p_uuid->type); - switch (p_uuid->type) { - case BT_UUID16: - UINT16_TO_LESTREAM(p_data, p_uuid->uuid16); - break; - case BT_UUID32: - UINT32_TO_LESTREAM(p_data, p_uuid->uuid32); - break; - case BT_UUID128: - memcpy(p_data, p_uuid->uuid128, MAX_UUID_SIZE); - p_data += MAX_UUID_SIZE; - break; + int i; + for (i = 0; i < len; ++i) { + uint8_to_ascii(src[i], dst); + dst += 2; } - return p_data; } -uint8_t ble_cpy_bt_uuid(uint8_t * p_uuid_dst, - const struct bt_uuid * p_uuid_src, - uint8_t type) +size_t adv_data_len(const struct bt_data *ad, size_t count) { - uint8_t *p = p_uuid_dst; - uint8_t res_type = (p_uuid_src->type >= type) ? type : 0; + int i; + size_t data_len = 0; - switch (res_type) { - case BT_UUID16: - switch (p_uuid_src->type) { - case BT_UUID16: - UINT16_TO_LESTREAM(p, p_uuid_src->uuid16); - break; - case BT_UUID32: - UINT16_TO_LESTREAM(p, p_uuid_src->uuid16); - break; - case BT_UUID128: { - uint16_t uuid16; - p = (uint8_t *)&p_uuid_src->uuid128[BLE_BASE_UUID_OCTET_OFFSET]; - LESTREAM_TO_UINT16(p, uuid16); - p = p_uuid_dst; - UINT16_TO_LESTREAM(p, p_uuid_src->uuid16); - break; - } - } - break; - case BT_UUID32: - switch (p_uuid_src->type) { - case BT_UUID32: - UINT32_TO_LESTREAM(p, p_uuid_src->uuid32); - break; - case BT_UUID128: { - uint32_t uuid32; - p = (uint8_t *)&p_uuid_src->uuid128[BLE_BASE_UUID_OCTET_OFFSET]; - LESTREAM_TO_UINT32(p, uuid32); - p = p_uuid_dst; - UINT32_TO_LESTREAM(p, uuid32); - break; - } - } - break; - case BT_UUID128: - memcpy(p_uuid_dst, p_uuid_src->uuid128, MAX_UUID_SIZE); - break; + if (ad == NULL) + return 0; + + for (i = 0; i < count ; i++) { + data_len += ad[i].data_len; } - return res_type; + + return data_len; } diff --git a/system/libarc32_arduino101/framework/src/services/ble/ble_service_utils.h b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_utils.h similarity index 66% rename from system/libarc32_arduino101/framework/src/services/ble/ble_service_utils.h rename to system/libarc32_arduino101/framework/src/services/ble_service/ble_service_utils.h index a51f8dcd..8d5d9378 100644 --- a/system/libarc32_arduino101/framework/src/services/ble/ble_service_utils.h +++ b/system/libarc32_arduino101/framework/src/services/ble_service/ble_service_utils.h @@ -28,20 +28,19 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __BLE_SERVICE_UTILS_H__ -#define __BLE_SERVICE_UTILS_H__ +#ifndef BLE_SERVICE_UTILS_H_ +#define BLE_SERVICE_UTILS_H_ -#include "services/ble/ble_service_gap_api.h" -#include "services/ble/ble_service_gatt.h" -//#include "ble_service_int.h" +#include -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + __must_be_array(a) +// For HAVE_SAME_TYPE +#include "compiler.h" #define IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) #define UINT8_TO_LESTREAM(p, i) \ do { *(p)++ = (uint8_t)(i); } \ - while (sizeof(char[1 - 2 * !(__builtin_types_compatible_p(__typeof__(p), uint8_t *))]) - 1) + while (sizeof(char[1 - 2 * !(HAVE_SAME_TYPE(p, uint8_t *))]) - 1) #define UINT16_TO_LESTREAM(p, i) UINT8_TO_LESTREAM(p, i); UINT8_TO_LESTREAM(p, (i)>>8) #define UINT32_TO_LESTREAM(p, i) UINT16_TO_LESTREAM(p, i); UINT16_TO_LESTREAM(p, (i)>>16) @@ -59,8 +58,8 @@ #define LESTREAM_TO_UINT8(p, i) \ do { i = *p; p++; } \ - while (sizeof(char[1 - 2 * !(__builtin_types_compatible_p(__typeof__(p), const uint8_t *) || \ - __builtin_types_compatible_p(__typeof__(p), uint8_t *))]) - 1) + while (sizeof(char[1 - 2 * !(HAVE_SAME_TYPE(p, const uint8_t *) || \ + HAVE_SAME_TYPE(p, uint8_t *))]) - 1) #define LESTREAM_TO_UINT16(p, i) \ do { uint16_t temp16; LESTREAM_TO_UINT8(p, i); LESTREAM_TO_UINT8(p, temp16); i |= (temp16 << 8); } \ while (0) @@ -90,53 +89,38 @@ #define BESTREAM_TO_INT32(p, i) \ do {uint32_t __i; BESTREAM_TO_UINT32(p, __i); i = (int32_t)__i; } while (0) -#define between(a, b, c) (((a) >= (b)) || ((a) <= (c))) - -#define strict_between(a, b, c) (((a) > (b)) || ((a) < (c))) - /** * BLE helper functions. */ -#define BLE_BASE_UUID_OCTET_OFFSET 12 -/** - * Compute the size required to encode a UUID in a buffer +/**@brief Represent an unsigned 8 bit value in ASCII hexadecimal + * + * @param[in] in The value to represent + * @param[inout] p Pointer to the buffer to fill * - * @param p_uuid Pointer to the UUID + * @note The representation requires 2 bytes */ -uint8_t ble_sizeof_bt_uuid(const struct bt_uuid * p_uuid); +void uint8_to_ascii(uint8_t in, uint8_t * p); -/** - * Encode a UUID in a buffer +/** Converts buffer from hex to ascii. * - * @param p_uuid Pointer to the UUID to encode - * @param p_data Pointer to the buffer to store the encoded UUID + * @param dst buffer converted + * @param src buffer which is converted + * @param len length of src (dst shall be large enough) * - * @return The pointer to the buffer after the encoded UUID + * @return None */ -uint8_t * ble_encode_bt_uuid(const struct bt_uuid * p_uuid, uint8_t * p_data); +void uint8buf_to_ascii(uint8_t * dst, const uint8_t * src, int len); -/** Copy BT/BLE address and eventually reduce size. - * - * Copies a uuid from src to dst. type may modify the resulting uuid type. only - * going from bigger to small type is supported. typically 128 bits to 16 bits - * If it is different from src type, a transformation is applied: - * IN: BT_UUID128: dd97c415-fed9-4766-b18f-ba690d24a06a (stored in little endian) - * OUT: BT_UUID16: c415 - * OUT: BT_UUID32: dd97c415 - * or - * IN: BT_UUID32: dd97c415 - * OUT: BT_UUID16: c415 - * - * @param p_uuid_src source uuid - * @param[out] p_uuid_dst: destination to copy uuid to (excluding type). little endian - * @param type output type +struct bt_data; +/** + * Get advertisement data length. * - * \return size/type of copied uuid: BT_UUID16, BT_UUID32, BT_UUID128 or 0 for failure! + * @param ad advertisement data + * @param count array length + * @return length of advertisement data * */ -uint8_t ble_cpy_bt_uuid(uint8_t * p_uuid_dst, - const struct bt_uuid * p_uuid_src, - uint8_t type); +size_t adv_data_len(const struct bt_data *ad, size_t count); -#endif +#endif /* BLE_SERVICE_UTILS_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 new file mode 100644 index 00000000..333ad36e --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble_service/gap_internal.h @@ -0,0 +1,629 @@ +/* + * 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 GAP_INTERNAL_H_ +#define GAP_INTERNAL_H_ + +#include +/* For bt_addr_le_t */ +#include +/* For bt_security_t */ +#include + +/* 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, + NBLE_TEST_START_DTM_TX = 0x1e, + NBLE_TEST_END_DTM = 0x1f, + /* vendor specific commands start at 0x80 */ + /* Set Tx power. To be called before start of tx test */ + NBLE_TEST_SET_TXPOWER = 0x80, + NBLE_TEST_START_TX_CARRIER, +}; + +/* DTM commands, opcodes, indexes. */ +#define H4_CMD 0x01 +#define HCI_OGF_LE_CMD 0x20 + +#define DTM_HCI_STATUS_IDX 6 +#define DTM_HCI_LE_END_IDX (DTM_HCI_STATUS_IDX + 1) + + +struct nble_response { + 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 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; +}; + + +enum NBLE_GAP_SVC_ATTR_TYPE { + /* Device Name, UUID 0x2a00 */ + NBLE_GAP_SVC_ATTR_NAME = 0, + /* Appearance, UUID 0x2a01 */ + NBLE_GAP_SVC_ATTR_APPEARANCE, + /* Peripheral Preferred Connection Parameters (PPCP), UUID 0x2a04 */ + NBLE_GAP_SVC_ATTR_PPCP = 4, + /* Central Address Resolution (CAR), UUID 0x2aa6, BT 4.2 */ + NBLE_GAP_SVC_ATTR_CAR = 0xa6, +}; + +struct nble_gap_connection_params { + /* 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! */ + uint16_t interval_max; + /* maximum connection slave latency: 0x0000 to 0x01f3 */ + uint16_t slave_latency; + /* link supervision timeout: 0x000a to 0x0c80 (unit 10ms) */ + 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 */ + 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; + /* 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; +}; + +struct nble_debug_params { + uint32_t u0; + uint32_t u1; +}; + +struct nble_debug_resp { + int status; + uint32_t u0; + uint32_t u1; + void *user_data; +}; + +typedef void (*nble_set_bda_cb_t)(int status, void *user_data); + +struct nble_set_bda_params { + bt_addr_le_t bda; + nble_set_bda_cb_t cb; + void *user_data; +}; + +struct nble_set_bda_rsp { + nble_set_bda_cb_t cb; + void *user_data; + int status; +}; + +struct bt_eir_data { + uint8_t len; + uint8_t data[31]; +}; + +struct nble_gap_adv_params { + 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 */ + uint8_t type; + /* filter policy to apply with white list */ + uint8_t filter_policy; + /* bd address of peer device in case of directed advertisement */ + 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_start_adv_req(void); + +void on_nble_gap_start_advertise_rsp(const struct nble_response *params); + +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 { + uint16_t conn_handle; + struct nble_gap_connection_params params; +}; + +void nble_gap_conn_update_req(const struct nble_gap_connect_update_params *params); + +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; +}; + +struct nble_gap_disconnect_req_params { + 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); + +struct nble_gap_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); + + +struct nble_gap_sm_pairing_params { + /* authentication level see @ref BLE_GAP_SM_OPTIONS */ + uint8_t auth_level; +}; + +struct nble_gap_sm_security_params { + struct bt_conn *conn; + uint16_t conn_handle; + /* Local authentication/bonding parameters */ + struct nble_gap_sm_pairing_params params; +}; + +void nble_gap_sm_security_req(const struct nble_gap_sm_security_params * + params); + +struct nble_gap_sm_passkey { + uint8_t type; + union { + uint32_t passkey; + uint8_t oob[16]; + uint8_t reason; + }; +}; + +struct nble_gap_sm_key_reply_req_params { + struct bt_conn *conn; + uint16_t conn_handle; + struct nble_gap_sm_passkey params; +}; + +void nble_gap_sm_passkey_reply_req(const struct nble_gap_sm_key_reply_req_params + *params); + +struct nble_gap_sm_clear_bond_req_params { + bt_addr_le_t addr; +}; + +void nble_gap_sm_clear_bonds_req(const struct nble_gap_sm_clear_bond_req_params + *params); + +struct nble_gap_sm_response { + int status; + struct bt_conn *conn; +}; + +void on_nble_gap_sm_common_rsp(const struct nble_gap_sm_response *rsp); + +/** + * Callback for rssi event. + */ +typedef void (*rssi_report_t)(const int8_t *rssi_data); + +/** + * Callback for rssi report response. + */ +typedef void (*rssi_report_resp_t)(int status); + +struct nble_rssi_report_params { + uint16_t conn_handle; + /* RSSI operation @ref 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 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 on_nble_gap_set_rssi_report_rsp(const struct nble_response *params); + +struct nble_gap_scan_params { + uint16_t interval; + uint16_t window; + uint8_t scan_type; + 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); + +void nble_gap_cancel_connect_req(void *priv); + +void on_nble_gap_cancel_connect_rsp(const struct nble_response *params); + +enum BLE_GAP_SET_OPTIONS { + BLE_GAP_SET_CH_MAP = 0, +}; + +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_set_option_params { + /* Option to set @ref BLE_GAP_SET_OPTIONS */ + uint8_t op; + union { + struct nble_gap_channel_map ch_map; + }; +}; + +/* + * 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, +}; + +struct nble_gap_gen_cmd_params { + /* @ref BLE_GAP_GEN_OPS */ + uint8_t op_code; +}; + +/* Temporary patch: RSSI processing for UAS */ +struct nble_uas_rssi_calibrate { + float distance; +}; +void nble_uas_rssi_calibrate_req(const struct nble_uas_rssi_calibrate *p_struct); + +/* 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); + +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; +}; + +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_dtm_init_req(void *user_data); + +void on_nble_gap_dtm_init_rsp(void *user_data); + +struct nble_gap_tx_power_params { + int8_t tx_power; +}; + +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; + /* 0 if connected as master, otherwise as slave */ + uint8_t role_slave; + /* Address of peer device */ + bt_addr_le_t peer_bda; +}; + +void on_nble_gap_connect_evt(const struct nble_gap_connect_evt *evt); + +struct nble_gap_disconnect_evt { + uint16_t conn_handle; + uint8_t hci_reason; +}; + +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; +}; + +void on_nble_gap_conn_update_evt(const struct nble_gap_conn_update_evt *evt); + +struct nble_gap_adv_report_evt { + bt_addr_le_t addr; + int8_t rssi; + uint8_t adv_type; +}; + +void on_nble_gap_adv_report_evt(const struct nble_gap_adv_report_evt *evt, + const uint8_t *buf, 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); + +#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]; +}; + +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 { + 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); + +struct nble_gap_sm_passkey_disp_evt { + uint16_t conn_handle; + uint32_t passkey; +}; + +void on_nble_gap_sm_passkey_display_evt(const struct nble_gap_sm_passkey_disp_evt *evt); + +struct nble_link_sec { + bt_security_t sec_level; + uint8_t enc_size; +}; + +struct nble_gap_sm_status_evt { + uint16_t conn_handle; + uint8_t evt_type; + int status; + struct nble_link_sec enc_link_sec; +}; + +void on_nble_gap_sm_status_evt(const struct nble_gap_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 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 ble_get_info_rsp { + int status; /* Response status */ + uint8_t info_type; /* Requested information type */ + struct ble_gap_bonded_dev_info info_params; +}; + +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); + +struct nble_gap_sm_bond_info_param { + 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); + +struct nble_gap_sm_bond_info { + int err; + uint8_t addr_count; + uint8_t irk_count; +}; + +struct nble_gap_sm_bond_info_rsp { + ble_bond_info_cb_t cb; + void *user_data; + struct nble_gap_sm_bond_info info; +}; + +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 ble_gap_get_bonding_info(ble_bond_info_cb_t func, void *user_data, + bool include_bonded_addrs); + +void ble_gap_get_version(ble_get_version_cb_t func); + +#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 new file mode 100644 index 00000000..25ac4da8 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble_service/gatt_internal.h @@ -0,0 +1,308 @@ +/* + * 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 GATT_INTERNAL_H_ +#define GATT_INTERNAL_H_ + +#include +#include + +/* Forward declarations */ +struct nble_response; + +#define BLE_GATT_MTU_SIZE 23 + +/* + * Internal APIs used between host and BLE controller + * 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, +}; + +struct nble_gatt_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 { + int status; + struct bt_gatt_attr *attr_base; + /* Number of attributes successfully added */ + uint8_t attr_count; +}; + +enum nble_gatt_wr_flag { + NBLE_GATT_WR_FLAG_REPLY = 1, + NBLE_GATT_WR_FLAG_PREP = 2, +}; + +struct nble_gatt_wr_evt { + struct bt_gatt_attr *attr; + uint16_t conn_handle; + uint16_t offset; + uint8_t flag; /* Cf. enum nble_gatt_wr_flag */ +}; + +struct nble_gatt_wr_exec_evt { + uint16_t conn_handle; + uint8_t flag; +}; + +struct nble_gatt_rd_evt { + struct bt_gatt_attr *attr; + uint16_t conn_handle; + uint16_t offset; +}; + +struct nble_gatts_rd_reply_params { + uint16_t conn_handle; + uint16_t offset; + int32_t status; +}; + +struct nble_gatts_wr_reply_params { + uint16_t conn_handle; + int32_t status; +}; + +struct nble_gatt_notif_ind_params { + const struct bt_gatt_attr *attr; + uint16_t offset; +}; + +struct nble_gatt_send_notif_params { + /* 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_gatt_notif_rsp { + bt_gatt_notify_sent_func_t cback; + int status; + uint16_t conn_handle; + struct bt_gatt_attr *attr; +}; + +struct nble_gatt_send_ind_params { + /* 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_gatt_ind_rsp { + bt_gatt_indicate_func_t cback; + int status; + uint16_t conn_handle; + struct bt_gatt_attr *attr; +}; + +struct nble_gatt_handle_range { + uint16_t start_handle; + uint16_t end_handle; +}; + +struct nble_gattc_primary { + uint16_t handle; + struct nble_gatt_handle_range range; + struct bt_uuid_128 uuid; +}; + +struct nble_gattc_included { + uint16_t handle; + struct nble_gatt_handle_range range; + struct bt_uuid_128 uuid; +}; + +struct nble_gattc_characteristic { + uint16_t handle; + uint8_t prop; + uint16_t value_handle; + struct bt_uuid_128 uuid; +}; + +struct nble_gattc_descriptor { + uint16_t handle; + struct bt_uuid_128 uuid; +}; + +struct nble_gattc_discover_rsp { + int32_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 + +struct nble_discover_params { + 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_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[]; +}; + +struct ble_gattc_read_params { + 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; +}; + +struct ble_gattc_read_rsp { + int status; + void *user_data; + uint16_t conn_handle; + uint16_t handle; + uint16_t offset; +}; + +/* forward declaration */ +struct bt_gatt_write_params; + +typedef void (*bt_att_func_t)(struct bt_conn *conn, uint8_t err, + const struct bt_gatt_write_params *wr_params); + +struct bt_gatt_write_params { + /* Function invoked upon write response */ + bt_att_func_t func; + /* User specific data */ + void *user_data[2]; +}; + +struct ble_gattc_write_params { + 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 ble_gattc_write_rsp { + uint16_t conn_handle; + int status; + uint16_t handle; + uint16_t len; + struct bt_gatt_write_params 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 bt_gatt_connected(struct bt_conn *conn); +void bt_gatt_disconnected(struct bt_conn *conn); + + +struct ble_gattc_value_evt { + uint16_t conn_handle; + int status; + uint16_t handle; + uint8_t type; +}; + +void on_nble_gattc_value_evt(const struct ble_gattc_value_evt *evt, + uint8_t *buf, uint8_t buflen); + +#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 new file mode 100644 index 00000000..4a128f13 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble_service/nble_driver.c @@ -0,0 +1,354 @@ +/* + * 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 + +#include "nble_driver.h" + +#include "portable.h" + +/* ipc/rpc uart interface */ +#include "os/os.h" +#include "infra/ipc_requests.h" +#include "infra/port.h" +#include "infra/log.h" +#include "drivers/soc_gpio.h" +#include "drivers/ipc_uart_ns16550.h" + +#include "platform.h" + +#include "rpc.h" + +#include "util/misc.h" + +#include "infra/time.h" + +#include "infra/ipc_uart.h" + + + +/* + * Macro definition for reset pin + * Curie and other board - Everything should be working out of the box + */ +#define BLE_SW_CLK_PIN 27 +#define BLE_SWDIO_PIN 6 +#define RESET_PIN BLE_SWDIO_PIN +#define QRK_BLE_INT 5 + +static uint16_t rpc_port_id; +static list_head_t m_rpc_tx_q; + +extern void on_nble_curie_log(char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + log_vprintk(LOG_LEVEL_INFO, LOG_MODULE_BLE, fmt, args); + va_end(args); +} + +/* + * When we set val to 1 it will wake up the remote (BLE Core), setting it to 0 + * will allow remote to sleep. + */ +static int nble_wake_assert(bool val) +{ + val = true; + uint8_t ret = soc_gpio_write(SOC_GPIO_32, QRK_BLE_INT, val); + + //pr_debug(LOG_MODULE_BLE, "BLE wake up: %d", val); + if (ret != DRV_RC_OK) { + pr_debug(LOG_MODULE_BLE, "Error setting QRK_BLE_INT %d", ret); + } + return ret; +} + +/** + * Function registered to be invoked when the IPC starts or ends + * a transmission session. + * + * This sets the wake state of ble core to either keep it awake at start of a tx + * or to allow sleep at the end of a TX. + * + * @param wake_state false if remote may sleep (end of transmission). + * true, wake remote to start a transmission session. + * @param ignored not used + */ +static void nble_ipc_tx_wake_cb(bool wake_state, void *ignored) +{ + nble_wake_assert(wake_state); +} + +static int nble_interface_init(void) +{ + DRIVER_API_RC ret = DRV_RC_OK; + /* setup IPC UART reference */ + ipc_uart_ns16550_set_tx_cb(nble_ipc_tx_wake_cb, NULL); + + /* Configure GPIO as output and high by default */ + gpio_cfg_data_t config; + config.gpio_type = GPIO_OUTPUT; + ret = soc_gpio_set_config(SOC_GPIO_32, QRK_BLE_INT, &config); + if (ret != DRV_RC_OK) + return -1; + + list_init(&m_rpc_tx_q); + + ret = nble_wake_assert(1); + return ret; +} + +void uart_ipc_disable(void) +{ + ipc_uart_ns16550_disable(SYNC_CHANNEL); +} + +static void *m_rpc_channel; + +struct rpc_tx_elt { + list_t l; + uint16_t length; + uint8_t data[0]; +}; + +/** + * Try to send a element of the RPC waiting list + * + * @param l Pointer to the list element to try to send on the UART + * @return + */ +static int uart_rpc_try_tx(list_t *l) +{ + struct rpc_tx_elt *p_elt; + + /* Retrieve the RPC TX element from the list pointer */ + p_elt = container_of(l, struct rpc_tx_elt, l); + + /* Try to send the element payload */ + return ipc_uart_ns16550_send_pdu(m_rpc_channel, + p_elt->length, + p_elt->data); +} + +/** + * Try to send an RPC TX queue element during the free operation + * of the previous message. This is invoked under interrupt context + * and therefore does not require protection. It is also expected + * that the tx operation can not fail. + */ +static void uart_rpc_try_tx_on_free(void) +{ + list_t *l; + int ret; + + /* Get next element in tx q */ + l = list_get(&m_rpc_tx_q); + if (l) { + ret = uart_rpc_try_tx(l); + + /* It is not possible to fail when called on free event */ + assert(ret == IPC_UART_ERROR_OK); + } +} + +/** + * Try to send an RPC TX queue element after enqueuing an element to the + * RPC TX queue. At this point the state of the UART driver is not known + * and there could be a transmission in progress, so the procedure is to + * protect from interruption, pick (not get) the first element and only + * get it out of the queue if the tx operation was successful. + */ +static void uart_rpc_try_tx_on_add(void) +{ + list_t *l; + int ret; + + int flags = interrupt_lock(); + + /* Pick next element in tx q */ + l = m_rpc_tx_q.head; + if (l) { + ret = uart_rpc_try_tx(l); + + /* If it was sent correctly, remove it from the queue */ + if (ret == IPC_UART_ERROR_OK) { + l = list_get(&m_rpc_tx_q); + } + } + + interrupt_unlock(flags); +} + +/** + * Function handling the events from the UART IPC (irq). + * + * @param channel Channel on which the event applies + * @param request IPC_MSG_TYPE_MESSAGE when a new message was received, + * IPC_MSG_TYPE_FREE when the previous message was sent and can be freed. + * @param len Length of the data + * @param p_data Pointer to the data + * @return 0 + */ +static int uart_ipc_rpc_cback(int channel, int request, int len, void *p_data) +{ + switch (request) { + case IPC_MSG_TYPE_MESSAGE: { +#ifdef CONFIG_RPC_IN + /* 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); +} + MESSAGE_ID(&rpc->msg) = 0; + MESSAGE_LEN(&rpc->msg) = sizeof(*rpc); + MESSAGE_SRC(&rpc->msg) = rpc_port_id; + MESSAGE_DST(&rpc->msg) = rpc_port_id; + MESSAGE_TYPE(&rpc->msg) = TYPE_INT; + rpc->p_data = p_data; + rpc->len = len; + if (port_send_message(&rpc->msg) != E_OS_OK) + panic(-1); +#endif + } + break; + case IPC_MSG_TYPE_FREE: + { + /* Free the message */ + struct rpc_tx_elt *p_elt; + + p_elt = container_of(p_data, struct rpc_tx_elt, data); + bfree(p_elt); + + //pr_debug(LOG_MODULE_IPC, "%s:%p", __FUNCTION__, p_elt); + + /* Try to send another message immediately */ + uart_rpc_try_tx_on_free(); + break; + } + default: + /* Free the message */ + bfree(p_data); + pr_error(LOG_MODULE_BLE, "Unsupported RPC request"); + break; + } + return 0; +} + +uint8_t *rpc_alloc_cb(uint16_t length) +{ + struct rpc_tx_elt *p_elt; + + //pr_info(0, "%s", __FUNCTION__); + + p_elt = balloc(length + offsetof(struct rpc_tx_elt, data), NULL); + //pr_debug(LOG_MODULE_IPC, "%s:%p", __FUNCTION__, p_elt); + assert(p_elt != NULL); + + /* Save the length of the buffer */ + p_elt->length = length; + + return p_elt->data; +} + +/* called under NON-interrupt context */ +void rpc_transmit_cb(uint8_t *p_buf, uint16_t length) +{ + struct rpc_tx_elt *p_elt; + + p_elt = container_of(p_buf, struct rpc_tx_elt, data); + + list_add(&m_rpc_tx_q, &p_elt->l); + + uart_rpc_try_tx_on_add(); +} + +/* nble reset is achieved by asserting low the SWDIO pin. + * However, the BLE Core chip can be in SWD debug mode, and NRF_POWER->RESET = 0 due to, + * other constraints: therefore, this reset might not work everytime, especially after + * flashing or debugging. + */ +void nble_driver_init(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 }; + + 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; + + /* Open the UART channel for RPC while Nordic is in reset */ + m_rpc_channel = ipc_uart_channel_open(RPC_CHANNEL, uart_ipc_rpc_cback); + + while (get_uptime_32k() < delay_until); + + /* De-assert the reset */ + soc_gpio_write(SOC_GPIO_32, RESET_PIN, 1); + + + /* Set back GPIO to input to avoid interfering with external debugger */ + pin_cfg.gpio_type = GPIO_INPUT; + soc_gpio_set_config(SOC_GPIO_32, RESET_PIN, &pin_cfg); +} + + +void nble_driver_configure(T_QUEUE queue, void (*handler)(struct message*, void*)) +{ + rpc_port_id = port_alloc(queue); + assert(rpc_port_id != 0); + port_set_handler(rpc_port_id, handler, NULL); + pr_debug(LOG_MODULE_BLE, "%s: done port: %d", __func__, rpc_port_id); +} + + +void on_nble_curie_init(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 new file mode 100644 index 00000000..7ea15b44 --- /dev/null +++ b/system/libarc32_arduino101/framework/src/services/ble_service/nble_driver.h @@ -0,0 +1,55 @@ +/* + * 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. + */ + +#ifndef NBLE_DRIVER_H_ +#define NBLE_DRIVER_H_ + +#include "os/os.h" +#include "infra/message.h" + +struct ble_rpc_callin { + struct message msg; /**< Message header, MUST be first element of structure */ + uint8_t *p_data; /**< RPC buffer, must be freed after deserializing */ + uint16_t len; /**< length of above buffer */ +}; + +/** + * This resets and initializes the uart/ipc mechanism of nble. + * + * This this will trigger the call to @ref on_nble_up indicating that rpc + * mechanism is up and running. + */ +void nble_driver_init(void); + +void nble_driver_configure(T_QUEUE queue, void (*handler)(struct message*, void*)); + +void uart_ipc_disable(void); + +#endif /* NBLE_DRIVER_H_ */ diff --git a/variants/arduino_101/variant.cpp b/variants/arduino_101/variant.cpp index 0fe85c2d..72e75aae 100644 --- a/variants/arduino_101/variant.cpp +++ b/variants/arduino_101/variant.cpp @@ -22,6 +22,11 @@ #include "cfw_platform.h" #include "platform.h" +// Add for debug corelib +#ifdef CONFIGURE_DEBUG_CORELIB_ENABLED +#include +#endif + /* * Arduino 101 @@ -230,6 +235,11 @@ void initVariant( void ) variantAdcInit(); cfw_platform_init(); + + // Add for debug corelib + #ifdef CONFIGURE_DEBUG_CORELIB_ENABLED + log_init(); + #endif } #ifdef __cplusplus