|
Architecture
Describes the overall architecture and how clients interact with the stack.
Featured IntroductionBTstack is a Bluetooth stack that is mainly designed for embedded devices where resources are scarce. Despite scarce resources, it allows multiple applications to make use of Bluetooth services at the same time. The BTstack architecture consists of a Bluetooth server, called BTdaemon, which handles client requests, and a corresponding client library, which forwards the requests to the BTdaemon. In the following, the design of the BTdaemon is explained in more detail. BTdaemon ArchitectureThe BTdaemon is necessary to handle multiple clients. Clients use the BTstack client library to communicate with the BTdaemon over TCP or Unix sockets. In addition to necessary socket server, the other main components of the BTdaemon are: a run loop and the actual Bluetooth stack. The Bluetooth stack and the socket server are implemented as a collection of finite state machines. The state machines are executed by a single run loop, where all sockets and the Bluetooth module are registered as individual data sources. This design allows for a single-threaded implementation, which avoids concurrency problems and facilitates porting and running BTstack on embedded systems. As embedded systems usually implement a single functionality, support for multiple clients results in an unnecessary overhead. In this case, e.g., to support 8-bit microcontrollers, the socket server can be omitted and the client directly integrated into the BTdaemon run loop.
Posix Run Loop ImplementationIn the widely spread Posix standard, everything (files, I/Os, sockets, devices) is accessed via file descriptors. The BTdaemon's run loop is exploiting this fact to manage multiple data sources without multithreading. Such a data source is defined by a file descriptor and an associated data_source_ready handler: typedef struct data_source {
linked_item_t item; // <-- used internally by RunLoop
int fd; // <-- file descriptors to watch or 0
int (*data_source_ready)(struct data_source *ds); // <-- handler
} data_source_t;All data sources are tracked in parallel using the select() call. For a detailed introduction into handling of multiple file descriptors within a single thread, check this single-threaded socket server. Besides data sources, the BTdaemon needs to track various Bluetooth-related timeout events. For example, the BTdaemon supports an option to turn off the Bluetooth module one minute after the last client disconnects. The tracking of timeouts is also performed by the run loop. For this, the run loop maintains a list of timeout events associated with the timeout (callback) handler and an optional callback argument. The list is ordered by time, such that the earliest timeout appears as the first element. The run loop then uses the interval between the current time and the earliest timeout as timeout parameter in the select() call. After select() returns, the run loop calls the callback handlers of all file descriptors returned by the select() are called, and those of the expired timeouts. The described run loop approach is compatible with many GUI frameworks, notably Cocoa on Mac OS X and CocoaTouch on the iPhone. As the BTstack client library is also designed to be executed by a run loop, it can be readily integrated into GUI applications. Flow ControlHandling flow control for various data streams in a Bluetooth stack is tedious job. So far, BTstack implements:
Shared stateThe state shared between all connected clients consists of:
Modular DesignThe BTstack was designed in a modular fashion: it provides an interface for "pluging-in" different run loop, HCI transport, and Bluetooth hardware control implementations. The run loop has to be set first by calling run_loop_init({RUN_LOOP_POSIX, RUN_LOOP_COCOA}). The HCI layer is constructed with a pointer to an hci_transport_t structure, a pointer to an HCI transport configuration structure and a pointer to an bt_control_t structure. HCI Transport APIThe HCI Transport API allows the BTdaemon to use different transport implementations. The hci_tranport_t control structure contains a data_source_t structure used for the single-thread implementation. typedef struct {
int (*open)(void *transport_config);
int (*close)();
int (*send_packet)(uint8_t packet_type, uint8_t *packet, int size);
void (*register_packet_handler)(void (*handler)(uint8_t packet_type, uint8_t *packet, int size));
const char * (*get_transport_name)();
} hci_transport_t;Note: packet sizes are not needed for HCI packets (ACL, Command, Event), as they themselves contain length information. They could be removed from the function parameters, but are kept for efficient code. Bluetooth Hardware Control APIThe Bluetooth hardware control API allows the HCI layer to initialize, turn on/off the Bluetooth module, and configure a particular transport protocol including the physical connection (H4/H5/USB, device path, baud rate, flow control, Vendor ID, Product ID). This is device specific, e.g., turning on Bluetooth on the iPhone requires to make use of Apple's BlueTool; on the BTnode, the power is controlled by a special kernel function, etc. GoodiesHCI LoggingBTdaemon is able to write HCI dumps in several formats. It supports both the bluez-hcidump format, which can be read by: the hcidump tool, the GNOME Bluetooth-Analyzer, the Wireshark, and the Apple's PacketLogger format. In addition, it can dump raw HCI packets in hex. Development/DebuggingSo far, only Bluetooth modules connected by a serial connection (H4/H5) are supported. To communicate with USB Bluetooth modules, which are not supported yet, the cross-platform libUSB library can be employed. An early version of an HCI USB Transport implementation is included and should simplify the development/debugging of BTstack applications on standard desktops. More on it can be found on the HCI USB Transport page. References
|
Oops! Google Chrome could not find wiki.bluez.org
weird. can't find it either, but updated the wiki. thanks for the hint.