Linux平台下实现BLE GATT客户端遇连接问题求助
Hey there! Let's break down what's going wrong here and get your BLE connection working properly with Bluez.
The Core Problem: Unimplemented Connection Callback
The BtIOConnect is a function pointer type, not a variable you can just declare and pass directly. When you call gatt_connect, you need to provide your own function that matches the signature Bluez expects—this function will run once the connection succeeds (or if setup completes).
First, let's clarify the callback signature from Bluez headers:
typedef void (*BtIOConnect)(GIOChannel *io, gpointer user_data);
You need to write a function that accepts these two parameters and handles the post-connection logic.
Fixing Parameter Type Mismatches
Looking at your code, you're using char for dst_type and sec_level—but these should be the proper enumeration types from Bluez:
dst_type→bdaddr_type_t(from<bluetooth/bluetooth.h>)sec_level→bt_io_sec_level_t(from<bluetooth/io.h>)
Usingcharhere causes type mismatches that lead to undefined behavior.
Full Working Example Code
Here's a corrected version of your code with a proper callback, fixed types, and basic error handling:
#include <stdio.h> #include <glib.h> #include <bluetooth/bluetooth.h> #include <bluetooth/hci.h> #include <bluetooth/hci_lib.h> #include <bluetooth/io.h> #include <bluetooth/gatt.h> // Custom connection callback function void my_connect_cb(GIOChannel *io, gpointer user_data) { g_print("Successfully connected to the BLE device!\n"); // Add your post-connection logic here: // - Read/write GATT characteristics // - Subscribe to notifications // - Initialize a GATT client with gatt_client_new(io, ...) } int main() { const char *device_addr = "XX:XX:XX:XX:XX:XX"; // Replace with your device's address bdaddr_type_t addr_type = BDADDR_LE_RANDOM; // Use BDADDR_LE_PUBLIC if your device uses a public address bt_io_sec_level_t sec_level = BT_IO_SEC_LOW; GError *error = NULL; GIOChannel *channel; // Initialize GLib (required for Bluez's async event system) g_type_init(); // Attempt to connect to the BLE device channel = gatt_connect( NULL, // No specific adapter (use default) device_addr, &addr_type, &sec_level, 0, // No I/O options 0, // No GATT options my_connect_cb, // Our custom callback &error ); // Handle connection errors if (error != NULL) { g_printerr("Connection failed: %s\n", error->message); g_error_free(error); return 1; } if (!channel) { g_printerr("Failed to create GIO channel for connection\n"); return 1; } // Start the GLib main loop to process async events (like the connection callback) // Without this, the program will exit before the connection completes g_main_loop_run(g_main_loop_new(NULL, FALSE)); // Cleanup (only runs if the main loop exits) g_io_channel_unref(channel); return 0; }
Key Notes to Avoid Issues
- GLib Main Loop: Bluez relies on GLib's asynchronous event system. You must run the main loop to trigger the connection callback—otherwise, your program will exit before the connection is established.
- Address Type: Double-check if your device uses a random or public BLE address. You can confirm this with
hcitool lescan(random addresses typically have a specific bit pattern in the first octet). - Permissions: Your program needs access to the Bluetooth adapter. Run it with
sudoor set the appropriate capabilities:setcap cap_net_raw+ep ./your_program. - Bluez Version: Ensure you're using Bluez 5.40 or newer—older versions may have different API signatures that break this code.
内容的提问来源于stack exchange,提问作者ble_beginner

