Discovering Gatt Parameters is stalling/crashing system system

Hello All,

I am programming an nrf52480 using zephyr on a windows machine.

I am trying to write a bluetooth peripheral characteristic, ore specifically to the led characteristic in the nordic led and button service.

In my code far I have verified:

  1. the central scanning mechanism works to find the peripheral device I want to attached to,
  2. filtering is working correctly such that I connect to the correct device.

Upon this step I didn't know how to write to the characteristic to turn on an led on the peripheral and I have determined the following steps need to be followed to write to a characteristic:

  1. I need to discover the characteristics that are attached with the uuid using the bt_gatt_discover function
  2. Once the desired characteristic is found using the discover_cb funciton that is set in the bt_gatt_discover funciton as a parameter structure then the handles value can be extracted.
  3. The characteristic handle value is used with bt_gatt_write_without_response function to transmit the data.

Please correct me if the above understanding is incorrect.

Given these steps I am getting stuck on step one.

The following is th ebackground for the steps I am taking before getting stuck. I think the issue is how I have implemented the bt_gatt_discover function:

  1. Once the filter match is done, the system automatically attempts to connect with the device at which point the scan_connecting callback function is called. INn my case this function just produces the logs.
    1. To my understanding the scan_connecting function is a call back before the actuatl connection is done.
  2. Once the connection to the peripheral is made the connected callbacck set using the bt_conn_cb_resiter funciton is called.
  3. In the connected callback I am attempting to call the bt_gatt_discover function.

My program either crashes or stalls when I call the bt_gatt)discover function. I think the issue is how or when I am calling this function because if I do not include it the logs for the connected callback function are outputted properly as shown below:

```

[00:01:07.612,884] <inf> button_control: IN the connected callback
[00:01:07.612,915] <inf> button_control: Bluetooth Connection Sucessfull
[00:01:07.612,915] <err> button_control: RIGHT BEFORE THE DISCOVER FUNCTION

```

Given this connected code:

```

void connected(struct bt_conn *conn, uint8_t err){
    LOG_INF("IN the connected callback");
    if (err < 0){
        LOG_ERR("Conection error has occured (err %d)", err);
    }

    LOG_INF("Bluetooth Connection Sucessfull");

    if(conn == NULL){
        LOG_ERR("The Conneciton ptr is not set properly");
    }

    static struct bt_uuid_128 uuid = BT_UUID_INIT_128(0);
    memcpy(&uuid, BT_UUID_LBS, sizeof(uuid));

    struct bt_gatt_discover_params discover_params = {
        .uuid = NULL,
        .func = discover_cb, //discover attribute callback
        .start_handle = 0x0001,
        .end_handle = 0xffff,
        .type = BT_GATT_DISCOVER_CHARACTERISTIC,
    };

    wrist_conn = conn;

    LOG_ERR("RIGHT BEFORE THE DISCOVER FUNCTION");
    // int result = bt_gatt_discover(conn, &discover_params);
    // if (result < 0) {
    //  LOG_ERR("Error occured when discovering the bluetooth services (err: %d)", result);
    // }
};

```

When I uncomment the bt_gatt_discover line as below:

```

void connected(struct bt_conn *conn, uint8_t err){
    LOG_INF("IN the connected callback");
    if (err < 0){
        LOG_ERR("Conection error has occured (err %d)", err);
    }

    LOG_INF("Bluetooth Connection Sucessfull");

    if(conn == NULL){
        LOG_ERR("The Conneciton ptr is not set properly");
    }

    static struct bt_uuid_128 uuid = BT_UUID_INIT_128(0);
    memcpy(&uuid, BT_UUID_LBS, sizeof(uuid));

    struct bt_gatt_discover_params discover_params = {
        .uuid = NULL,
        .func = discover_cb, //discover attribute callback
        .start_handle = 0x0001,
        .end_handle = 0xffff,
        .type = BT_GATT_DISCOVER_CHARACTERISTIC,
    };

    wrist_conn = conn;

    LOG_ERR("RIGHT BEFORE THE DISCOVER FUNCTION");
    int result = bt_gatt_discover(conn, &discover_params);
    if (result < 0) {
        LOG_ERR("Error occured when discovering the bluetooth services (err: %d)", result);
    }

};

```

I get the following log output (the connected function doesn't provide it's log)

```
[00:00:06.744,781] <inf> button_control: Connected in the Scan Connecting callback

```

What is going on? What is incorrect about my thinking and code? Any guidance on this would be much appreciated.

the below are the important pieces of code then settingup the bluetooth connection in the bluetooth_control.c file:

```

/** @brief Scan event handler function to handle with filter passed devices
 *
 *  The following are the situations that can be set to check in the @ref bt_scan_filter match struct:
    1. name //will the filter work like a contain function or a hard name?
    2. short_name x
    3. addr x
    4. uuid //using the lbs service uuid
    5. appearance x
    6. manufacturer_data x
 *  
 *  @param device_info ptr to structure that holds device data to make a connection
 *  @param bt_scan_filter_match ptr to a struct that holds the information of filter matches for a device. Would change based on the filter opetions used
 *  @param connectable  inform the central that the device is connectable.
 *  
*/
void scan_filter_match(struct bt_scan_device_info *device_info, struct bt_scan_filter_match *filter_match, bool connectable)
{
    // Handle filter match event
    //assume anything with a uuid and a name that are filtered will work.
    int err;
   
    if (filter_match->short_name.match){
        LOG_INF("NAME: ");
        for (int i = 0; i < filter_match->short_name.len; i++){
            LOG_INF("%c", filter_match->short_name.name[i]);
        }
        LOG_INF("\n");
    }

    if(filter_match->uuid.match){
        LOG_INF("UUID: ");
        for (int i = 0; i < filter_match->uuid.count; i++){
            LOG_INF("%d", filter_match->uuid.uuid[i]->type); // Logging as hexadecimal
            if (filter_match->uuid.uuid[i]->type == BT_UUID_TYPE_128) {
                LOG_INF("128 bit uuid found");
                struct bt_uuid_128 *u128 = (struct bt_uuid_128 *)filter_match->uuid.uuid;
                LOG_INF("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
                        // u128->val[0], u128->val[1], u128->val[2], u128->val[3],
                        // u128->val[4], u128->val[5],
                        // u128->val[6], u128->val[7],
                        // u128->val[8], u128->val[9],
                        // u128->val[10], u128->val[11], u128->val[12], u128->val[13], u128->val[14], u128->val[15]
                       
                        u128->val[15], u128->val[14], u128->val[13], u128->val[12],
                        u128->val[11], u128->val[10],
                        u128->val[9], u128->val[8],
                        u128->val[7], u128->val[6],
                        u128->val[5], u128->val[4], u128->val[3], u128->val[2], u128->val[1], u128->val[0]
                        );
                LOG_INF("END OF UUID 128 bit");
            }
        }
    }

    if(filter_match->name.match){
        LOG_INF("NAME: ");
        for (int i = 0; i < filter_match->name.len; i++){
            LOG_INF("%c", filter_match->name.name[i]);
        }

        LOG_INF("\n");
    }

   

    //two options: perform a manual connect operation or allow the auto connect to work?
    if (connectable) {
        struct bt_conn *conn;
        err = bt_conn_le_create(device_info->recv_info->addr,
                                BT_CONN_LE_CREATE_CONN,
                                device_info->conn_param,
                                &conn);

        if (!err){
            if (!err) {
                default_conn = bt_conn_ref(conn);
                bt_conn_unref(conn);
            }
        }
    }



   
};

/** @brief Scan event handler function to handle with non filter passed devices
 *         The device information is simpley outputed for debugging purposes.
 *  
 *  @param device_info ptr to structure that holds device data to make a connection
 *  @param connectable  inform the central that the device is connectable.
 *  
*/

void scan_filter_no_match(struct bt_scan_device_info *device_info, bool connectable)
{
    // Handle filter no match event
    // LOG_ERR("DEVICE WITH ALL FILTERS NOT FOUND\n");
};

/** @brief Event handler runnign when a connection is made. Output the status of the connection.
 *          - what device is connected to
 *          - status of the connection
 *          
 *  
 *  @param device_info ptr to structure that holds device data to make a connection
 *  @param conn ptr to connection info
 *  
*/

void scan_connecting(struct bt_scan_device_info *device_info, struct bt_conn *conn)
{
    LOG_INF("Connected in the Scan Connecting callback\n");

    if(conn == NULL){
        LOG_ERR("The Conneciton ptr is not set properly");
    }

    // static struct bt_uuid_128 uuid = BT_UUID_INIT_128(0);
    // memcpy(&uuid, BT_UUID_LBS, sizeof(uuid));

    // struct bt_gatt_discover_params discover_params = {
    //  .uuid = &uuid.uuid,
    //  .func = discover_cb, //discover attribute callback
    //  .start_handle = 0x0001,
    //  .end_handle = 0xffff,
    //  .type = BT_GATT_DISCOVER_CHARACTERISTIC,
    // };

    // wrist_conn = conn;

    // int result = bt_gatt_discover(conn, &discover_params);
    // if (result < 0) {
    //  LOG_ERR("Error occured when discovering the bluetooth services (err: %d)", result);
    // }
};

/** @brief Event handler runnign when a connection has failed.
 *          Output:
 *          - what device was attempted to connect to
 *          - Error/reason for the connection failing
 *          
 *  @param device_info ptr to structure that holds device data to make a connection
 *  
*/

void scan_connecting_error(struct bt_scan_device_info *device_info)
{
    LOG_ERR("Failed to Connect\n");
};

/** @brief Macro for establishing the scan callbacks for when scanning is started
 *          
 *  @param _name scan_cb name of the bt_can_cb structure that is made
 *  @param match_fun scan_filter_match function handler for when filters match
 *  @param no_match_fun function handler for when filters do not match a device
 *  @param err_fun handler for handling error if connection failed (connect_if_match flag in the scan param must be set for connect to occur with this callback)
 *  @param connecting_fun handler for when a connection occurs (connect_if_match flag must be present)

*/

BT_SCAN_CB_INIT(scan_cb, scan_filter_match, scan_filter_no_match, scan_connecting_error, scan_connecting);

/** @brief starting the discovery of the services after a central connection is made
 *
 *  @param  bt_conn * conn: struct holding the connectin parameters
 *  @param  err if error in connection has occured
 *            
*/

void connected(struct bt_conn *conn, uint8_t err){
    LOG_INF("IN the connected callback");
    if (err < 0){
        LOG_ERR("Conection error has occured (err %d)", err);
    }

    LOG_INF("Bluetooth Connection Sucessfull");

    if(conn == NULL){
        LOG_ERR("The Conneciton ptr is not set properly");
    }

    static struct bt_uuid_128 uuid = BT_UUID_INIT_128(0);
    memcpy(&uuid, BT_UUID_LBS, sizeof(uuid));

    struct bt_gatt_discover_params discover_params = {
        .uuid = NULL,
        .func = discover_cb, //discover attribute callback
        .start_handle = 0x0001,
        .end_handle = 0xffff,
        .type = BT_GATT_DISCOVER_CHARACTERISTIC,
    };

    wrist_conn = conn;

    LOG_ERR("RIGHT BEFORE THE DISCOVER FUNCTION");
    int result = bt_gatt_discover(conn, &discover_params);
    if (result < 0) {
        LOG_ERR("Error occured when discovering the bluetooth services (err: %d)", result);
    }
};

/** @brief starting the discovery of the services after a central connection is made
 *
 *  @param  bt_conn * conn: struct holding the connectin parameters
 *  @param  reason error code for why disconnected occured  
*/

void disconnected(struct bt_conn *conn, uint8_t reason){
    LOG_ERR("Disconnection occured. (err: %d)", reason);
    wrist_conn = NULL;
    ledHandleReady = false;
};

/** @brief callback funciton to address cycling through characteristics of the incoming connection
 *
 *  Want to find the led characteristic of the led service then get the required information
 *
 *  @param bt_conn *conn: ptr to the connection parameters needed for a bluetooth conneciton
 *  @param bt_gatt_attr *attr: the gatt attribute that is found currently
 *  @param bt_gatt_discover_params *params: Discovery parameters that are given
 *  
 */

uint8_t discover_cb(struct bt_conn *conn, const struct bt_gatt_attr *attr, struct bt_gatt_discover_params *params){
    LOG_INF("IN THE DISCOVERY CALLBACK");
    if(attr == NULL){
        LOG_INF("Discovery complete");
        return BT_GATT_ITER_STOP;
    }

    //set the struct for a characteristic
    struct bt_gatt_chrc *chrc = (struct bt_gatt_chrc *)attr->user_data;

    if(bt_uuid_cmp(chrc->uuid,BT_UUID_LBS_LED) == 0) {
        led_handle = chrc->value_handle;
        LOG_INF("LED characteristic handle: %u", led_handle);
        ledHandleReady = true;
        return BT_GATT_ITER_STOP;  
    }

    return BT_GATT_ITER_CONTINUE;
    // return BT_GATT_ITER_STOP;
};

```

The below is my bluetooth implementation in my main.c file:

```

//--------------SCAN TESTING START---------------------//

        // int err = 0;
        err = bt_enable(bt_ready_cb);
        if (err) {
                LOG_ERR("Bluetooth init failed (err %d)", err);
                return 0;
        }

        struct bt_conn_cb cb = {
                .connected = connected,
                .disconnected = disconnected,
        };

        bt_conn_cb_register(&cb);

        while(!btReady);

        const struct bt_scan_init_param bt_scan_init_opts = {
                        .scan_param = NULL, //default config
                        .connect_if_match = true,
                        .conn_param = NULL, //default config
        };
       
        bt_scan_init(&bt_scan_init_opts);
        BT_SCAN_CB_INIT(scan_cb, scan_filter_match, scan_filter_no_match, scan_connecting_error, scan_connecting);
        bt_scan_cb_register(&scan_cb);

        //--------------------UUID FILTER

        err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_UUID, BT_UUID_LBS);
        if (err) {
                LOG_ERR("UUID scanning filters cannot be set (err %d)", err);
                return err;
        }

        //------------------SHORT NAME FILTER

        // struct bt_scan_short_name short_name_filter_data = {
        //         .name = TARGET_DEVICE_NAME,
        //         .min_len = sizeof(TARGET_DEVICE_NAME),
        // };

        // err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_SHORT_NAME,&short_name_filter_data);
        // if (err) {
        //      LOG_ERR("Short Name scanning filters cannot be set (err %d)", err);
        //      return err;
        // }

        //------------------NAME FILTER
        err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_NAME, TARGET_DEVICE_NAME);
        if (err) {
                LOG_ERR("Name scanning filters cannot be set (err %d)", err);
                return err;
        }


        err = bt_scan_filter_enable(BT_SCAN_UUID_FILTER | BT_SCAN_NAME_FILTER, true);
        // err = bt_scan_filter_enable(BT_SCAN_NAME_FILTER, true);

        if (err) {
                LOG_ERR("Filters cannot be turned on (err %d)", err);
                return err;
        }

        LOG_INF("Scan module initialized");


        err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
        if (err) {
                LOG_ERR("Scanning failed to start (err %d)", err);
                return 0;
        }

        LOG_INF("Scanning successfully started");

        //--------------SCAN TESTING END---------------------//

```

I have also attached the full main.c and the bluetooth_control.c files as well for your reference.

#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/drivers/adc.h>
#include <stdlib.h>

#include "led_control.h"
#include "adc_control.h"
#include "bluetooth_control.h"
#include "button_control.h"

#include <math.h>

#define NUM_SENSORS (2)

#define NUM_ADC_SEL_PINS (1) //should be the bits needed to rep the num_sensors value

#define PIN_ADC_SEL_0 (28) //to be coordinated with the rest of the sytem
#define PIN_ADC_SEL_1 (29) 
#define PIN_ADC_SEL_2 (4) 
#define PIN_ADC_SEL_3 (5+1)
// adc read pin is set to be pin 3 in the overlay file 
#define PIN_BOARD_LED (2)
#define PIN_PAIRING_BUTTON (5)


#define ADC_BUFFER_SIZE (2) //based of resolution, samples taken, and number of channesl (12 bits = 2 bytes)
                                // 2 bytes * 1 sample taken * 1 channel = 2 

#define PRESSURE_THRESHOLD (10)

#define TARGET_DEVICE_NAME "SNOW"


// FUNCTION DEFINITIONS

void pairing_button_cb(const struct device *port, struct gpio_callback *cb, gpio_port_pins_t pins);
void bt_ready_cb(int err);

LOG_MODULE_REGISTER(base_station, LOG_LEVEL_INF);

//flags
bool btReady = false; 

int main(void)
{
        k_sleep(K_SECONDS(3));
        //Setup
        int err = 0; 

        //flags 
        bool sensorDataRequested = false;
        adcReady = false; 
        bool turnOnRightSide = false; 
        bool turnOnLeftSide = false; 
        ledHandleReady = false; 
        led_handle = 0; 
        wrist_conn = NULL;

        //variables
        int checkSensorNum = 0; 
        int pressureDiff = 0; 
        LED_Operation led_operation = BLANK; 
        LED_Operation* led_operation_ptr = &led_operation;   

        //get the gpio binding
        const struct device *gpio0_dev = DEVICE_DT_GET(DT_NODELABEL(gpio0));
	if (gpio0_dev == NULL) {
		LOG_ERR("Device binding is not found\n");
		return -1; 
	}

        // dynamically allocated memory        
        uint16_t* boardLedMap = init_board_led(PIN_BOARD_LED);
        if (boardLedMap == NULL){
                LOG_ERR("Initilization of board led failed\n");
        }

        //define the array to hold the selec pins 
        int adc_sel_pins[] = {PIN_ADC_SEL_0, PIN_ADC_SEL_1, PIN_ADC_SEL_2, PIN_ADC_SEL_3};

        // ---------------------------ADC INIT---------------------------//

        // //initalize the adc device tree variable 
        static const struct adc_dt_spec adc_channel = ADC_DT_SPEC_GET(DT_PATH(zephyr_user));

        struct adc_sequence_options opts = {
                .interval_us = 0,
                .callback = my_adc_sequence_callback,
                .user_data = NULL, 
                .extra_samplings = 0,
        };
        uint16_t adc_buf[ADC_BUFFER_SIZE] = {0};
        
	struct adc_sequence sequence = {
		.buffer = &adc_buf,
		/* buffer size in bytes, not number of samples */
		.buffer_size = sizeof(adc_buf),
		//Optional
		//.calibrate = true,
                .options = &opts,
	};

        int* sensorPressureMap = init_multiplexer_reader(&adc_channel, &sequence, NUM_SENSORS);
        if (sensorPressureMap == NULL) {
                LOG_ERR("Initalization of sensorPressureMap failed\n");
        }

        while(!adcReady);
        LOG_INF("ADC INITALIZATION DONE\n");
        adcReady = false; 

        err = init_multiplexer_sel(gpio0_dev, adc_sel_pins, NUM_ADC_SEL_PINS);
        if (err < 0){
                LOG_ERR("Failed to intializlize the multiplexer init pins (err %d)\n", err);
        }

        //----------------------------PWM INIT--------------------------------//
        //initalize the pwm pin and the array for the board led 
        uint16_t* led_board_map = init_board_led(PIN_BOARD_LED);

        //----------------------PAIRING BUTTON INIT--------------------------//

        //remeber to change to gpio1_dev for the buttons
        err = init_pairing_button(gpio0_dev,PIN_PAIRING_BUTTON,pairing_button_cb);

        //-----------------------BLUETOOTH SCAN TESTING----------------------//
        

        //--------------SCAN TESTING START---------------------//

        // int err = 0; 
        err = bt_enable(bt_ready_cb);
	if (err) {
		LOG_ERR("Bluetooth init failed (err %d)", err);
		return 0;
	}

        struct bt_conn_cb cb = {
                .connected = connected,
                .disconnected = disconnected,
        };

        bt_conn_cb_register(&cb);

        while(!btReady);

	const struct bt_scan_init_param bt_scan_init_opts = {
			.scan_param = NULL, //default config 
			.connect_if_match = true,
			.conn_param = NULL, //default config
	};
	
	bt_scan_init(&bt_scan_init_opts); 
        BT_SCAN_CB_INIT(scan_cb, scan_filter_match, scan_filter_no_match, scan_connecting_error, scan_connecting);
        bt_scan_cb_register(&scan_cb);

        //--------------------UUID FILTER

        err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_UUID, BT_UUID_LBS);
	if (err) {
		LOG_ERR("UUID scanning filters cannot be set (err %d)", err);
		return err;
	}

        //------------------SHORT NAME FILTER

        // struct bt_scan_short_name short_name_filter_data = {
        //         .name = TARGET_DEVICE_NAME,
        //         .min_len = sizeof(TARGET_DEVICE_NAME),
        // };

        // err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_SHORT_NAME,&short_name_filter_data);
        // if (err) {
	// 	LOG_ERR("Short Name scanning filters cannot be set (err %d)", err);
	// 	return err;
        // }

        //------------------NAME FILTER
        err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_NAME, TARGET_DEVICE_NAME);
        if (err) {
		LOG_ERR("Name scanning filters cannot be set (err %d)", err);
		return err;
        }


        err = bt_scan_filter_enable(BT_SCAN_UUID_FILTER | BT_SCAN_NAME_FILTER, true);
        // err = bt_scan_filter_enable(BT_SCAN_NAME_FILTER, true);

        if (err) {
		LOG_ERR("Filters cannot be turned on (err %d)", err);
		return err;
	}

        LOG_INF("Scan module initialized");


        err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
	if (err) {
		LOG_ERR("Scanning failed to start (err %d)", err);
		return 0;
	}

        LOG_INF("Scanning successfully started");

        //--------------SCAN TESTING END---------------------//

        *led_operation_ptr = BOARD_ALIVE;

        for(;;){

                if (sensorDataRequested == false) {
                        //send the reques to the adc to read
                        err = request_sensor_data(gpio0_dev, &adc_channel, adc_sel_pins, NUM_ADC_SEL_PINS, checkSensorNum, NUM_SENSORS, &sequence);
                        if (err < 0){
                                LOG_ERR("Failed to request the sensor data (err %d)\n", err);
                        }

                        sensorDataRequested = true; 
                }

                if(adcReady){
                        //update the array of the sensor value 
                        sensorPressureMap[checkSensorNum] = adc_buf[0];
                        //calculate the pressure difference 
                        pressureDiff = calculate_pressure_diffrential(checkSensorNum, adc_buf[0], NUM_SENSORS);

                        //based on the pressureDiff decide which side to turn on
                        turnOnLeftSide = false; 
                        turnOnRightSide = false; 
                        if (abs(pressureDiff) > PRESSURE_THRESHOLD) {
                                //yes something need to turn on
                                if(pressureDiff > 0) {
                                        turnOnRightSide = true;
                                } else {
                                        turnOnLeftSide = true; 
                                        
                                }
                        }

                        //update the led as needed 
                        update_board_led_pressure(led_board_map, turnOnLeftSide, turnOnRightSide);
                        if(ledHandleReady){
                                LOG_INF("Able to turn on wrist led");
                                updateWristLED(turnOnRightSide);
                        }

                        checkSensorNum = (checkSensorNum + 1) % NUM_SENSORS;
                        adcReady = false; 
                        sensorDataRequested = false; 
                }

                //electronics status indicator
                status_led_operation(*led_operation_ptr);

        }
        return 0;
}

/** @brief  callback function to show the user is a connection has been made or not and set flag to allow the code to begin bluetooth activites
 * 
 *     
 *  @param err: error present with the connection if at all. 
 *  
*/

void bt_ready_cb(int err){
        if (err < 0){
                LOG_ERR("Error with enabling the bluetooth module (err: %d)", err);
        } else {
                LOG_INF("Bluetooth initialized");
        }

        btReady = true; 

}


/** @brief  callback function for the pairing button
 * 
 *  Allow the bluetooth scanning to occur to accept a new wrist module
 *  TODO: Make the button keep a time state for deliteing all of the connections 
 *  
 *  @param port: device binding device structure 
 *  @param gpio_callback: structure that is used to register callback function in the config stage
 *  @param pins: bitwise repersentation of what pin callback has occured. 
 *  
 *  implement concurrency control to ensure that the updates occur correctly
*/

void pairing_button_cb(const struct device *port, struct gpio_callback *cb, gpio_port_pins_t pins){
	// Call the bluetoth advertising function to occur here. 
	uint32_t pin_vals = 0; 
        int err = 0; 

        err = gpio_port_get(port,&pin_vals);
        if (err < 0){
                LOG_ERR("Error: Unable to get gpio port levels (err: %d)", err);
        }
         //if the button is not pressed down then just return right away 
        if (!(pin_vals & (1 << PIN_PAIRING_BUTTON))) {
                return;
        }

        // err = init_bt_scan();
        // if (err < 0){
        //         LOG_ERR("Unable to initalize the bluetooth scan parameters (err: %d)\n", err);
        // }
        
        //start the scan function 
        err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
        if (err < 0) {
                LOG_ERR("Error starting the bt scan (err: %d)\n", err);
        }

};
#include "bluetooth_control.h"

LOG_MODULE_REGISTER(button_control, LOG_LEVEL_INF);

struct bt_conn *default_conn; //would need to make this into an array if more than one connection is needed to be made 

//flags 
bool ledHandleReady = false;
uint16_t led_handle = 0; 
struct bt_conn *wrist_conn = NULL;
              

/** @brief for each bond present the device is added to an accept list
 * 
 * 
 *  @param info: Local identity (mostly just BT_ID_DEFAULT). 
 *  @param user_dat: passed the current count of the number of bonds that are accounted for in the accept list 
 * 
*/
void setup_accept_list_cb(const struct bt_bond_info *info, void *user_data)
{
	int *bond_cnt = user_data;
	if ((*bond_cnt) < 0) {
		return;
	}
	int err = bt_le_filter_accept_list_add(&info->addr);
	printk("Added following peer to whitelist: %x %x \n",info->addr.a.val[0],info->addr.a.val[1]);
	if (err) {
		printk("Cannot add peer to Filter Accept List (err: %d)\n", err);
		(*bond_cnt) = -EIO;
	} else {
		(*bond_cnt)++;
	}

}

/** @brief set up an accept list for bluetooth advertising  
 * 
 * 	The function iterates over all of the bond information stored in the flash memory to add the 
 *  device to the accept list 
 * 
 *  @param local_id  Local identity (mostly just BT_ID_DEFAULT). 
 *   
 *  @return return the total devices that were bonded and added to the accept list
*/

int setup_accept_list(uint8_t local_id)
{
	int err = bt_le_filter_accept_list_clear();
	if (err) {
		printk("Cannot clear Filter Accept List (err: %d)\n", err);
		return err;
	}
	int bond_cnt = 0;
	bt_foreach_bond(local_id, setup_accept_list_cb, &bond_cnt);
	return bond_cnt;
}

/** @brief unpairs all bonded device from the system 
 * 
 * 
 *  @param work: defined using the k_work structure so the function can be submitted for multi threading work 
 *   
*/

void unpair(struct k_work *work){
	int err= bt_unpair(BT_ID_DEFAULT,BT_ADDR_LE_ANY);
	if (err) {
		LOG_INF("Cannot delete bond (err: %d)\n", err);
	} else	{
		LOG_INF("Bond deleted succesfully \n");
	}
}

K_WORK_DEFINE(unpair_work, unpair);
	

/** @brief Transmit LED on or off information 
 * 
 * 	bluetooth should be set up prior to ensure that there is a perpheral that can complete the request
 *  
 *  @param led_status bool: if the led should be on 
 * //TODO: figure out how to be able to send the led info to a peripheral. 
 *  
*/

void transmit_led_info(bool led_status){};

/** @brief Scan event handler function to handle with filter passed devices
 * 
 *	The following are the situations that can be set to check in the @ref bt_scan_filter match struct: 
	1. name //will the filter work like a contain function or a hard name? 
	2. short_name x
	3. addr x
	4. uuid //using the lbs service uuid
	5. appearance x
	6. manufacturer_data x
 *  
 *  @param device_info ptr to structure that holds device data to make a connection
 *  @param bt_scan_filter_match ptr to a struct that holds the information of filter matches for a device. Would change based on the filter opetions used
 * 	@param connectable  inform the central that the device is connectable. 
 *  
*/
void scan_filter_match(struct bt_scan_device_info *device_info, struct bt_scan_filter_match *filter_match, bool connectable)
{
    // Handle filter match event
	//assume anything with a uuid and a name that are filtered will work.
	int err; 
	
	if (filter_match->short_name.match){
		LOG_INF("NAME: ");
		for (int i = 0; i < filter_match->short_name.len; i++){
			LOG_INF("%c", filter_match->short_name.name[i]);
		}
		LOG_INF("\n");
	}

	if(filter_match->uuid.match){
		LOG_INF("UUID: ");
		for (int i = 0; i < filter_match->uuid.count; i++){
			LOG_INF("%d", filter_match->uuid.uuid[i]->type); // Logging as hexadecimal
			if (filter_match->uuid.uuid[i]->type == BT_UUID_TYPE_128) {
				LOG_INF("128 bit uuid found");
				struct bt_uuid_128 *u128 = (struct bt_uuid_128 *)filter_match->uuid.uuid;
				LOG_INF("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
						// u128->val[0], u128->val[1], u128->val[2], u128->val[3], 
						// u128->val[4], u128->val[5], 
						// u128->val[6], u128->val[7], 
						// u128->val[8], u128->val[9], 
						// u128->val[10], u128->val[11], u128->val[12], u128->val[13], u128->val[14], u128->val[15]
						
						u128->val[15], u128->val[14], u128->val[13], u128->val[12], 
						u128->val[11], u128->val[10], 
						u128->val[9], u128->val[8], 
						u128->val[7], u128->val[6], 
						u128->val[5], u128->val[4], u128->val[3], u128->val[2], u128->val[1], u128->val[0]
						);
				LOG_INF("END OF UUID 128 bit");
			}
		}
	}

	if(filter_match->name.match){
		LOG_INF("NAME: ");
		for (int i = 0; i < filter_match->name.len; i++){
			LOG_INF("%c", filter_match->name.name[i]);
		}

		LOG_INF("\n");
	}

	

	//two options: perform a manual connect operation or allow the auto connect to work? 
	if (connectable) {
		struct bt_conn *conn; 
		err = bt_conn_le_create(device_info->recv_info->addr,
								BT_CONN_LE_CREATE_CONN, 
								device_info->conn_param, 
								&conn);

		if (!err){
			if (!err) {
				default_conn = bt_conn_ref(conn);
				bt_conn_unref(conn);
			}
		}
	}



	
};

/** @brief Scan event handler function to handle with non filter passed devices
 * 		   The device information is simpley outputed for debugging purposes. 
 *  
 *  @param device_info ptr to structure that holds device data to make a connection
 * 	@param connectable  inform the central that the device is connectable. 
 *  
*/

void scan_filter_no_match(struct bt_scan_device_info *device_info, bool connectable)
{
    // Handle filter no match event
	// LOG_ERR("DEVICE WITH ALL FILTERS NOT FOUND\n");
};

/** @brief Event handler runnign when a connection is made. Output the status of the connection. 
 * 			- what device is connected to
 * 			- status of the connection 
 * 		    
 *  
 *  @param device_info ptr to structure that holds device data to make a connection
 * 	@param conn ptr to connection info
 *  
*/

void scan_connecting(struct bt_scan_device_info *device_info, struct bt_conn *conn)
{
    LOG_INF("Connected in the Scan Connecting callback\n");

	if(conn == NULL){
		LOG_ERR("The Conneciton ptr is not set properly");
	}

	// static struct bt_uuid_128 uuid = BT_UUID_INIT_128(0);
	// memcpy(&uuid, BT_UUID_LBS, sizeof(uuid));

	// struct bt_gatt_discover_params discover_params = {
	// 	.uuid = &uuid.uuid,
	// 	.func = discover_cb, //discover attribute callback 
	// 	.start_handle = 0x0001, 
	// 	.end_handle = 0xffff,
	// 	.type = BT_GATT_DISCOVER_CHARACTERISTIC,
	// };

	// wrist_conn = conn; 

	// int result = bt_gatt_discover(conn, &discover_params);
	// if (result < 0) {
	// 	LOG_ERR("Error occured when discovering the bluetooth services (err: %d)", result);
	// }
};

/** @brief Event handler runnign when a connection has failed. 
 * 			Output:
 * 			- what device was attempted to connect to
 * 			- Error/reason for the connection failing
 * 		    
 *  @param device_info ptr to structure that holds device data to make a connection
 *  
*/

void scan_connecting_error(struct bt_scan_device_info *device_info)
{
    LOG_ERR("Failed to Connect\n");
};

/** @brief Macro for establishing the scan callbacks for when scanning is started
 * 		    
 *  @param _name scan_cb name of the bt_can_cb structure that is made 
 *  @param match_fun scan_filter_match function handler for when filters match 
 *  @param no_match_fun function handler for when filters do not match a device
 *  @param err_fun handler for handling error if connection failed (connect_if_match flag in the scan param must be set for connect to occur with this callback)
 *  @param connecting_fun handler for when a connection occurs (connect_if_match flag must be present)

*/

BT_SCAN_CB_INIT(scan_cb, scan_filter_match, scan_filter_no_match, scan_connecting_error, scan_connecting);

/** @brief starting the discovery of the services after a central connection is made 
 * 
 *  @param 	bt_conn * conn: struct holding the connectin parameters
 *  @param  err if error in connection has occured
 *			   
*/

void connected(struct bt_conn *conn, uint8_t err){
	LOG_INF("IN the connected callback");
	if (err < 0){
		LOG_ERR("Conection error has occured (err %d)", err);
	}

	LOG_INF("Bluetooth Connection Sucessfull");

	if(conn == NULL){
		LOG_ERR("The Conneciton ptr is not set properly");
	}

	static struct bt_uuid_128 uuid = BT_UUID_INIT_128(0);
	memcpy(&uuid, BT_UUID_LBS, sizeof(uuid));

	struct bt_gatt_discover_params discover_params = {
		.uuid = NULL,
		.func = discover_cb, //discover attribute callback 
		.start_handle = 0x0001, 
		.end_handle = 0xffff,
		.type = BT_GATT_DISCOVER_CHARACTERISTIC,
	};

	wrist_conn = conn; 

	LOG_ERR("RIGHT BEFORE THE DISCOVER FUNCTION");
	int result = bt_gatt_discover(conn, &discover_params);
	if (result < 0) {
		LOG_ERR("Error occured when discovering the bluetooth services (err: %d)", result);
	}
};

/** @brief starting the discovery of the services after a central connection is made 
 * 
 *  @param 	bt_conn * conn: struct holding the connectin parameters
 *  @param  reason error code for why disconnected occured   
*/

void disconnected(struct bt_conn *conn, uint8_t reason){
	LOG_ERR("Disconnection occured. (err: %d)", reason);
	wrist_conn = NULL;
	ledHandleReady = false; 
};

/** @brief callback funciton to address cycling through characteristics of the incoming connection
 * 
 * 	Want to find the led characteristic of the led service then get the required information 
 * 
 *  @param bt_conn *conn: ptr to the connection parameters needed for a bluetooth conneciton 
 *  @param bt_gatt_attr *attr: the gatt attribute that is found currently 
 *  @param bt_gatt_discover_params *params: Discovery parameters that are given
 *  
 */

uint8_t discover_cb(struct bt_conn *conn, const struct bt_gatt_attr *attr, struct bt_gatt_discover_params *params){
	LOG_INF("IN THE DISCOVERY CALLBACK");
	if(attr == NULL){
		LOG_INF("Discovery complete");
		return BT_GATT_ITER_STOP;
	}

	//set the struct for a characteristic 
	struct bt_gatt_chrc *chrc = (struct bt_gatt_chrc *)attr->user_data;

	if(bt_uuid_cmp(chrc->uuid,BT_UUID_LBS_LED) == 0) {
		led_handle = chrc->value_handle;
		LOG_INF("LED characteristic handle: %u", led_handle); 
		ledHandleReady = true; 
		return BT_GATT_ITER_STOP;  
	} 

	return BT_GATT_ITER_CONTINUE; 
	// return BT_GATT_ITER_STOP; 
};

/** @brief send the updated led signal to the wrist module attached 
 * 	
 * 	Will need to write to teh led characteristic to update the led wrist module thorugh bluetooth control
 *  User must check if the led_handle and the bluetooth connection parameters are present. 
 * 	
 *  @param led_on: bool to tell if the led wrist strap is to be on or not 
 * 
 *  @return erro if present else 0. 
 */

int updateWristLED(bool led_on){
	uint8_t transmit_val[1] = {led_on};
	
	int err = bt_gatt_write_without_response(wrist_conn, led_handle,transmit_val,sizeof(transmit_val),false);
	if (err < 0){
		LOG_ERR("Error updating wrist LED (err: %d)", err);
		return err; 
	} 
	return 0; 
};

Related