Bluez-Based C language Bluetooth Programming
There are many reasons for us to use C instead of other advanced languages such as Python to develop Bluetooth applications. The Python environment may not be suitable for embedded systems. Because the embedded system imposes strict restrictions on the program size, running speed, and storage space occupied, all of these make it impossible for an explanatory language like python to be applied on an embedded system. Programmers need to better control the local Bluetooth adapter, or create a dynamic link library to facilitate the connection of other applications to replace a single application. As described above, bluez is a powerful Bluetooth communication protocol stack. Its Extended APIs allow users to conveniently manipulate a large amount of Bluetooth resources. However, bluez does not have official Descriptive documents, or even few unofficial documents. Beginners request related documents on bluez's official email list. The usual reply is to be notified. Please read the source code carefully to learn about the API functions. Reading the source code of bluez is a very time-consuming task for beginners, and the progress made in the short term is quite limited. It is likely to become a obstacle for many beginners of Bluetooth programming.
This chapter briefly describes the method of C language Bluetooth Programming Based on bluez. This chapter further describes the knowledge points involved in Chapter 2 for C programmers.
4.1 select a communication object.
Example 4-1 is a simple application for searching peripheral Bluetooth devices. The program first obtains the system's bluetooth device number, scans the peripheral bluetooth device, and finds the name of each searched bluetooth device. Detailed descriptions of data structures and functions are provided later.
Example 4-1. simplescan. c
# Include
# Include
# Include
# Include
# Include
# Include
# Include
Int main (INT argc, char ** argv)
{
Inquiry_info * II = NULL;
Int max_rsp, num_rsp;
Int dev_id, Sock, Len, flags;
Int I;
Char ADDR [19] = {0 };
Char name [248] = {0 };
Dev_id = hci_get_route (null );
Sock = hci_open_dev (dev_id );
If (dev_id <0 | sock <0 ){
Perror ("Opening socket ");
Exit (1 );
}
Len = 8;
Max_rsp = 255;
Flags = ireq_cache_flush;
II = (inquiry_info *) malloc (max_rsp * sizeof (inquiry_info ));
Num_rsp = hci_inquiry (dev_id, Len, max_rsp, null, & ii, flags );
If (num_rsp <0) perror ("hci_inquiry ");
For (I = 0; I <num_rsp; I ++ ){
Ba2str (& (ii + I)-> bdaddr, ADDR );
Memset (name, 0, sizeof (name ));
If (hci_read_remote_name (sock, & (ii + I)-> bdaddr, sizeof (name ),
Name, 0) <0)
Strcpy (name, "[UNKNOWN]");
Printf ("% S % s/n", ADDR, name );
}
Free (II );
Close (sock );
Return 0;
}
4.1.1 Compilation
For compilation, you need to use GCC to link the libbluetooth library.
# Gcc-O simplescan. C-lbluetooth
4.1.2. Explanation
Typedef struct {
Uint8_t B [6];
} _ Attribute _ (packed) bdaddr_t;
The address of the bluetooth device is described by the structure bdaddr_t. The storage and operation of the Bluetooth address of the bluez squadron use the bdaddr_t structure. bluez provides two functions to convert the string to the Bluetooth address.
Int str2ba (const char * STR, bdaddr_t * Ba );
Int ba2str (const bdaddr_t * Ba, char * Str );
Str2ba converts a string in the form of XX: XX (XX represents a hexadecimal byte of the 48-bit Bluetooth address) into a 6-byte bdaddr_t structure, ba2str completes the opposite function.
The local Bluetooth adapter is assigned an identification number starting from 0. The program must specify the Bluetooth adapter when allocating system resources. Generally, the system only has one Bluetooth adapter. Pass the null parameter to hci_get_route to obtain the first valid Bluetooth adapter identification number.
Int hci_get_route (bdaddr_t * bdaddr );
Int hci_open_dev (INT dev_id );
[Note] it is inappropriate to specify the device Number of the adapter as 0 because it does not always represent the first available Bluetooth adapter. For example, if the system has two bluetooth adapters and the first is disable, the first valid device number is 2.
If multiple Bluetooth adapters exist, select "01: 23: 45: 67: 89: AB" as the address of the Bluetooth adapter, and pass the pointer char * representation indicating this address to the hci_devid function, use this function to replace hci_get_route.
Many Bluetooth operations require a set of interfaces. The hci_open_dev function can open a set of interfaces for a specific resource number. Specifically, the socket opened by hci_open_dev establishes a connection with the local Bluetooth adapter controller, instead of connecting to a remote Bluetooth device. You can use this interface to send commands to the Bluetooth controller to perform underlying Bluetooth operations. This section is discussed in detail in section 4.5.
After selecting the local Bluetooth adapter and allocating system resources, the program can start scanning the peripheral bluetooth device. In this routine, the hci_inquiry function completes the search for the bluetooth device, and record the returned device information data in variable II. When an error occurs, it returns-1 and sets the errno variable.
Int hci_inquiry (INT dev_id, int Len, int max_rsp, const uint8_t * lap,
Inquiry_info ** II, long flags );
The parameters of hci_inquiry need to use the device resource number instead of the Set interface. Therefore, we use the return value dev_id of the hci_get_route function to pass it. The query duration lasts for up to 1.28 * Len seconds. The information returned by max_rsp settings is stored in variable II. This variable must have enough space to store the results returned by max_rsp. We recommend that you set max_rsp to 255 to complete the standard 10.24-second query.
If the flag is set to ireq_cache_flush, the cache of the previous query record is refreshed during the query operation. Otherwise, if the flag is set to 0, even if the device in the previous query is no longer in the valid range, the records in the previous query will be returned.
The inquiry_info struct is defined as follows:
Typedef struct {
Bdaddr_t bdaddr;
Uint8_t pscan_rep_mode;
Uint8_t pscan_period_mode;
Uint8_t pscan_mode;
Uint8_t dev_class [3];
Uint16_t clock_offset;
} _ Attribute _ (packed) inquiry_info;
In most cases, we only use the member bdaddr, which identifies the Bluetooth address of the device. In some cases, we also use the member dev_class, which identifies some information of the detected bluetooth device (for example, identifying the device as a print device, phone number, or personal computer ), for more information about the relationship, see [3]. Other members are used for underlying communication, which is generally not commonly used. Interested readers can read the Bluetooth kernel specification [4] for more information. Once the peripheral bluetooth device and its Bluetooth address are detected, the program can provide the name of the device to the user, and the hci_read_remote_name function can complete this function.
Int hci_read_remote_name (INT sock, const bdaddr_t * Ba, int Len,
Char * Name, int timeout)
The hci_read_remote_name function uses a set of interfaces to obtain the name of the bluetooth device through the Bluetooth address Ba within the specified timeout period. After successful return, 0 is returned and the obtained bluetooth device name is saved to the name; if an error occurs,-1 is returned and the corresponding errno is set.
Notes
[1] http://www.bluez.org/lists.html
[2] for the curious, it makes a call to socket (af_bluetooth, sock_raw, btproto_hci), followed by a call to bind with the specified resource number.
[3] https://www.bluetooth.org/foundry/assignnumb/document/baseband
[4] http://www.bluetooth.org/spec