Created
October 8, 2023 22:31
-
-
Save shabaz123/a3fc517ac8ba5cf8bd3f776da1055ef3 to your computer and use it in GitHub Desktop.
BLE code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/************************************************************************ | |
* ble_handler.cpp | |
* shabaz - oct 2023 | |
* this file encapsulates the BLE related functions used in the project | |
************************************************************************/ | |
// includes | |
#include "ble_handler.h" | |
#include "config_gatt.h" | |
#include "btstack.h" | |
#include "pico/cyw43_arch.h" | |
#include "pico/btstack_cyw43.h" | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
// ************************ defines *********************************** | |
ble_rx_t ble_rx; // contains received data from remote BLE device | |
// ********************* global variables ***************************** | |
// Advertisement Data, contains Flags, and Advertised Name | |
// First byte is the number of following bytes, and the second byte is the type | |
// type 0x01 = Flags | |
// type 0x09 = Name | |
const uint8_t adv_data[] = { | |
// Flags general discoverable, BR/EDR not supported | |
0x02, 0x01, 0x06, | |
// Name | |
0x0b, 0x09, 'E', 'a', 's', 'y', 'A', 'c', 'c', 'e', 's', 's' | |
}; | |
const uint8_t adv_data_len = sizeof(adv_data); | |
const char * test_string = "Test response"; | |
// Used for notifications | |
uint16_t NotifyState = 0; | |
hci_con_handle_t con_handle = HCI_CON_HANDLE_INVALID; | |
// ********************** function prototypes ************************** | |
static uint16_t att_read_callback(hci_con_handle_t con_handle, uint16_t att_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size); | |
static int att_write_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size); | |
void att_server_handle_can_send_now(void); | |
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); | |
// ************************ functions definitions ********************** | |
//CYW43438 driver initialization | |
int ble_chip_init(void) { | |
int ret = 0; | |
if (cyw43_arch_init()) { | |
printf("ERROR - failed to initialise cyw43_arch!\n"); | |
ret = -1; | |
} | |
return (ret); | |
} | |
static void ble_setup(void){ | |
l2cap_init(); | |
// setup SM: Display only | |
sm_init(); | |
// setup ATT server | |
att_server_init(profile_data, att_read_callback, att_write_callback); | |
// register for ATT events | |
att_server_register_packet_handler(packet_handler); | |
// setup advertisements | |
uint16_t adv_int_min = 0x0030; | |
uint16_t adv_int_max = 0x0030; | |
uint8_t adv_type = 0; | |
bd_addr_t null_addr; | |
memset(null_addr, 0, 6); | |
gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, null_addr, 0x07, 0x00); | |
gap_advertisements_set_data(adv_data_len, (uint8_t*) adv_data); | |
gap_advertisements_enable(1); | |
} | |
// read callback (i.e. remote device is attempting to read from us) | |
static uint16_t att_read_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){ | |
UNUSED(connection_handle); | |
// useless code when ENABLE_ATT_DELAYED_RESPONSE is not defined - but avoids built errors | |
if (att_handle == ATT_CHARACTERISTIC_0000CC01_0000_1000_8000_00805F9B34FB_01_VALUE_HANDLE){ | |
printf("Remote read request for 0000CC01\n"); | |
return att_read_callback_handle_blob((const uint8_t *)test_string, (uint16_t) strlen(test_string), offset, buffer, buffer_size); | |
} | |
if (att_handle == ATT_CHARACTERISTIC_0000CC02_0000_1000_8000_00805F9B34FB_01_VALUE_HANDLE){ | |
printf("Remote read request for 0000CC02\n"); | |
return att_read_callback_handle_blob((const uint8_t *)test_string, (uint16_t) strlen(test_string), offset, buffer, buffer_size); | |
} | |
return 0; | |
} | |
// write callback (i.e. remote device has written to one of our attributes) | |
static int att_write_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size){ | |
UNUSED(transaction_mode); | |
UNUSED(offset); | |
UNUSED(buffer_size); | |
UNUSED(connection_handle); | |
NotifyState = little_endian_read_16(buffer, 0) == GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION; | |
if (NotifyState) { | |
// store the connection handle | |
con_handle = connection_handle; | |
} | |
if (att_handle == ATT_CHARACTERISTIC_0000CC01_0000_1000_8000_00805F9B34FB_01_VALUE_HANDLE) { | |
printf("Remote write request for 0000CC01, value: "); | |
printf_hexdump(buffer, buffer_size); | |
printf("length: %d\n", buffer_size); | |
if (ble_rx.status == STATUS_NO_DATA) { | |
memcpy(ble_rx.data, buffer, buffer_size); | |
ble_rx.len = buffer_size; | |
ble_rx.status = STATUS_NEW_DATA; | |
} | |
else { | |
// hmmm, the previous data has not been consumed. This should not happen. | |
// throw away the new data. Not ideal, but will do for now. | |
printf("ERROR: ble_rx.status is not STATUS_NO_DATA, delay in consumption?\n"); | |
} | |
return 0; | |
} | |
if (att_handle == ATT_CHARACTERISTIC_0000CC02_0000_1000_8000_00805F9B34FB_01_VALUE_HANDLE) { | |
printf("Remote write request for 0000CC02, value: "); | |
printf_hexdump(buffer, buffer_size); | |
printf("length: %d\n", buffer_size); | |
// ignore the written data for now. We only want to use this characteristic for Notify | |
if (NotifyState) { | |
printf("Notify enabled\n"); | |
} | |
return 0; | |
} | |
return 0; | |
} | |
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ | |
UNUSED(channel); | |
UNUSED(size); | |
if (packet_type != HCI_EVENT_PACKET) return; | |
switch (hci_event_packet_get_type(packet)) { | |
case HCI_EVENT_DISCONNECTION_COMPLETE: | |
NotifyState = 0; | |
break; | |
case ATT_EVENT_CAN_SEND_NOW: | |
att_server_notify(con_handle, ATT_CHARACTERISTIC_0000CC02_0000_1000_8000_00805F9B34FB_01_VALUE_HANDLE, (uint8_t*) "Bob", 3); | |
break; | |
default: | |
break; | |
} | |
} | |
// send a Notification | |
void | |
ble_send_notification(char* data) | |
{ | |
if (NotifyState) { | |
att_server_handle_can_send_now(); | |
} | |
} | |
int blestack_main(void) | |
{ | |
ble_setup(); | |
hci_power_control(HCI_POWER_ON); // turn on! | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment