mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-04-09 21:45:54 +00:00
added Arduino port that provides LE Central/GATT Client API with EM9301 single mode LE chipset
This commit is contained in:
parent
a3683d7720
commit
ca1bb42005
1
platforms/arduino/.gitignore
vendored
Normal file
1
platforms/arduino/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
btstack
|
625
platforms/arduino/BTstack.cpp
Normal file
625
platforms/arduino/BTstack.cpp
Normal file
@ -0,0 +1,625 @@
|
||||
/**
|
||||
* Arduino Wrapper for BTstack
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <SPI.h>
|
||||
|
||||
#include "BTstack.h"
|
||||
|
||||
#include "btstack_memory.h"
|
||||
#include "btstack/hal_tick.h"
|
||||
#include "btstack/hal_cpu.h"
|
||||
#include "btstack/hci_cmds.h"
|
||||
#include <btstack/utils.h>
|
||||
#include <btstack/run_loop.h>
|
||||
#include <btstack/sdp_util.h>
|
||||
|
||||
#include "bt_control_em9301.h"
|
||||
#include "hci.h"
|
||||
#include "hci_dump.h"
|
||||
#include "l2cap.h"
|
||||
#include "ad_parser.h"
|
||||
#include "att.h"
|
||||
#include "att_server.h"
|
||||
#include "le_device_db.h"
|
||||
#include "sm.h"
|
||||
#include "debug.h"
|
||||
|
||||
// Pin 13 has an LED connected on most Arduino boards.
|
||||
#define PIN_LED 13
|
||||
|
||||
// prototypes
|
||||
extern "C" void embedded_execute_once(void);
|
||||
extern "C" void hal_uart_dma_process(void);
|
||||
|
||||
// HAL TICK Implementation
|
||||
extern "C" void hal_tick_init(void){
|
||||
|
||||
}
|
||||
extern "C" void hal_tick_set_handler(void (*tick_handler)(void)){
|
||||
|
||||
}
|
||||
extern "C" int hal_tick_get_tick_period_in_ms(void){
|
||||
return 250;
|
||||
}
|
||||
|
||||
// btstack state
|
||||
static int btstack_state;
|
||||
|
||||
// HAL CPU Implementation
|
||||
extern "C" void hal_cpu_disable_irqs(void){ }
|
||||
extern "C" void hal_cpu_enable_irqs(void) { }
|
||||
extern "C" void hal_cpu_enable_irqs_and_sleep(void) { }
|
||||
|
||||
static const uint8_t adv_data_default[] = { 02, 01, 05, 03, 02, 0xf0, 0xff };
|
||||
static const uint8_t * adv_data = adv_data_default;
|
||||
static uint16_t adv_data_len = sizeof(adv_data_default);
|
||||
static uint16_t gatt_client_id;
|
||||
static int gatt_is_characteristics_query;
|
||||
|
||||
typedef enum gattAction {
|
||||
gattActionWrite,
|
||||
gattActionSubscribe,
|
||||
gattActionUnsubscribe,
|
||||
gattActionServiceQuery,
|
||||
gattActionCharacteristicQuery,
|
||||
gattActionRead,
|
||||
} gattAction_t;
|
||||
|
||||
static gattAction_t gattAction;
|
||||
|
||||
// static btstack_packet_handler_t client_packet_handler = NULL;
|
||||
static int client_mode = 0;
|
||||
static bool have_custom_addr;
|
||||
static bd_addr_t public_bd_addr;
|
||||
|
||||
static timer_source_t connection_timer;
|
||||
|
||||
static void (*bleAdvertismentCallback)(BLEAdvertisement * bleAdvertisement) = NULL;
|
||||
static void (*bleDeviceConnectedCallback)(BLEStatus status, BLEDevice * device)= NULL;
|
||||
static void (*bleDeviceDisconnectedCallback)(BLEDevice * device) = NULL;
|
||||
static void (*gattServiceDiscoveredCallback)(BLEStatus status, BLEDevice * device, BLEService * bleService) = NULL;
|
||||
static void (*gattCharacteristicDiscoveredCallback)(BLEStatus status, BLEDevice * device, BLECharacteristic * characteristic) = NULL;
|
||||
static void (*gattCharacteristicNotificationCallback)(BLEDevice * device, uint16_t value_handle, uint8_t* value, uint16_t length) = NULL;
|
||||
static void (*gattCharacteristicReadCallback)(BLEStatus status, BLEDevice * device, uint8_t * value, uint16_t length) = NULL;
|
||||
static void (*gattCharacteristicWrittenCallback)(BLEStatus status, BLEDevice * device) = NULL;
|
||||
static void (*gattCharacteristicSubscribedCallback)(BLEStatus status, BLEDevice * device) = NULL;
|
||||
static void (*gattCharacteristicUnsubscribedCallback)(BLEStatus status, BLEDevice * device) = NULL;
|
||||
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
|
||||
bd_addr_t addr;
|
||||
uint16_t handle;
|
||||
|
||||
switch (packet_type) {
|
||||
|
||||
case HCI_EVENT_PACKET:
|
||||
switch (packet[0]) {
|
||||
|
||||
case BTSTACK_EVENT_STATE:
|
||||
btstack_state = packet[2];
|
||||
// bt stack activated, get started
|
||||
// if (packet[2] == HCI_STATE_WORKING) {
|
||||
// if (client_mode) {
|
||||
// emit_stack_ready();
|
||||
// return;
|
||||
// }
|
||||
// // printf("1 - hci_le_set_advertising_parameters\n");
|
||||
// hci_send_cmd(&hci_le_set_advertising_parameters, 0x0400, 0x0800, 0, 0, 0, &addr, 0x07, 0);
|
||||
// }
|
||||
break;
|
||||
|
||||
case HCI_EVENT_DISCONNECTION_COMPLETE:
|
||||
if (bleDeviceDisconnectedCallback) {
|
||||
handle = READ_BT_16(packet, 3);
|
||||
BLEDevice device(handle);
|
||||
(*bleDeviceDisconnectedCallback)(&device);
|
||||
}
|
||||
break;
|
||||
|
||||
case GAP_LE_ADVERTISING_REPORT: {
|
||||
if (bleAdvertismentCallback) {
|
||||
BLEAdvertisement advertisement(packet);
|
||||
(*bleAdvertismentCallback)(&advertisement);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)) {
|
||||
bt_flip_addr(addr, &packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE + 1]);
|
||||
printf("Local Address: %s\n", bd_addr_to_str(addr));
|
||||
break;
|
||||
}
|
||||
// if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_advertising_parameters)){
|
||||
// printf("2 - hci_le_set_advertising_data\n");
|
||||
// hci_send_cmd(&hci_le_set_advertising_data, adv_data_len, adv_data);
|
||||
// break;
|
||||
// }
|
||||
// if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_advertising_data)){
|
||||
// printf("3 - hci_le_set_advertise_enable\n");
|
||||
// hci_send_cmd(&hci_le_set_advertise_enable, 1);
|
||||
// break;
|
||||
// }
|
||||
// if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_advertise_enable)){
|
||||
// emit_stack_ready();
|
||||
// break;
|
||||
// }
|
||||
break;
|
||||
|
||||
case HCI_EVENT_LE_META:
|
||||
switch (packet[2]) {
|
||||
case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
|
||||
handle = READ_BT_16(packet, 4);
|
||||
printf("Connection complete, handle 0x%04x\n", handle);
|
||||
run_loop_remove_timer(&connection_timer);
|
||||
if (!bleDeviceConnectedCallback) break;
|
||||
if (packet[3]){
|
||||
(*bleDeviceConnectedCallback)(BLE_STATUS_CONNECTION_ERROR, NULL);
|
||||
} else {
|
||||
BLEDevice device(handle);
|
||||
(*bleDeviceConnectedCallback)(BLE_STATUS_OK, &device);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if (client_packet_handler){
|
||||
// (*client_packet_handler)(packet_type, channel, packet, size);
|
||||
// }
|
||||
}
|
||||
|
||||
static void gatt_client_callback(le_event_t * event){
|
||||
// le_characteristic_t characteristic;
|
||||
// le_characteristic_value_event_t * value_event;
|
||||
gatt_complete_event_t * gatt_complete_event;
|
||||
|
||||
BLEDevice device(event->handle);
|
||||
switch(event->type){
|
||||
case GATT_SERVICE_QUERY_RESULT:
|
||||
if (gattServiceDiscoveredCallback) {
|
||||
BLEService bleService(((le_service_event_t *) event)->service);
|
||||
(*gattServiceDiscoveredCallback)(BLE_STATUS_OK, &device, &bleService);
|
||||
}
|
||||
break;
|
||||
case GATT_CHARACTERISTIC_QUERY_RESULT:
|
||||
if (gattCharacteristicDiscoveredCallback){
|
||||
BLECharacteristic bleCharacteristic(((le_characteristic_event_t *) event)->characteristic);
|
||||
(*gattCharacteristicDiscoveredCallback)(BLE_STATUS_OK, &device, &bleCharacteristic);
|
||||
}
|
||||
break;
|
||||
case GATT_QUERY_COMPLETE:
|
||||
gatt_complete_event = (gatt_complete_event_t*) event;
|
||||
switch (gattAction){
|
||||
case gattActionWrite:
|
||||
if (gattCharacteristicWrittenCallback) gattCharacteristicWrittenCallback(gatt_complete_event->status ? BLE_STATUS_OTHER_ERROR : BLE_STATUS_OK, &device);
|
||||
break;
|
||||
case gattActionSubscribe:
|
||||
if (gattCharacteristicSubscribedCallback) gattCharacteristicSubscribedCallback(gatt_complete_event->status ? BLE_STATUS_OTHER_ERROR : BLE_STATUS_OK, &device);
|
||||
break;
|
||||
case gattActionUnsubscribe:
|
||||
if (gattCharacteristicUnsubscribedCallback) gattCharacteristicUnsubscribedCallback(gatt_complete_event->status ? BLE_STATUS_OTHER_ERROR : BLE_STATUS_OK, &device);
|
||||
break;
|
||||
case gattActionServiceQuery:
|
||||
if (gattServiceDiscoveredCallback) gattServiceDiscoveredCallback(BLE_STATUS_DONE, &device, NULL);
|
||||
break;
|
||||
case gattActionCharacteristicQuery:
|
||||
if (gattCharacteristicDiscoveredCallback) gattCharacteristicDiscoveredCallback(BLE_STATUS_DONE, &device, NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
case GATT_NOTIFICATION:
|
||||
case GATT_INDICATION:
|
||||
if (gattCharacteristicNotificationCallback) {
|
||||
le_characteristic_value_event_t * value_event = (le_characteristic_value_event_t *) event;
|
||||
(*gattCharacteristicNotificationCallback)(&device, value_event->value_handle, value_event->blob, value_event->blob_length);
|
||||
}
|
||||
break;
|
||||
case GATT_CHARACTERISTIC_VALUE_QUERY_RESULT:
|
||||
if (gattCharacteristicReadCallback) {
|
||||
le_characteristic_value_event_t * value_event = (le_characteristic_value_event_t *) event;
|
||||
(*gattCharacteristicReadCallback)(BLE_STATUS_OK, &device, value_event->blob, value_event->blob_length);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void connection_timeout_handler(timer_source_t * timer){
|
||||
// log_info("Cancel outgoing connection");
|
||||
le_central_connect_cancel();
|
||||
if (!bleDeviceConnectedCallback) return;
|
||||
(*bleDeviceConnectedCallback)(BLE_STATUS_CONNECTION_TIMEOUT, NULL); // page timeout 0x04
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
static int nibble_for_char(const char c){
|
||||
if ('0' <= c && c <= '9') return c - '0';
|
||||
if ('a' <= c && c <= 'f') return c - 'a' + 10;
|
||||
if ('A' <= c && c <= 'F') return c - 'A' + 10;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// UUID class
|
||||
UUID::UUID(){
|
||||
memset(uuid, 0, 16);
|
||||
}
|
||||
|
||||
UUID::UUID(const uint8_t uuid[16]){
|
||||
memcpy(this->uuid, uuid, 16);
|
||||
}
|
||||
|
||||
UUID::UUID(const char * uuidStr){
|
||||
memset(uuid, 0, 16);
|
||||
int len = strlen(uuidStr);
|
||||
if (len <= 4){
|
||||
// Handle 4 Bytes HEX
|
||||
uint16_t uuid16;
|
||||
int result = sscanf( (char *) uuidStr, "%x", &uuid16);
|
||||
if (result == 1){
|
||||
sdp_normalize_uuid(uuid, uuid16);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// quick UUID parser, ignoring dashes
|
||||
int i = 0;
|
||||
int data = 0;
|
||||
int have_nibble = 0;
|
||||
while(*uuidStr && i < 16){
|
||||
const char c = *uuidStr++;
|
||||
if (c == '-') continue;
|
||||
data = data << 4 | nibble_for_char(c);
|
||||
if (!have_nibble) {
|
||||
have_nibble = 1;
|
||||
continue;
|
||||
}
|
||||
uuid[i++] = data;
|
||||
data = 0;
|
||||
have_nibble = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t * UUID::getUuid(void) const {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
static char uuid16_buffer[5];
|
||||
const char * UUID::getUuidString() const {
|
||||
// TODO: fix sdp_has_blueooth_base_uuid call to use const
|
||||
if (sdp_has_blueooth_base_uuid((uint8_t*)uuid)){
|
||||
sprintf(uuid16_buffer, "%04x", (uint16_t) READ_NET_32(uuid, 0));
|
||||
return uuid16_buffer;
|
||||
} else {
|
||||
// TODO: fix uuid128_to_str
|
||||
return uuid128_to_str((uint8_t*)uuid);
|
||||
}
|
||||
}
|
||||
|
||||
const char * UUID::getUuid128String() const {
|
||||
return uuid128_to_str((uint8_t*)uuid);
|
||||
}
|
||||
|
||||
bool UUID::matches(UUID *other) const {
|
||||
return memcmp(this->uuid, other->uuid, 16) == 0;
|
||||
}
|
||||
|
||||
|
||||
// BD_ADDR class
|
||||
BD_ADDR::BD_ADDR(){
|
||||
}
|
||||
|
||||
BD_ADDR::BD_ADDR(const char * address_string, BD_ADDR_TYPE address_type ) : address_type(address_type) {
|
||||
// TODO: implement
|
||||
// log_error("BD_ADDR::BD_ADDR(const char *, BD_ADDR_TYPE) not implemented yet!");
|
||||
}
|
||||
|
||||
BD_ADDR::BD_ADDR(const uint8_t address[6], BD_ADDR_TYPE address_type) : address_type(address_type){
|
||||
memcpy(this->address, address, 6);
|
||||
}
|
||||
|
||||
const uint8_t * BD_ADDR::getAddress(){
|
||||
return address;
|
||||
}
|
||||
|
||||
const char * BD_ADDR::getAddressString(){
|
||||
return bd_addr_to_str(address);
|
||||
}
|
||||
|
||||
BD_ADDR_TYPE BD_ADDR::getAddressType(){
|
||||
return address_type;
|
||||
}
|
||||
|
||||
|
||||
BLEAdvertisement::BLEAdvertisement(uint8_t * event_packet) :
|
||||
advertising_event_type(event_packet[2]),
|
||||
rssi(event_packet[10]),
|
||||
data_length(event_packet[11])
|
||||
{
|
||||
bd_addr_t addr;
|
||||
bt_flip_addr(addr, &event_packet[4]);
|
||||
bd_addr = BD_ADDR(addr, (BD_ADDR_TYPE)event_packet[3]);
|
||||
memcpy(data, &event_packet[12], LE_ADVERTISING_DATA_SIZE);
|
||||
}
|
||||
|
||||
const uint8_t * BLEAdvertisement::getAdvData(){
|
||||
return data;
|
||||
}
|
||||
|
||||
BD_ADDR * BLEAdvertisement::getBdAddr(void){
|
||||
return &bd_addr;
|
||||
}
|
||||
|
||||
int BLEAdvertisement::getRssi(){
|
||||
return rssi > 127 ? rssi - 256 : rssi;
|
||||
}
|
||||
|
||||
|
||||
bool BLEAdvertisement::containsService(UUID * service){
|
||||
return ad_data_contains_uuid128(data_length, data, (uint8_t*) service->getUuid());
|
||||
}
|
||||
|
||||
bool BLEAdvertisement::nameHasPrefix(const char * namePrefix){
|
||||
return false;
|
||||
};
|
||||
|
||||
BLECharacteristic::BLECharacteristic() {
|
||||
}
|
||||
|
||||
BLECharacteristic::BLECharacteristic(le_characteristic_t characteristic)
|
||||
: characteristic(characteristic), uuid(characteristic.uuid128) {
|
||||
}
|
||||
|
||||
const UUID * BLECharacteristic::getUUID(){
|
||||
return &uuid;
|
||||
}
|
||||
|
||||
bool BLECharacteristic::matches(UUID * uuid){
|
||||
return this->uuid.matches(uuid);
|
||||
}
|
||||
|
||||
bool BLECharacteristic::isValueHandle(uint16_t value_handle){
|
||||
return characteristic.value_handle == value_handle;
|
||||
}
|
||||
|
||||
const le_characteristic_t * BLECharacteristic::getCharacteristic() {
|
||||
return &characteristic;
|
||||
}
|
||||
|
||||
|
||||
BLEService::BLEService(){
|
||||
}
|
||||
|
||||
BLEService::BLEService(le_service_t service)
|
||||
: service(service), uuid(service.uuid128){
|
||||
}
|
||||
|
||||
const UUID * BLEService::getUUID(){
|
||||
return &uuid;
|
||||
}
|
||||
|
||||
bool BLEService::matches(UUID * uuid){
|
||||
return this->uuid.matches(uuid);
|
||||
}
|
||||
|
||||
const le_service_t * BLEService::getService(){
|
||||
return &service;
|
||||
}
|
||||
|
||||
// discovery of services and characteristics
|
||||
BLEDevice::BLEDevice(){
|
||||
}
|
||||
BLEDevice::BLEDevice(uint16_t handle)
|
||||
: handle(handle){
|
||||
}
|
||||
uint16_t BLEDevice::getHandle(){
|
||||
return handle;
|
||||
}
|
||||
int BLEDevice::discoverGATTServices(){
|
||||
return BTstack.discoverGATTServices(this);
|
||||
}
|
||||
int BLEDevice::discoverCharacteristicsForService(BLEService * service){
|
||||
return BTstack.discoverCharacteristicsForService(this, service);
|
||||
}
|
||||
int BLEDevice::readCharacteristic(BLECharacteristic * characteristic){
|
||||
return BTstack.readCharacteristic(this, characteristic);
|
||||
}
|
||||
int BLEDevice::writeCharacteristic(BLECharacteristic * characteristic, uint8_t * data, uint16_t size){
|
||||
return BTstack.writeCharacteristic(this, characteristic, data, size);
|
||||
}
|
||||
int BLEDevice::writeCharacteristicWithoutResponse(BLECharacteristic * characteristic, uint8_t * data, uint16_t size){
|
||||
return BTstack.writeCharacteristicWithoutResponse(this, characteristic, data, size);
|
||||
}
|
||||
int BLEDevice::subscribeForNotifications(BLECharacteristic * characteristic){
|
||||
return BTstack.subscribeForNotifications(this, characteristic);
|
||||
}
|
||||
int BLEDevice::unsubscribeFromNotifications(BLECharacteristic * characteristic){
|
||||
return BTstack.unsubscribeFromNotifications(this, characteristic);
|
||||
}
|
||||
|
||||
|
||||
BTstackManager::BTstackManager() {
|
||||
// client_packet_handler = NULL;
|
||||
have_custom_addr = false;
|
||||
// reset handler
|
||||
bleAdvertismentCallback = NULL;
|
||||
bleDeviceConnectedCallback = NULL;
|
||||
bleDeviceDisconnectedCallback = NULL;
|
||||
gattServiceDiscoveredCallback = NULL;
|
||||
gattCharacteristicDiscoveredCallback = NULL;
|
||||
gattCharacteristicNotificationCallback = NULL;
|
||||
}
|
||||
|
||||
void BTstackManager::setBLEAdvertisementCallback(void (*callback)(BLEAdvertisement * bleAdvertisement)){
|
||||
bleAdvertismentCallback = callback;
|
||||
}
|
||||
void BTstackManager::setBLEDeviceConnectedCallback(void (*callback)(BLEStatus status, BLEDevice * device)){
|
||||
bleDeviceConnectedCallback = callback;
|
||||
}
|
||||
void BTstackManager::setBLEDeviceDisconnectedCallback(void (*callback)(BLEDevice * device)){
|
||||
bleDeviceDisconnectedCallback = callback;
|
||||
}
|
||||
void BTstackManager::setGATTServiceDiscoveredCallback(void (*callback)(BLEStatus status, BLEDevice * device, BLEService * bleService)){
|
||||
gattServiceDiscoveredCallback = callback;
|
||||
}
|
||||
void BTstackManager::setGATTCharacteristicDiscoveredCallback(void (*callback)(BLEStatus status, BLEDevice * device, BLECharacteristic * characteristic)){
|
||||
gattCharacteristicDiscoveredCallback = callback;
|
||||
}
|
||||
void BTstackManager::setGATTCharacteristicNotificationCallback(void (*callback)(BLEDevice * device, uint16_t value_handle, uint8_t* value, uint16_t length)){
|
||||
gattCharacteristicNotificationCallback = callback;
|
||||
}
|
||||
void BTstackManager::setGATTCharacteristicReadCallback(void (*callback)(BLEStatus status, BLEDevice * device, uint8_t * value, uint16_t length)){
|
||||
gattCharacteristicReadCallback = callback;
|
||||
}
|
||||
void BTstackManager::setGATTCharacteristicWrittenCallback(void (*callback)(BLEStatus status, BLEDevice * device)){
|
||||
gattCharacteristicWrittenCallback = callback;
|
||||
}
|
||||
void BTstackManager::setGATTCharacteristicSubscribedCallback(void (*callback)(BLEStatus status, BLEDevice * device)){
|
||||
gattCharacteristicSubscribedCallback = callback;
|
||||
}
|
||||
void BTstackManager::setGATTCharacteristicUnsubscribedCallback(void (*callback)(BLEStatus status, BLEDevice * device)){
|
||||
gattCharacteristicUnsubscribedCallback = callback;
|
||||
}
|
||||
|
||||
int BTstackManager::discoverGATTServices(BLEDevice * device){
|
||||
gattAction = gattActionServiceQuery;
|
||||
return gatt_client_discover_primary_services(gatt_client_id, device->getHandle());
|
||||
}
|
||||
int BTstackManager::discoverCharacteristicsForService(BLEDevice * device, BLEService * service){
|
||||
gattAction = gattActionCharacteristicQuery;
|
||||
return gatt_client_discover_characteristics_for_service(gatt_client_id, device->getHandle(), (le_service_t*) service->getService());
|
||||
}
|
||||
int BTstackManager::readCharacteristic(BLEDevice * device, BLECharacteristic * characteristic){
|
||||
return gatt_client_read_value_of_characteristic(gatt_client_id, device->getHandle(), (le_characteristic_t*) characteristic->getCharacteristic());
|
||||
}
|
||||
int BTstackManager::writeCharacteristic(BLEDevice * device, BLECharacteristic * characteristic, uint8_t * data, uint16_t size){
|
||||
gattAction = gattActionWrite;
|
||||
return gatt_client_write_value_of_characteristic(gatt_client_id, device->getHandle(), characteristic->getCharacteristic()->value_handle,
|
||||
size, data);
|
||||
}
|
||||
int BTstackManager::writeCharacteristicWithoutResponse(BLEDevice * device, BLECharacteristic * characteristic, uint8_t * data, uint16_t size){
|
||||
return gatt_client_write_value_of_characteristic_without_response(gatt_client_id, device->getHandle(), characteristic->getCharacteristic()->value_handle,
|
||||
size, data);
|
||||
}
|
||||
int BTstackManager::subscribeForNotifications(BLEDevice * device, BLECharacteristic * characteristic){
|
||||
gattAction = gattActionSubscribe;
|
||||
return gatt_client_write_client_characteristic_configuration(gatt_client_id, device->getHandle(), (le_characteristic_t*) characteristic->getCharacteristic(),
|
||||
GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION);
|
||||
}
|
||||
int BTstackManager::unsubscribeFromNotifications(BLEDevice * device, BLECharacteristic * characteristic){
|
||||
gattAction = gattActionUnsubscribe;
|
||||
return gatt_client_write_client_characteristic_configuration(gatt_client_id, device->getHandle(), (le_characteristic_t*) characteristic->getCharacteristic(),
|
||||
GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NONE);
|
||||
}
|
||||
void BTstackManager::bleConnect(BLEAdvertisement * advertisement, int timeout_ms){
|
||||
bleConnect(advertisement->getBdAddr(), timeout_ms);
|
||||
}
|
||||
void BTstackManager::bleConnect(BD_ADDR * address, int timeout_ms){
|
||||
bleConnect(address->getAddressType(), address->getAddress(), timeout_ms);
|
||||
}
|
||||
void BTstackManager::bleConnect(BD_ADDR_TYPE address_type, const char * address, int timeout_ms){
|
||||
// TOOD: implement
|
||||
// log_error("BTstackManager::bleConnect(BD_ADDR_TYPE address_type, const char * address, int timeout_ms) not implemented");
|
||||
}
|
||||
void BTstackManager::bleConnect(BD_ADDR_TYPE address_type, const uint8_t address[6], int timeout_ms){
|
||||
le_central_connect((uint8_t*)address, (bd_addr_type_t) address_type);
|
||||
if (!timeout_ms) return;
|
||||
run_loop_set_timer(&connection_timer, timeout_ms);
|
||||
run_loop_set_timer_handler(&connection_timer, connection_timeout_handler);
|
||||
run_loop_add_timer(&connection_timer);
|
||||
}
|
||||
|
||||
void BTstackManager::bleDisconnect(BLEDevice * device){
|
||||
run_loop_remove_timer(&connection_timer);
|
||||
}
|
||||
|
||||
void BTstackManager::registerPacketHandler(btstack_packet_handler_t packet_handler){
|
||||
// client_packet_handler = packet_handler;
|
||||
}
|
||||
|
||||
void BTstackManager::setClientMode(){
|
||||
client_mode = 1;
|
||||
}
|
||||
|
||||
void BTstackManager::setAdvData(uint16_t size, const uint8_t * data){
|
||||
adv_data = data;
|
||||
adv_data_len = size;
|
||||
}
|
||||
|
||||
void BTstackManager::setPublicBdAddr(bd_addr_t addr){
|
||||
have_custom_addr = true;
|
||||
memcpy(public_bd_addr, addr ,6);
|
||||
}
|
||||
|
||||
// static hci_uart_config_t config;
|
||||
|
||||
void BTstackManager::setup(){
|
||||
|
||||
#ifdef PIN_LED
|
||||
pinMode(PIN_LED, OUTPUT);
|
||||
#endif
|
||||
|
||||
printf("BTstackManager::setup()\n");
|
||||
|
||||
btstack_memory_init();
|
||||
run_loop_init(RUN_LOOP_EMBEDDED);
|
||||
|
||||
hci_dump_open(NULL, HCI_DUMP_STDOUT);
|
||||
|
||||
hci_transport_t * transport = hci_transport_h4_dma_instance();
|
||||
bt_control_t * control = bt_control_em9301_instance();
|
||||
hci_init(transport, NULL, control, NULL);
|
||||
|
||||
if (have_custom_addr){
|
||||
hci_set_bd_addr(public_bd_addr);
|
||||
}
|
||||
|
||||
l2cap_init();
|
||||
|
||||
// setup central device db
|
||||
le_device_db_init();
|
||||
|
||||
sm_init();
|
||||
|
||||
att_server_init(NULL, NULL, NULL);
|
||||
att_server_register_packet_handler(packet_handler);
|
||||
|
||||
gatt_client_init();
|
||||
gatt_client_id = gatt_client_register_packet_handler(gatt_client_callback);
|
||||
|
||||
// turn on!
|
||||
btstack_state = 0;
|
||||
hci_power_control(HCI_POWER_ON);
|
||||
|
||||
// poll until working
|
||||
while (btstack_state != HCI_STATE_WORKING){
|
||||
loop();
|
||||
}
|
||||
printf("--> READY <--\n");
|
||||
}
|
||||
|
||||
void BTstackManager::loop(){
|
||||
// process data from/to Bluetooth module
|
||||
hal_uart_dma_process();
|
||||
// BTstack Run Loop
|
||||
embedded_execute_once();
|
||||
}
|
||||
|
||||
void BTstackManager::bleStartScanning(){
|
||||
printf("Start scanning\n");
|
||||
le_central_start_scan();
|
||||
}
|
||||
void BTstackManager::bleStopScanning(){
|
||||
le_central_stop_scan();
|
||||
}
|
||||
|
||||
BTstackManager BTstack;
|
||||
|
169
platforms/arduino/BTstack.h
Normal file
169
platforms/arduino/BTstack.h
Normal file
@ -0,0 +1,169 @@
|
||||
/**
|
||||
* Arduino Wrapper for BTstack
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "att.h"
|
||||
#include <btstack/utils.h>
|
||||
#include "gatt_client.h"
|
||||
#include "hci.h"
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum BLEStatus {
|
||||
BLE_STATUS_OK,
|
||||
BLE_STATUS_DONE, // e.g. for service or characteristic discovery done
|
||||
BLE_STATUS_CONNECTION_TIMEOUT,
|
||||
BLE_STATUS_CONNECTION_ERROR,
|
||||
BLE_STATUS_OTHER_ERROR
|
||||
} BLEStatus;
|
||||
|
||||
typedef void (*btstack_packet_handler_t) (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
|
||||
class UUID {
|
||||
private:
|
||||
uint8_t uuid[16];
|
||||
public:
|
||||
UUID();
|
||||
UUID(const uint8_t uuid[16]);
|
||||
UUID(const char * uuidStr);
|
||||
const char * getUuidString() const;
|
||||
const char * getUuid128String() const;
|
||||
const uint8_t * getUuid(void) const;
|
||||
bool matches(UUID *uuid) const;
|
||||
};
|
||||
|
||||
typedef enum BD_ADDR_TYPE {
|
||||
PUBLIC_ADDRESS = 0,
|
||||
PRIVAT_ADDRESS
|
||||
} BD_ADDR_TYPE;
|
||||
|
||||
class BD_ADDR {
|
||||
private:
|
||||
uint8_t address[6];
|
||||
BD_ADDR_TYPE address_type;
|
||||
public:
|
||||
BD_ADDR();
|
||||
BD_ADDR(const char * address_string, BD_ADDR_TYPE address_type = PUBLIC_ADDRESS);
|
||||
BD_ADDR(const uint8_t address[6], BD_ADDR_TYPE address_type = PUBLIC_ADDRESS);
|
||||
const uint8_t * getAddress();
|
||||
const char * getAddressString();
|
||||
BD_ADDR_TYPE getAddressType();
|
||||
};
|
||||
|
||||
class BLEAdvertisement {
|
||||
private:
|
||||
uint8_t advertising_event_type;
|
||||
uint8_t rssi;
|
||||
uint8_t data_length;
|
||||
uint8_t data[10 + LE_ADVERTISING_DATA_SIZE];
|
||||
BD_ADDR bd_addr;
|
||||
public:
|
||||
BLEAdvertisement(uint8_t * event_packet);
|
||||
BD_ADDR * getBdAddr();
|
||||
BD_ADDR_TYPE getBdAddrType();
|
||||
int getRssi();
|
||||
bool containsService(UUID * service);
|
||||
bool nameHasPrefix(const char * namePrefix);
|
||||
const uint8_t * getAdvData();
|
||||
};
|
||||
|
||||
class BLECharacteristic {
|
||||
private:
|
||||
le_characteristic_t characteristic;
|
||||
UUID uuid;
|
||||
public:
|
||||
BLECharacteristic();
|
||||
BLECharacteristic(le_characteristic_t characteristic);
|
||||
const UUID * getUUID();
|
||||
bool matches(UUID * uuid);
|
||||
bool isValueHandle(uint16_t value_handle);
|
||||
const le_characteristic_t * getCharacteristic();
|
||||
};
|
||||
|
||||
class BLEService {
|
||||
private:
|
||||
le_service_t service;
|
||||
UUID uuid;
|
||||
public:
|
||||
BLEService();
|
||||
BLEService(le_service_t service);
|
||||
const UUID * getUUID();
|
||||
bool matches(UUID * uuid);
|
||||
const le_service_t * getService();
|
||||
};
|
||||
|
||||
class BLEDevice {
|
||||
private:
|
||||
uint16_t handle;
|
||||
public:
|
||||
BLEDevice();
|
||||
BLEDevice(uint16_t handle);
|
||||
uint16_t getHandle();
|
||||
|
||||
// discovery of services and characteristics
|
||||
int discoverGATTServices();
|
||||
int discoverCharacteristicsForService(BLEService * service);
|
||||
|
||||
// read/write
|
||||
int readCharacteristic(BLECharacteristic * characteristic);
|
||||
int writeCharacteristic(BLECharacteristic * characteristic, uint8_t * data, uint16_t size);
|
||||
int writeCharacteristicWithoutResponse(BLECharacteristic * characteristic, uint8_t * data, uint16_t size);
|
||||
|
||||
// subscribe/unsubscribe
|
||||
int subscribeForNotifications(BLECharacteristic * characteristic);
|
||||
int unsubscribeFromNotifications(BLECharacteristic * characteristic);
|
||||
};
|
||||
|
||||
class BTstackManager {
|
||||
public:
|
||||
BTstackManager(void);
|
||||
void setup(void);
|
||||
void loop(void);
|
||||
|
||||
// @deprecated
|
||||
void registerPacketHandler(btstack_packet_handler_t packet_handler);
|
||||
// @deprecated
|
||||
void setClientMode();
|
||||
|
||||
void setAdvData(uint16_t size, const uint8_t * data);
|
||||
void setPublicBdAddr(bd_addr_t addr);
|
||||
|
||||
void bleStartScanning();
|
||||
void bleStopScanning();
|
||||
|
||||
// connection management
|
||||
void bleConnect(BD_ADDR_TYPE address_type, const uint8_t address[6], int timeout_ms);
|
||||
void bleConnect(BD_ADDR_TYPE address_type, const char * address, int timeout_ms);
|
||||
void bleConnect(BD_ADDR * address, int timeout_ms);
|
||||
void bleConnect(BLEAdvertisement * advertisement, int timeout_ms);
|
||||
void bleDisconnect(BLEDevice * device);
|
||||
|
||||
// discovery of services and characteristics
|
||||
int discoverGATTServices(BLEDevice * device);
|
||||
int discoverCharacteristicsForService(BLEDevice * peripheral, BLEService * service);
|
||||
|
||||
// read/write
|
||||
int readCharacteristic(BLEDevice * device, BLECharacteristic * characteristic);
|
||||
int writeCharacteristic(BLEDevice * device, BLECharacteristic * characteristic, uint8_t * data, uint16_t size);
|
||||
int writeCharacteristicWithoutResponse(BLEDevice * device, BLECharacteristic * characteristic, uint8_t * data, uint16_t size);
|
||||
|
||||
// subscribe/unsubscribe
|
||||
int subscribeForNotifications(BLEDevice * device, BLECharacteristic * characteristic);
|
||||
int unsubscribeFromNotifications(BLEDevice * device, BLECharacteristic * characteristic);
|
||||
|
||||
// Callbacks
|
||||
void setBLEAdvertisementCallback(void (*)(BLEAdvertisement * bleAdvertisement));
|
||||
void setBLEDeviceConnectedCallback(void (*)(BLEStatus status, BLEDevice * device));
|
||||
void setBLEDeviceDisconnectedCallback(void (*)(BLEDevice * device));
|
||||
void setGATTServiceDiscoveredCallback(void (*)(BLEStatus status, BLEDevice * device, BLEService * bleService));
|
||||
void setGATTCharacteristicDiscoveredCallback(void (*)(BLEStatus status, BLEDevice * device, BLECharacteristic * characteristic));
|
||||
void setGATTCharacteristicReadCallback(void (*)(BLEStatus status, BLEDevice * device, uint8_t * value, uint16_t length));
|
||||
void setGATTCharacteristicNotificationCallback(void (*)(BLEDevice * device, uint16_t value_handle, uint8_t* value, uint16_t length));
|
||||
void setGATTDoneCallback(void (*)(BLEStatus status, BLEDevice * device));
|
||||
|
||||
void setGATTCharacteristicWrittenCallback(void (*)(BLEStatus status, BLEDevice * device));
|
||||
void setGATTCharacteristicSubscribedCallback(void (*)(BLEStatus status, BLEDevice * device));
|
||||
void setGATTCharacteristicUnsubscribedCallback(void (*)(BLEStatus status, BLEDevice * device));
|
||||
};
|
||||
|
||||
extern BTstackManager BTstack;
|
251
platforms/arduino/bsp_arduino_em9301.cpp
Normal file
251
platforms/arduino/bsp_arduino_em9301.cpp
Normal file
@ -0,0 +1,251 @@
|
||||
/**
|
||||
* Arduino + Energia Wrapper for BTstack
|
||||
*/
|
||||
|
||||
#if !defined(ARDUINO)
|
||||
#error "Not compiling for Arduino/Energia"
|
||||
#endif
|
||||
|
||||
#include <Arduino.h>
|
||||
#ifdef ENERGIA
|
||||
#include <Energia.h>
|
||||
#endif
|
||||
#include <SPI.h>
|
||||
|
||||
#include "btstack/hal_uart_dma.h"
|
||||
|
||||
#define HAVE_SHUTDOWN
|
||||
|
||||
#ifdef ENERGIA
|
||||
|
||||
// CMM 9301 Configuration for TI Launchpad
|
||||
#define PIN_SCK 7
|
||||
#define PIN_CS 8
|
||||
#define PIN_SHUTDOWN 11
|
||||
#define PIN_IRQ_DATA 13
|
||||
#define PIN_MISO 14
|
||||
#define PIN_MOSI 15
|
||||
#else // ARDUINO
|
||||
|
||||
// CMM 9301 Configuration on Arduino
|
||||
#define PIN_IRQ_DATA 2
|
||||
#define PIN_CS 4
|
||||
#define PIN_SHUTDOWN 5
|
||||
#define PIN_MISO 50
|
||||
#define PIN_MOSI 51
|
||||
#define PIN_SCK 52
|
||||
#endif
|
||||
|
||||
// rx state
|
||||
static uint16_t bytes_to_read = 0;
|
||||
static uint8_t * rx_buffer_ptr = 0;
|
||||
|
||||
// tx state
|
||||
static uint16_t bytes_to_write = 0;
|
||||
static uint8_t * tx_buffer_ptr = 0;
|
||||
|
||||
// handlers
|
||||
static void dummy_handler(void){};
|
||||
static void (*rx_done_handler)(void) = dummy_handler;
|
||||
static void (*tx_done_handler)(void) = dummy_handler;
|
||||
|
||||
static void bt_setup(void){
|
||||
pinMode(PIN_CS, OUTPUT);
|
||||
pinMode(PIN_MOSI, OUTPUT);
|
||||
pinMode(PIN_SCK, OUTPUT);
|
||||
pinMode(PIN_SHUTDOWN, OUTPUT);
|
||||
pinMode(PIN_IRQ_DATA, INPUT);
|
||||
|
||||
digitalWrite(PIN_CS, HIGH);
|
||||
digitalWrite(PIN_MOSI, LOW);
|
||||
digitalWrite(PIN_SHUTDOWN, HIGH);
|
||||
|
||||
SPI.setBitOrder(MSBFIRST);
|
||||
SPI.setDataMode(SPI_MODE0);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SHUTDOWN
|
||||
static void bt_power_cycle(void){
|
||||
// power cycle. set CPU outputs to input to not power EM9301 via IOs
|
||||
// pinMode(PIN_MOSI, INPUT);
|
||||
// pinMode(PIN_CS, INPUT);
|
||||
pinMode(PIN_CS, OUTPUT);
|
||||
pinMode(PIN_MOSI, OUTPUT);
|
||||
pinMode(PIN_SCK, OUTPUT);
|
||||
pinMode(PIN_SHUTDOWN, OUTPUT);
|
||||
digitalWrite(PIN_CS, LOW);
|
||||
digitalWrite(PIN_MOSI, LOW);
|
||||
digitalWrite(PIN_SCK, LOW);
|
||||
digitalWrite(PIN_SHUTDOWN, HIGH);
|
||||
delay(500);
|
||||
|
||||
pinMode(PIN_MOSI, OUTPUT);
|
||||
pinMode(PIN_CS, OUTPUT);
|
||||
digitalWrite(PIN_MOSI, LOW);
|
||||
digitalWrite(PIN_CS, HIGH);
|
||||
digitalWrite(PIN_SHUTDOWN, LOW);
|
||||
delay(1000);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SHUTDOWN
|
||||
static void bt_send_illegal(){
|
||||
digitalWrite(PIN_MOSI, HIGH);
|
||||
digitalWrite(PIN_CS, LOW);
|
||||
printf("Illegal start\n");
|
||||
SPI.begin();
|
||||
int i;
|
||||
for (i=0;i<255;i++){
|
||||
SPI.transfer(0xff);
|
||||
printf(".");
|
||||
}
|
||||
SPI.end();
|
||||
printf("\nIllegal stop\n");
|
||||
digitalWrite(PIN_CS, HIGH);
|
||||
}
|
||||
|
||||
static void bt_flush_input(){
|
||||
digitalWrite(PIN_MOSI, LOW);
|
||||
digitalWrite(PIN_CS, LOW);
|
||||
SPI.begin();
|
||||
while (digitalRead(PIN_IRQ_DATA) == HIGH){
|
||||
SPI.transfer(0x00);
|
||||
}
|
||||
SPI.end();
|
||||
digitalWrite(PIN_CS, HIGH);
|
||||
}
|
||||
|
||||
static void bt_send_reset(){
|
||||
digitalWrite(PIN_MOSI, HIGH);
|
||||
digitalWrite(PIN_CS, LOW);
|
||||
SPI.begin();
|
||||
SPI.transfer(0x01);
|
||||
SPI.transfer(0x03);
|
||||
SPI.transfer(0x0c);
|
||||
SPI.transfer(0x00);
|
||||
SPI.end();
|
||||
digitalWrite(PIN_CS, HIGH);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void bt_try_send(void){
|
||||
|
||||
if (!bytes_to_write) return;
|
||||
|
||||
// activate module
|
||||
pinMode(PIN_MOSI, OUTPUT);
|
||||
digitalWrite(PIN_MOSI, HIGH);
|
||||
digitalWrite(PIN_CS, LOW);
|
||||
|
||||
// module ready
|
||||
int tx_done = 0;
|
||||
if (digitalRead(PIN_MISO) == HIGH){
|
||||
// printf("Sending: ");
|
||||
|
||||
SPI.begin();
|
||||
while (bytes_to_write){
|
||||
// printf("%02x ", *tx_buffer_ptr);
|
||||
SPI.transfer(*tx_buffer_ptr);
|
||||
tx_buffer_ptr++;
|
||||
bytes_to_write--;
|
||||
}
|
||||
SPI.end();
|
||||
// printf(".\n");
|
||||
tx_done = 1;
|
||||
}
|
||||
|
||||
// deactivate module
|
||||
digitalWrite(PIN_CS, HIGH);
|
||||
digitalWrite(PIN_MOSI, LOW);
|
||||
pinMode(PIN_MOSI, OUTPUT);
|
||||
|
||||
// notify upper layer
|
||||
if (tx_done) {
|
||||
(*tx_done_handler)();
|
||||
}
|
||||
}
|
||||
|
||||
static int bt_try_read(void){
|
||||
|
||||
// check if data available and buffer is ready
|
||||
if (digitalRead(PIN_IRQ_DATA) == LOW) return 0;
|
||||
if (bytes_to_read == 0) return 0;
|
||||
|
||||
int num_bytes_read = 0;
|
||||
|
||||
// printf("Reading (%u): ", bytes_to_read);
|
||||
|
||||
// activate module
|
||||
digitalWrite(PIN_MOSI, LOW);
|
||||
digitalWrite(PIN_CS, LOW);
|
||||
SPI.begin();
|
||||
do {
|
||||
uint8_t byte_read = SPI.transfer(0x00);
|
||||
// printf("%02x ", byte_read);
|
||||
*rx_buffer_ptr = byte_read;
|
||||
rx_buffer_ptr++;
|
||||
bytes_to_read--;
|
||||
num_bytes_read++;
|
||||
} while (bytes_to_read > 0);
|
||||
SPI.end();
|
||||
digitalWrite(PIN_CS, HIGH);
|
||||
|
||||
// printf("\n");
|
||||
|
||||
// notify upper layer
|
||||
(*rx_done_handler)();
|
||||
|
||||
return num_bytes_read;
|
||||
}
|
||||
|
||||
extern "C" void hal_uart_dma_init(void){
|
||||
bt_setup();
|
||||
|
||||
#ifdef HAVE_SHUTDOWN
|
||||
bt_power_cycle();
|
||||
#else
|
||||
// bring EM9301 into defined state
|
||||
bt_send_illegal();
|
||||
bt_send_reset();
|
||||
bt_flush_input();
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" void hal_uart_dma_set_block_received( void (*block_handler)(void)){
|
||||
rx_done_handler = block_handler;
|
||||
}
|
||||
extern "C" void hal_uart_dma_set_block_sent( void (*block_handler)(void)){
|
||||
tx_done_handler = block_handler;
|
||||
}
|
||||
|
||||
extern "C" void hal_uart_dma_set_csr_irq_handler( void (*csr_irq_handler)(void)){
|
||||
// only used for eHCILL
|
||||
}
|
||||
|
||||
extern "C" int hal_uart_dma_set_baud(uint32_t baud){
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" void hal_uart_dma_send_block(const uint8_t *buffer, uint16_t length){
|
||||
// printf("send_block, bytes %u\n", length);
|
||||
tx_buffer_ptr = (uint8_t *) buffer;
|
||||
bytes_to_write = length;
|
||||
}
|
||||
|
||||
extern "C" void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t length){
|
||||
rx_buffer_ptr = buffer;
|
||||
bytes_to_read = length;
|
||||
}
|
||||
|
||||
extern "C" void hal_uart_dma_set_sleep(uint8_t sleep){
|
||||
// not needed for SPI (doesn't need internal clock to work)
|
||||
}
|
||||
|
||||
extern "C" void hal_uart_dma_process(){
|
||||
int num_bytes_read = bt_try_read();
|
||||
if (num_bytes_read == 0){
|
||||
bt_try_send();
|
||||
}
|
||||
}
|
||||
|
29
platforms/arduino/btstack-config.h
Normal file
29
platforms/arduino/btstack-config.h
Normal file
@ -0,0 +1,29 @@
|
||||
#define EMBEDDED
|
||||
|
||||
// #define HAVE_INIT_SCRIPT
|
||||
// #define HAVE_EHCILL
|
||||
|
||||
#define HAVE_BZERO
|
||||
#define HAVE_TICK
|
||||
|
||||
#define HAVE_BLE
|
||||
|
||||
// #define HAVE_HCI_DUMP
|
||||
// #define ENABLE_LOG_INFO
|
||||
// #define ENABLE_LOG_ERROR
|
||||
|
||||
#define HCI_ACL_PAYLOAD_SIZE 52
|
||||
|
||||
#define MAX_NO_BNEP_SERVICES 0
|
||||
#define MAX_NO_BNEP_CHANNELS 0
|
||||
#define MAX_NO_GATT_SUBCLIENTS 1
|
||||
#define MAX_NO_HCI_CONNECTIONS 1
|
||||
#define MAX_NO_L2CAP_SERVICES 0
|
||||
#define MAX_NO_L2CAP_CHANNELS 0
|
||||
#define MAX_NO_RFCOMM_MULTIPLEXERS 0
|
||||
#define MAX_NO_RFCOMM_SERVICES 0
|
||||
#define MAX_NO_RFCOMM_CHANNELS 0
|
||||
#define MAX_NO_DB_MEM_DEVICE_LINK_KEYS 0
|
||||
#define MAX_NO_DB_MEM_DEVICE_NAMES 0
|
||||
#define MAX_NO_DB_MEM_SERVICES 0
|
||||
#define MAX_NO_GATT_CLIENTS 1
|
61
platforms/arduino/clone.sh
Executable file
61
platforms/arduino/clone.sh
Executable file
@ -0,0 +1,61 @@
|
||||
#!/bin/sh
|
||||
DIR=`dirname $0`
|
||||
BTSTACK_ROOT=$DIR/../..
|
||||
BTSTACK_PACKAGE=$DIR/btstack
|
||||
|
||||
echo Update version.h file
|
||||
$BTSTACK_ROOT/tools/get_version.sh
|
||||
|
||||
pushd .
|
||||
cd $BTSTACK_ROOT
|
||||
VERSION=`sed -n -e 's/^.*BTSTACK_VERSION \"\(.*\)\"/\1/p' include/btstack/version.h`
|
||||
ARCHIVE=btstack-arduino-$VERSION.zip
|
||||
popd
|
||||
|
||||
echo Prepare lib at $BTSTACK_PACKAGE
|
||||
|
||||
rm -rf $BTSTACK_PACKAGE
|
||||
mkdir $BTSTACK_PACKAGE
|
||||
|
||||
|
||||
# <btstack/...> headers
|
||||
cp -r $BTSTACK_ROOT/include/btstack $BTSTACK_PACKAGE
|
||||
|
||||
# other headers
|
||||
cp $BTSTACK_ROOT/ble/*.h $BTSTACK_PACKAGE
|
||||
cp $BTSTACK_ROOT/src/*.h $BTSTACK_PACKAGE
|
||||
|
||||
# src files
|
||||
SRC_FILES="btstack_memory.c linked_list.c memory_pool.c run_loop.c run_loop_embedded.c "
|
||||
SRC_FILES+="hci_dump.c hci.c hci_cmds.c hci_transport_h4_dma.c sdp_util.c utils.c "
|
||||
for i in $SRC_FILES
|
||||
do
|
||||
cp $BTSTACK_ROOT/src/$i $BTSTACK_PACKAGE
|
||||
done
|
||||
|
||||
# ble files
|
||||
BLE_FILES="ad_parser.c att.c att_server.c att_dispatch.c le_device_db_memory.c gatt_client.c "
|
||||
BLE_FILES+="sm.c l2cap_le.c ancs_client_lib.h ancs_client_lib.c"
|
||||
for i in $BLE_FILES
|
||||
do
|
||||
cp $BTSTACK_ROOT/ble/$i $BTSTACK_PACKAGE
|
||||
done
|
||||
|
||||
# em9301 chipset support
|
||||
cp $BTSTACK_ROOT/chipset-em9301/* $BTSTACK_PACKAGE
|
||||
|
||||
# Configuration
|
||||
cp $DIR/btstack-config.h $BTSTACK_PACKAGE
|
||||
|
||||
# BSP Arduino
|
||||
cp bsp_arduino_em9301.cpp $BTSTACK_PACKAGE
|
||||
|
||||
# Arduino c++ API
|
||||
cp $DIR/BTstack.cpp $DIR/BTstack.h $BTSTACK_PACKAGE
|
||||
|
||||
# Arduino examples
|
||||
cp -r $BTSTACK_ROOT/platforms/arduino/examples $BTSTACK_PACKAGE
|
||||
|
||||
echo "Create Archive $ARCHIVE"
|
||||
rm -f $ARCHIVE btstack.zip
|
||||
zip -r $ARCHIVE btstack
|
184
platforms/arduino/examples/BLECentralPseudo/BLECentralPseudo.ino
Normal file
184
platforms/arduino/examples/BLECentralPseudo/BLECentralPseudo.ino
Normal file
@ -0,0 +1,184 @@
|
||||
|
||||
#include <BTstack.h>
|
||||
#include <SPI.h>
|
||||
|
||||
// BLE Shield Service V2 incl. used Characteristics
|
||||
UUID bleShieldServiceV2UUID("B8E06067-62AD-41BA-9231-206AE80AB550");
|
||||
|
||||
typedef enum characteristicIDs {
|
||||
charRX = 0,
|
||||
charTX,
|
||||
charBaud,
|
||||
charBdAddr,
|
||||
numCharacteristics /* last one */
|
||||
} characteristicIDs_t;
|
||||
|
||||
UUID characteristicUUIDs[] = {
|
||||
UUID("f897177b-aee8-4767-8ecc-cc694fd5fcee"),
|
||||
UUID("bf45e40a-de2a-4bc8-bba0-e5d6065f1b4b"),
|
||||
UUID("2fbc0f31-726a-4014-b9fe-c8be0652e982"),
|
||||
UUID("65c228da-bad1-4f41-b55f-3d177f4e2196"),
|
||||
};
|
||||
|
||||
const char * characteristicNames[] = {
|
||||
"RX",
|
||||
"TX",
|
||||
"Baudrate",
|
||||
"BD ADDR"
|
||||
};
|
||||
|
||||
bool characteristicFound[numCharacteristics];
|
||||
BLECharacteristic characteristics[numCharacteristics];
|
||||
|
||||
// Application state
|
||||
BLEDevice myBLEDevice;
|
||||
BLEService myBLEService;
|
||||
bool serviceFound;
|
||||
bool sendCounter = false;
|
||||
|
||||
int counter = 0;
|
||||
char counterString[20];
|
||||
|
||||
// setup printf
|
||||
static FILE uartout = {0} ;
|
||||
static int uart_putchar (char c, FILE *stream) {
|
||||
Serial.write(c);
|
||||
return 0;
|
||||
}
|
||||
static void setup_printf(int baud) {
|
||||
Serial.begin(baud);
|
||||
fdev_setup_stream (&uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE);
|
||||
stdout = &uartout;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
|
||||
setup_printf(9600);
|
||||
|
||||
BTstack.setBLEAdvertisementCallback(advertisementCallback);
|
||||
BTstack.setBLEDeviceConnectedCallback(deviceConnectedCallback);
|
||||
BTstack.setBLEDeviceDisconnectedCallback(deviceDisconnectedCallback);
|
||||
BTstack.setGATTServiceDiscoveredCallback(gattServiceDiscovered);
|
||||
BTstack.setGATTCharacteristicDiscoveredCallback(gattCharacteristicDiscovered);
|
||||
BTstack.setGATTCharacteristicNotificationCallback(gattCharacteristicNotification);
|
||||
BTstack.setGATTCharacteristicReadCallback(gattReadCallback);
|
||||
BTstack.setGATTCharacteristicWrittenCallback(gattWrittenCallback);
|
||||
BTstack.setGATTCharacteristicSubscribedCallback(gattSubscribedCallback);
|
||||
|
||||
BTstack.setup();
|
||||
|
||||
BTstack.bleStartScanning();
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
BTstack.loop();
|
||||
|
||||
// send counter as fast as possible
|
||||
if (sendCounter){
|
||||
sprintf(counterString, "BTstack %u\n", counter);
|
||||
int result = myBLEDevice.writeCharacteristicWithoutResponse(&characteristics[charTX], (uint8_t*) counterString, strlen(counterString) );
|
||||
if (result == BLE_PERIPHERAL_OK){
|
||||
printf("Wrote without response: %s\n", counterString);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void advertisementCallback(BLEAdvertisement *bleAdvertisement) {
|
||||
printf("Device discovered: %s, RSSI: %d\n", bleAdvertisement->getBdAddr()->getAddressString(), bleAdvertisement->getRssi() );
|
||||
// if (bleAdvertisement->containsService(&bleShieldServiceV2UUID) && bleAdvertisement->nameHasPrefix("BLE-Shield")) {
|
||||
if (bleAdvertisement->containsService(&bleShieldServiceV2UUID)) {
|
||||
printf("\nBLE ShieldService V2 found!\n\n");
|
||||
BTstack.bleStopScanning();
|
||||
BTstack.bleConnect(bleAdvertisement, 10000); // 10 s
|
||||
}
|
||||
}
|
||||
|
||||
void deviceConnectedCallback(BLEStatus status, BLEDevice *device) {
|
||||
switch (status){
|
||||
case BLE_STATUS_OK:
|
||||
printf("Device connected!\n");
|
||||
myBLEDevice = *device;
|
||||
counter = 0;
|
||||
myBLEDevice.discoverGATTServices();
|
||||
break;
|
||||
case BLE_STATUS_CONNECTION_TIMEOUT:
|
||||
printf("Error while Connecting the Peripheral\n");
|
||||
BTstack.bleStartScanning();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void deviceDisconnectedCallback(BLEDevice * device){
|
||||
printf("Disconnected, starting over..\n");
|
||||
sendCounter = false;
|
||||
BTstack.bleStartScanning();
|
||||
}
|
||||
|
||||
void gattServiceDiscovered(BLEStatus status, BLEDevice *device, BLEService *bleService) {
|
||||
switch(status){
|
||||
case BLE_STATUS_OK:
|
||||
printf("Service Discovered: %s\n", bleService->getUUID()->getUuidString());
|
||||
if (bleService->matches(&bleShieldServiceV2UUID)) {
|
||||
serviceFound = true;
|
||||
printf("Our service located!\n");
|
||||
myBLEService = *bleService;
|
||||
}
|
||||
break;
|
||||
case BLE_STATUS_DONE:
|
||||
printf("Service discovery finished\n");
|
||||
if (serviceFound) {
|
||||
device->discoverCharacteristicsForService(&myBLEService);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("Service discovery error\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void gattCharacteristicDiscovered(BLEStatus status, BLEDevice *device, BLECharacteristic *characteristic) {
|
||||
switch(status){
|
||||
case BLE_STATUS_OK:
|
||||
printf("Characteristic Discovered: %s, handle 0x%04x\n", characteristic->getUUID()->getUuidString(), characteristic->getCharacteristic()->value_handle);
|
||||
int i;
|
||||
for (i=0;i<numCharacteristics;i++){
|
||||
if (characteristic->matches(&characteristicUUIDs[i])){
|
||||
printf("\nCharacteristic '%s' found!\n", characteristicNames[i]);
|
||||
characteristicFound[i] = 1;
|
||||
characteristics[i] = *characteristic;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BLE_STATUS_DONE:
|
||||
printf("Characteristic discovery finished, status %u.\n", status);
|
||||
if (characteristicFound[charRX]) {
|
||||
device->subscribeForNotifications(&characteristics[charRX]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("Characteristics discovery error\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void gattSubscribedCallback(BLEStatus status, BLEDevice * device){
|
||||
device->readCharacteristic(&characteristics[charBdAddr]);
|
||||
}
|
||||
|
||||
void gattReadCallback(BLEStatus status, BLEDevice *device, uint8_t *value, uint16_t length) {
|
||||
printf("Read callback: '%s'\n", (const char *)value);
|
||||
device->writeCharacteristic(&characteristics[charTX], (uint8_t*) "Hello!", 6);
|
||||
}
|
||||
|
||||
void gattWrittenCallback(BLEStatus status, BLEDevice *device){
|
||||
sendCounter = true;
|
||||
}
|
||||
|
||||
void gattCharacteristicNotification(BLEDevice *device, uint16_t value_handle, uint8_t *value, uint16_t length) {
|
||||
printf("Notification: '%s'\n", (const char *)value);
|
||||
}
|
192
platforms/arduino/examples/Test/Test.ino
Normal file
192
platforms/arduino/examples/Test/Test.ino
Normal file
@ -0,0 +1,192 @@
|
||||
/* basic SPI */
|
||||
#include <SPI.h>
|
||||
|
||||
#ifdef ENERGIA
|
||||
|
||||
// CMM 9301 Configuration for TI Launchpad
|
||||
#define PIN_SCK 7
|
||||
#define PIN_CS 8
|
||||
#define PIN_SHUTDOWN 11
|
||||
#define PIN_IRQ_DATA 13
|
||||
#define PIN_MISO 14
|
||||
#define PIN_MOSI 15
|
||||
#else // ARDUINO
|
||||
|
||||
// CMM 9301 Configuration on Arduino
|
||||
#define PIN_IRQ_DATA 2
|
||||
#define PIN_CS 4
|
||||
#define PIN_SHUTDOWN 5
|
||||
#define PIN_MISO 50
|
||||
#define PIN_MOSI 51
|
||||
#define PIN_SCK 52
|
||||
#define PIN_SHUTDOWN
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// software SPI
|
||||
class Software_SPI {
|
||||
public:
|
||||
void setBitOrder(int){}
|
||||
void setDataMode(int){};
|
||||
void setClockDivider(int){};
|
||||
void begin(){
|
||||
}
|
||||
void end(){
|
||||
}
|
||||
uint8_t transfer(uint8_t data){
|
||||
int i;
|
||||
for (i=0;i<8;i++){
|
||||
if (data & 0x80){
|
||||
digitalWrite(PIN_MOSI, HIGH);
|
||||
} else {
|
||||
digitalWrite(PIN_MOSI, LOW);
|
||||
}
|
||||
digitalWrite(PIN_SCK, HIGH);
|
||||
data = data << 1;
|
||||
digitalWrite(PIN_SCK, LOW);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
#define SPI_MODE0 0
|
||||
#define SPI_CLOCK_DIV8 8
|
||||
|
||||
Software_SPI SPI;
|
||||
#endif
|
||||
|
||||
void setup(){
|
||||
pinMode (PIN_CS, OUTPUT);
|
||||
pinMode(PIN_MOSI, OUTPUT);
|
||||
pinMode(PIN_SCK, OUTPUT);
|
||||
pinMode(PIN_SHUTDOWN, OUTPUT);
|
||||
|
||||
SPI.setBitOrder(MSBFIRST);
|
||||
SPI.setDataMode(SPI_MODE0);
|
||||
|
||||
// digitalWrite(PIN_SHUTDOWN, LOW);
|
||||
digitalWrite(PIN_CS, HIGH);
|
||||
digitalWrite(PIN_MOSI, LOW);
|
||||
|
||||
Serial.begin(9600);
|
||||
Serial.println("Started\n");
|
||||
}
|
||||
|
||||
void send_reset(){
|
||||
pinMode(PIN_MOSI, OUTPUT);
|
||||
digitalWrite(PIN_MOSI, HIGH);
|
||||
delay(1);
|
||||
digitalWrite(PIN_CS, LOW);
|
||||
delay(1);
|
||||
SPI.begin();
|
||||
SPI.setClockDivider(SPI_CLOCK_DIV8);
|
||||
SPI.transfer(0x01);
|
||||
SPI.transfer(0x03);
|
||||
SPI.transfer(0x0c);
|
||||
SPI.transfer(0x00);
|
||||
SPI.end();
|
||||
pinMode(PIN_MOSI, OUTPUT);
|
||||
digitalWrite(PIN_MOSI, LOW);
|
||||
digitalWrite(PIN_CS, HIGH);
|
||||
}
|
||||
|
||||
void send_illegal(){
|
||||
digitalWrite(PIN_MOSI, HIGH);
|
||||
pinMode(PIN_MOSI, OUTPUT);
|
||||
delay(1);
|
||||
digitalWrite(PIN_CS, LOW);
|
||||
delay(1);
|
||||
SPI.begin();
|
||||
int i;
|
||||
for (i=0;i<255;i++){
|
||||
SPI.transfer(0xff);
|
||||
}
|
||||
SPI.end();
|
||||
digitalWrite(PIN_CS, HIGH);
|
||||
}
|
||||
|
||||
void flush_input(){
|
||||
pinMode(PIN_MOSI, OUTPUT);
|
||||
digitalWrite(PIN_MOSI, LOW);
|
||||
digitalWrite(PIN_CS, LOW);
|
||||
SPI.begin();
|
||||
while (digitalRead(PIN_IRQ_DATA) == HIGH){
|
||||
SPI.transfer(0x00);
|
||||
}
|
||||
SPI.end();
|
||||
digitalWrite(PIN_CS, HIGH);
|
||||
}
|
||||
|
||||
void read_event(){
|
||||
do {
|
||||
pinMode (PIN_CS, OUTPUT);
|
||||
pinMode(PIN_MOSI, OUTPUT);
|
||||
digitalWrite(PIN_MOSI, LOW);
|
||||
delay(1);
|
||||
digitalWrite(PIN_CS, LOW);
|
||||
delay(1);
|
||||
SPI.begin();
|
||||
uint8_t data = SPI.transfer(0x00);
|
||||
Serial.print("Read 0x");
|
||||
Serial.println(data, HEX);
|
||||
SPI.end();
|
||||
pinMode (PIN_CS, OUTPUT);
|
||||
pinMode(PIN_MOSI, OUTPUT);
|
||||
digitalWrite(PIN_CS, HIGH);
|
||||
delay(1);
|
||||
} while (digitalRead(PIN_IRQ_DATA) == HIGH);
|
||||
}
|
||||
|
||||
void send_noise(){
|
||||
while (1){
|
||||
Serial.print(".");
|
||||
pinMode(PIN_MOSI, OUTPUT);
|
||||
digitalWrite(PIN_MOSI, HIGH);
|
||||
SPI.begin();
|
||||
digitalWrite(PIN_CS, LOW);
|
||||
SPI.transfer(0x0f);
|
||||
SPI.transfer(0x55);
|
||||
SPI.transfer(0xf0);
|
||||
digitalWrite(PIN_CS, HIGH);
|
||||
SPI.end();
|
||||
pinMode(PIN_MOSI, OUTPUT);
|
||||
digitalWrite(PIN_MOSI, LOW);
|
||||
}
|
||||
Serial.println("\n");
|
||||
}
|
||||
|
||||
void power_cycle(){
|
||||
// power cycle
|
||||
pinMode(PIN_MOSI, INPUT);
|
||||
pinMode(PIN_CS, INPUT);
|
||||
digitalWrite(PIN_SHUTDOWN, HIGH);
|
||||
delay(1000);
|
||||
digitalWrite(PIN_SHUTDOWN, LOW);
|
||||
delay(1000);
|
||||
pinMode(PIN_CS, OUTPUT);
|
||||
pinMode(PIN_MOSI, OUTPUT);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
Serial.println("Send noise");
|
||||
|
||||
// prepare unsynced state
|
||||
// send_noise();
|
||||
|
||||
// bring HCI parser into defined error state
|
||||
// send_illegal();
|
||||
|
||||
// power cycle
|
||||
Serial.println("Power cycle");
|
||||
power_cycle();
|
||||
|
||||
Serial.println("Reset");
|
||||
send_reset();
|
||||
|
||||
while (digitalRead(PIN_IRQ_DATA) == HIGH){
|
||||
read_event();
|
||||
}
|
||||
|
||||
delay(5000);
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
#include <BTstack.h>
|
||||
#include <stdio.h>
|
||||
#include "att_server.h"
|
||||
#include "gatt_client.h"
|
||||
#include "ancs_client_lib.h"
|
||||
#include "sm.h"
|
||||
#include <SPI.h>
|
||||
|
||||
const uint8_t adv_data[] = {
|
||||
// Flags general discoverable
|
||||
0x02, 0x01, 0x02,
|
||||
// Name
|
||||
0x05, 0x09, 'A', 'N', 'C', 'S',
|
||||
// Service Solicitation, 128-bit UUIDs - ANCS (little endian)
|
||||
0x11,0x15,0xD0,0x00,0x2D,0x12,0x1E,0x4B,0x0F,0xA4,0x99,0x4E,0xCE,0xB5,0x31,0xF4,0x05,0x79
|
||||
};
|
||||
|
||||
// retarget printf
|
||||
#ifdef ENERGIA
|
||||
extern "C" {
|
||||
int putchar(int c) {
|
||||
Serial.write((uint8_t)c);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
static void setup_printf(void) {
|
||||
Serial.begin(9600);
|
||||
}
|
||||
#else
|
||||
static FILE uartout = {0} ;
|
||||
static int uart_putchar (char c, FILE *stream) {
|
||||
Serial.write(c);
|
||||
return 0;
|
||||
}
|
||||
static void setup_printf(void) {
|
||||
Serial.begin(115200);
|
||||
fdev_setup_stream (&uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE);
|
||||
stdout = &uartout;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
printf("packet_handler type %u, event 0x%02x\n", packet_type, packet[0]);
|
||||
ancs_client_hci_event_handler(packet_type, channel, packet, size);
|
||||
}
|
||||
|
||||
void ancs_callback(ancs_event_t * event){
|
||||
const char * attribute_name;
|
||||
switch (event->type){
|
||||
case ANCS_CLIENT_CONNECTED:
|
||||
printf("ANCS Client: Connected\n");
|
||||
break;
|
||||
case ANCS_CLIENT_DISCONNECTED:
|
||||
printf("ANCS Client: Disconnected\n");
|
||||
break;
|
||||
case ANCS_CLIENT_NOTIFICATION:
|
||||
attribute_name = ancs_client_attribute_name_for_id(event->attribute_id);
|
||||
if (!attribute_name) break;
|
||||
printf("Notification: %s - %s\n", attribute_name, event->text);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setup(){
|
||||
setup_printf();
|
||||
printf("Main::Setup()\n");
|
||||
BT.setup();
|
||||
BT.setAdvData(sizeof(adv_data), adv_data);
|
||||
|
||||
// setup packet handler (Client+Server_
|
||||
BT.registerPacketHandler(&packet_handler);
|
||||
|
||||
sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_ONLY);
|
||||
sm_set_authentication_requirements( SM_AUTHREQ_BONDING );
|
||||
|
||||
// set up GATT Server
|
||||
att_set_db(NULL);
|
||||
|
||||
// setup GATT client
|
||||
gatt_client_init();
|
||||
|
||||
// setup ANCS Client
|
||||
ancs_client_init();
|
||||
ancs_client_register_callback(&ancs_callback);
|
||||
}
|
||||
|
||||
void loop(){
|
||||
BT.loop();
|
||||
}
|
@ -0,0 +1,129 @@
|
||||
#include <BTstack.h>
|
||||
#include <stdio.h>
|
||||
#include "att_server.h"
|
||||
#include "gatt_client.h"
|
||||
#include "hci.h"
|
||||
|
||||
#include <SPI.h>
|
||||
|
||||
static bd_addr_t em9301_addr = { 0x0C, 0xF3, 0xEE, 0x00, 0x00, 0x00 };
|
||||
static gatt_client_t gatt_context;
|
||||
static uint16_t con_handle;
|
||||
static uint8_t sensor_value;
|
||||
|
||||
// retarget printf
|
||||
#ifdef ENERGIA
|
||||
extern "C" {
|
||||
int putchar(int c) {
|
||||
Serial.write((uint8_t)c);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
static void setup_printf(void) {
|
||||
Serial.begin(9600);
|
||||
}
|
||||
#else
|
||||
static FILE uartout = {0} ;
|
||||
static int uart_putchar (char c, FILE *stream) {
|
||||
Serial.write(c);
|
||||
return 0;
|
||||
}
|
||||
static void setup_printf(void) {
|
||||
Serial.begin(115200);
|
||||
fdev_setup_stream (&uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE);
|
||||
stdout = &uartout;
|
||||
}
|
||||
#endif
|
||||
|
||||
// test profile
|
||||
#include "profile.h"
|
||||
|
||||
// write requests
|
||||
static int att_write_callback(uint16_t con_handle, uint16_t handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size){
|
||||
printf("WRITE Callback, handle 0x%04x\n", handle);
|
||||
|
||||
switch(handle){
|
||||
case ATT_CHARACTERISTIC_FFF1_01_VALUE_HANDLE:
|
||||
buffer[buffer_size]=0;
|
||||
printf("New text: %s\n", buffer);
|
||||
break;
|
||||
case ATT_CHARACTERISTIC_FFF2_01_VALUE_HANDLE:
|
||||
printf("New value: %u\n", buffer[0]);
|
||||
#ifdef PIN_LED
|
||||
if (buffer[0]){
|
||||
digitalWrite(PIN_LED, HIGH);
|
||||
} else {
|
||||
digitalWrite(PIN_LED, LOW);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void try_send(){
|
||||
if (!con_handle) return;
|
||||
|
||||
// try write
|
||||
gatt_client_write_value_of_characteristic_without_response(&gatt_context, ATT_CHARACTERISTIC_FFF2_01_VALUE_HANDLE, 1, &sensor_value);
|
||||
}
|
||||
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
printf("packet type %x\n", packet[0]);
|
||||
switch (packet_type) {
|
||||
case HCI_EVENT_PACKET:
|
||||
switch (packet[0]) {
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (packet[2] == HCI_STATE_WORKING) {
|
||||
printf("Connecting to server\n");
|
||||
le_central_connect(&em9301_addr, BD_ADDR_TYPE_LE_PUBLIC);
|
||||
}
|
||||
break;
|
||||
|
||||
case HCI_EVENT_DISCONNECTION_COMPLETE:
|
||||
con_handle = 0;
|
||||
break;
|
||||
|
||||
case HCI_EVENT_LE_META:
|
||||
switch (packet[2]) {
|
||||
case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
|
||||
// store connection info
|
||||
con_handle = READ_BT_16(packet, 4);
|
||||
|
||||
// start GATT Client
|
||||
gatt_client_start(&gatt_context, con_handle);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
try_send();
|
||||
}
|
||||
|
||||
void setup(){
|
||||
|
||||
setup_printf();
|
||||
|
||||
printf("Main::Setup()\n");
|
||||
BT.setup();
|
||||
|
||||
// set up GATT Server
|
||||
att_set_db(profile_data);
|
||||
att_set_write_callback(att_write_callback);
|
||||
|
||||
// set up GATT Client
|
||||
gatt_client_init();
|
||||
BT.setClientMode();
|
||||
|
||||
// setup packet handler (Client+Server_
|
||||
BT.registerPacketHandler(&packet_handler);
|
||||
}
|
||||
|
||||
void loop(){
|
||||
BT.loop();
|
||||
sensor_value = analogRead(A0) >> 2;
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
#include <BTstack.h>
|
||||
#include <stdio.h>
|
||||
#include "att_server.h"
|
||||
#include <SPI.h>
|
||||
|
||||
// EM9301 address 0C:F3:EE:00:00:00
|
||||
|
||||
// retarget printf
|
||||
#ifdef ENERGIA
|
||||
extern "C" {
|
||||
int putchar(int c) {
|
||||
Serial.write((uint8_t)c);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
static void setup_printf(void) {
|
||||
Serial.begin(9600);
|
||||
}
|
||||
#else
|
||||
static FILE uartout = {0} ;
|
||||
static int uart_putchar (char c, FILE *stream) {
|
||||
Serial.write(c);
|
||||
return 0;
|
||||
}
|
||||
static void setup_printf(void) {
|
||||
Serial.begin(115200);
|
||||
fdev_setup_stream (&uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE);
|
||||
stdout = &uartout;
|
||||
}
|
||||
#endif
|
||||
|
||||
// test profile
|
||||
#include "profile.h"
|
||||
|
||||
// write requests
|
||||
static int att_write_callback(uint16_t con_handle, uint16_t handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size){
|
||||
printf("WRITE Callback, handle 0x%04x\n", handle);
|
||||
|
||||
switch(handle){
|
||||
case ATT_CHARACTERISTIC_FFF1_01_VALUE_HANDLE:
|
||||
buffer[buffer_size]=0;
|
||||
printf("New text: %s\n", buffer);
|
||||
break;
|
||||
case ATT_CHARACTERISTIC_FFF2_01_VALUE_HANDLE:
|
||||
printf("New value: %u\n", buffer[0]);
|
||||
#ifdef PIN_LED
|
||||
if (buffer[0]){
|
||||
digitalWrite(PIN_LED, HIGH);
|
||||
} else {
|
||||
digitalWrite(PIN_LED, LOW);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setup(){
|
||||
|
||||
setup_printf();
|
||||
|
||||
printf("Main::Setup()\n");
|
||||
BT.setup();
|
||||
|
||||
// set up ATT
|
||||
att_set_db(profile_data);
|
||||
att_set_write_callback(att_write_callback);
|
||||
}
|
||||
|
||||
void loop(){
|
||||
BT.loop();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user