\documentclass[a4paper,titlepage,oneside,12pt]{amsart} %amsart \usepackage{graphicx} \usepackage{hyperref} %\usepackage{geometry} % see geometry.pdf on how to lay out the page. There's lots. \usepackage[margin=1.3in]{geometry} \geometry{a4paper} % or letter or a5paper or ... etc % \geometry{landscape} % rotated page geometry \usepackage{ifthen} % See the ``Article customise'' template for come common customisations \usepackage[usenames,dvipsnames]{color} \usepackage[table]{xcolor} \definecolor{lightgray}{RGB}{245, 245, 245} \definecolor{bkblue}{RGB}{18, 47, 76} \definecolor{bklightblue}{RGB}{102, 131, 158} \definecolor{mygreen}{rgb}{0,0.6,0} \definecolor{orange}{RGB}{255,153,0} \usepackage{opensans} \usepackage{setspace} \usepackage{booktabs} \newcommand{\ra}[1]{\renewcommand{\arraystretch}{#1}} \usepackage{color} % show todos \newcommand{\todo}[1]{\colorbox{yellow}{#1}} % ignore todos % \newcommand{\todo}[1]{} \newcommand{\toread}[1]{{\color{bklightblue} #1}} \usepackage{listings} \lstset{ % float, language=C, % choose the language of the code basicstyle=\footnotesize, % the size of the fonts that are used for the code %numbers=left, % where to put the line-numbers %numberstyle=\footnotesize, % the size of the fonts that are used for the line-numbers %stepnumber=1, % the step between two line-numbers. If it is 1 each line will be numbered %numbersep=5pt, % how far the line-numbers are from the code backgroundcolor=\color{lightgray}, % choose the background color. You must add \usepackage{color} showspaces=false, % show spaces adding particular underscores showstringspaces=false, % underline spaces within strings showtabs=false, % show tabs within strings adding particular underscores frame=single, % adds a frame around the code framerule=0.2pt, tabsize=2, % sets default tabsize to 2 spaces captionpos=b, % sets the caption-position to bottom breaklines=true, % sets automatic line breaking breakatwhitespace=false, % sets if automatic breaks should only happen at whitespace escapeinside={\%*}{*)}, % if you want to add a comment within your code belowcaptionskip=5em, belowskip=1em, aboveskip=1.8em, commentstyle=\itshape\color{mygreen}, keywordstyle=\bfseries\color{black}, identifierstyle=\color{black}, stringstyle=\color{blue}, morekeywords={*, timer_source_t, data_source_t, uint32_t, uint16_t, uint8_t, RUN_LOOP_TYPE, le_command_status_t, gatt_client_t, le_characteristic_t, le_service_t, le_characteristic_descriptor_t, service_record_item_t, bd_addr_t, btstack_packet_handler_t, hci_cmd_t, bt_control_t, remote_device_db_t, link_key_t, device_name_t, hci_transport_t, hci_uart_config_t, sdp_query_event_t, sdp_query_complete_event_t, sdp_query_rfcomm_service_event_t, sdp_parser_event_t, sdp_parser_event_type_t, sdp_parser_attribute_value_event_t, sdp_parser_complete_event_t, advertising_report_t, gc_state_t, le_service_event_t, le_characteristic_event_t} } % Bluetopia & TI MSP430 + Stellaris % http://processors.wiki.ti.com/index.php/CC256x_Bluetopia_Stack#Demos % Setup MSP430+PAN1315 % \newcommand{\versionNr}{1.3} \newcommand{\authorMila}{Dr. sc. Milanka Ringwald} \newcommand{\authorMatthias}{Dr. sc. Matthias Ringwald} \newcommand{\bkContact}{\href{contact@bluekitchen-gmbh.com}{contact@bluekitchen-gmbh.com}} \newcommand{\barWidth}{0.3cm} \newcommand{\urlfoot}[2]{\href{#1}{{\color{blue} #2}}\footnote{#1}} \makeatletter \renewcommand{\maketitle}{ \begin{titlepage} \fosfamily \begin{center} \begin{minipage}[b]{\textwidth} \begin{minipage}[b]{.1\textwidth} \color{bkblue}\rule{\barWidth{}}{22cm} \end{minipage} \hfill\begin{minipage}[b]{.8\textwidth}\begin{flushright} {\color{bkblue} % VERSION \versionNr{} \\ \today \\} \vspace*{7.5cm} \hfill\includegraphics[width=0.85\textwidth]{picts/bklogo.pdf} \vspace*{1.5cm} \begin{spacing}{2} {\huge \color{bkblue} \@title} \\ {\Large \color{bklightblue} Including Quickstart Guide} \end{spacing} \vspace*{1.5cm} {\color{bkblue}\large \authorMila \\ \large \authorMatthias \\ \large \bkContact\\ } \end{flushright}\end{minipage} \vfill \begin{minipage}[b]{\textwidth} \color{bklightblue}\rule{\barWidth{}}{\barWidth{}} \end{minipage} \end{minipage} \end{center} \end{titlepage} } \makeatother \title[BTstack Manual] {BTstack Manual} \author{Copyright \copyright 2012-2015 BlueKitchen GmbH} %%% BEGIN DOCUMENT \newcommand{\UserGuide}{\urlfoot{http://processors.wiki.ti.com/index.php/PAN1315EMK\_User\_Guide\#RF3\_Connector}{User Guide}{}} \newcommand{\MSPGCCWiki}{\urlfoot{http://sourceforge.net/apps/mediawiki/mspgcc/index.php?title=MSPGCC\_Wiki}{MSPGCC Wiki}} \newcommand{\GNUMake}{\urlfoot{http://gnuwin32.sourceforge.net/packages/make.htm}{GNU Make}} \newcommand{\Python}{\urlfoot{http://www.python.org/getit/}{Python}} \newcommand{\mspgcc}{\urlfoot{http://sourceforge.net/projects/mspgcc/files/Windows/mingw32/}{mspgcc}} \newcommand{\BTSfile}{\urlfoot{http://processors.wiki.ti.com/index.php/CC256x\_Downloads}{BTS file}} \newcommand{\MSPFlasher}{\urlfoot{http://processors.wiki.ti.com/index.php/MSP430\_Flasher\_-\_Command\_Line\_Programmer}{MSP430Flasher}} \newcommand{\MSPDebug}{\urlfoot{http://mspdebug.sourceforge.net/}{MSPDebug}} \newcommand{\BtstackGithub}{\urlfoot{https://github.com/bluekitchen/btstack/archive/master.zip}{BTstack's page}} \newcommand{\gccarm}{\urlfoot{https://launchpad.net/gcc-arm-embedded}{arm-gcc}} \newcommand{\OpenOCD}{\urlfoot{http://openocd.org}{OpenOCD}} \newcommand{\mplabxc}{\urlfoot{http://www.microchip.com/pagehandler/en\_us/devtools/mplabxc/}{MPLAB XC}} \newcommand{\PICkit}{\urlfoot{http://www.microchip.com/DevelopmentTools/ProductDetails.aspx?PartNO=pg164130}{PICkit 3}} \newcommand{\pkgconfig}{\urlfoot{http://www.freedesktop.org/wiki/Software/pkg-config/}{pkg-config}} \newcommand{\libusb}{\urlfoot{www.libusb.org}{libusb}} \newcommand{\Zadig}{\urlfoot{http://zadig.akeo.ie}{Zadig}} \newcommand{\MSYS}{\urlfoot{www.mingw.org/wiki/msys}{MSYS}} \newcommand{\MINGW}{\urlfoot{www.mingw.org}{MINGW32}} %level -1: part, 0: chapter, 1: section, etc. \setcounter{tocdepth}{3} \begin{document} \maketitle \tableofcontents \pagebreak Thanks for checking out BTstack! In this manual, we first provide a 'quick starter guide' for common platforms before highlighting BTstack's main design choices and go over all implemented protocols and profiles. A series of examples show how BTstack can be used to implement common use cases. Finally, we outline the basic steps when integrating BTstack into existing single-threaded or even multi-threaded environments. The Revision History is shown in the Appendix \ref{appendix:revision_history} on page \pageref{appendix:revision_history}. \section{Quick Start} \subsection{General Tools} On Unix-based systems, git, make, and Python are usually installed. If not, use the system's packet manager to install them. On Windows, you need to manually install and configure GNU Make, Python, and optionally git : \begin{itemize} \item \GNUMake{} for Windows: Add its bin folder to the Windows Path in Environment Variables. The bin folder is where make.exe resides, and it's usually located in \path{C:\Program Files\GnuWin32\bin}. \item \Python{} for Windows: Add Python installation folder to the Windows Path in Environment Variables. \end{itemize} Adding paths to the Windows Path variable: \begin{itemize} \label{sec:windowsPath} \item Go to: Control Panel$\rightarrow$System$\rightarrow$Advanced tab$\rightarrow$Environment Variables. \item The top part contains a list of User variables. \item Click on the Path variable and then click edit. \item Go to the end of the line, then append the path to the list., for example, \path{C:\Program Files\GnuWin32\bin} for GNU Make. \item Ensure that there is a semicolon before and after \path{C:\Program Files\GnuWin32\bin}. \end{itemize} \subsection{Getting BTstack from GitHub} Use git to clone the latest version: \begin{lstlisting} git clone https://github.com/bluekitchen/btstack.git \end{lstlisting} Alternatively, you can download it as a ZIP archive from \BtstackGithub{}on GitHub. \subsection{Compiling the examples and loading firmware} This step is platform specific. To compile and run the examples, you need to download and install the platform specific toolchain and a flash tool. For TI's CC256x chipsets, you also need the correct init script, or "Service Pack" in TI nomenclature. Assuming that these are provided, go to \path{btstack/platforms/$PLATFORM$} folder in command prompt and run make. If all the paths are correct, it will generate several firmware files. These firmware files can be loaded onto the device using platform specific flash programmer. For the PIC32-Harmony platform, a project file for the MPLAB X IDE is provided, too. \begin{table*}\centering \caption{Overview of platform specific toolchains, programmers, and used chipsets.} \resizebox{\textwidth}{!}{\begin{minipage}{\textwidth} \rowcolors{1}{lightgray}{white} \begin{tabular}{p{4cm}p{2cm}p{3cm}p{4cm} } \toprule \hiderowcolors Platform & Chipset & Toolchain & Programmer\\ \showrowcolors \midrule ez430-rf2560, msp-exp430f5438, msp430f5229lp & CC256x & \mspgcc{} & \MSPFlasher{}, \MSPDebug{} \\ stm32-f103rb-nucleo & CC256x & \gccarm{} & \OpenOCD{} \\ pic32-harmony & CSR8811 & \mplabxc{} & \PICkit{} \\ \hiderowcolors libusb on Linux/OS X & any & any & N/A \\ \bottomrule \label{table:platformCompiler} \end{tabular} \end{minipage} } \end{table*} \subsection{Run the Example} As a first test, we recommend the SPP Counter example (see Section \ref{example:spp_counter}). During the startup, for TI chipsets, the init script is transferred, and the Bluetooth stack brought up. After that, the development board is discoverable as "BTstack SPP Counter" and provides a single virtual serial port. When you connect to it, you'll receive a counter value as text every second. % The SPP Counter doesn't use the display to keep the memory footprint small. % The HID demo has a fancier user interface - it uses a display to show the discovery process and connection establishment with a Bluetooth keyboard, as well as the text as you type. \subsection{Platform specifics} \input{quickstart_platforms} \section{BTstack Architecture} As well as any other communication stack, BTstack is a collection of state machines that interact with each other. There is one or more state machines for each protocol and service that it implements. The rest of the architecture follows these fundamental design guidelines: \begin{itemize} \item \emph{Single threaded design} - BTstack does not use or require multi-threading to handle data sources and timers. Instead, it uses a single run loop. \item \emph{No blocking anywhere} - If Bluetooth processing is required, its result will be delivered as an event via registered packet handlers. \item \emph{No artificially limited buffers/pools} - Incoming and outgoing data packets are not queued. \item \emph{Statically bounded memory (optionally)} - The number of maximum connections/channels/services can be configured. \end{itemize} \begin{figure}[htbp] % figure placement: here, top, bottom, or page \centering \includegraphics[width=\textwidth]{picts/btstack-architecture.pdf} \caption{BTstack-based single-threaded application. The Main Application contains the application logic, e.g., reading a sensor value and providing it via the Communication Logic as a SPP Server. The Communication Logic is often modeled as a finite state machine with events and data coming from either the Main Application or from BTstack via registered packet handlers (PH). BTstack's Run Loop is responsible for providing timers and processing incoming data. } \label{fig:BTstackArchitecture} \end{figure} Figure \ref{fig:BTstackArchitecture} shows the general architecture of a BTstack-based application that includes the BTstack run loop. \subsection{Single threaded design} BTstack does not use or require multi-threading. It uses a single run loop to handle data sources and timers. Data sources represent communication interfaces like an UART or an USB driver. Timers are used by BTstack to implement various Bluetooth-related timeouts. For example, to disconnect a Bluetooth baseband channel without an active L2CAP channel after 20 seconds. They can also be used to handle periodic events. During a run loop cycle, the callback functions of all registered data sources are called. Then, the callback functions of timers that are ready are executed. For adapting BTstack to multi-threaded environments, see Section \ref{section:multithreading}. \subsection{No blocking anywhere} Bluetooth logic is event-driven. Therefore, all BTstack functions are non-blocking, i.e., all functions that cannot return immediately implement an asynchronous pattern. If the arguments of a function are valid, the necessary commands are sent to the Bluetooth chipset and the function returns with a success value. The actual result is delivered later as an asynchronous event via registered packet handlers. If a Bluetooth event triggers longer processing by the application, the processing should be split into smaller chunks. The packet handler could then schedule a timer that manages the sequential execution of the chunks. \subsection{No artificially limited buffers/pools} Incoming and outgoing data packets are not queued. BTstack delivers an incoming data packet to the application before it receives the next one from the Bluetooth chipset. Therefore, it relies on the link layer of the Bluetooth chipset to slow down the remote sender when needed. Similarly, the application has to adapt its packet generation to the remote receiver for outgoing data. L2CAP relies on ACL flow control between sender and receiver. If there are no free ACL buffers in the Bluetooth module, the application cannot send. For RFCOMM, the mandatory credit-based flow-control limits the data sending rate additionally. The application can only send an RFCOMM packet if it has RFCOMM credits. \subsection{Statically bounded memory} BTstack has to keep track of services and active connections on the various protocol layers. The number of maximum connections/channels/services can be configured. In addition, the non-persistent database for remote device names and link keys needs memory and can be be configured, too. These numbers determine the amount of static memory allocation. \section{How to use BTstack} BTstack implements a set of basic Bluetooth protocols. To make use of these to connect to other devices or to provide own services, BTstack has to be properly configured during application startup. In the following, we provide an overview of the memory management, the run loop, and services that are necessary to setup BTstack. From the point when the run loop is executed, the application runs as a finite state machine, which processes events received from BTstack. BTstack groups events logically and provides them over packet handlers, of which an overview is provided here. Finally, we describe the RFCOMM credit-based flow-control, which may be necessary for resource-constraint devices. Complete examples for the MSP430 platforms will be presented in Chapter \ref{section:examples}. \subsection{Memory configuration} \label{section:memory_configuration} The structs for services, active connections and remote devices can be allocated in two different manners: \begin{itemize} \item statically from an individual memory pool, whose maximal number of elements is defined in the config file. To initialize the static pools, you need to call \emph{btstack\_memory\_init} function. An example of memory configuration for a single SPP service with a minimal L2CAP MTU is shown in Listing \ref{memoryConfigurationSPP}. \item dynamically using the \emph{malloc/free} functions, if HAVE\_MALLOC is defined in config file. \end{itemize} If both HAVE\_MALLOC and maximal size of a pool are defined in the config file, the statical allocation will take precedence. In case that both are omitted, an error will be raised. The memory is set up by calling \emph{btstack\_memory\_init} function: \begin{lstlisting} btstack_memory_init(); \end{lstlisting} \subsection{Run loop} \label{section:run_loop} BTstack uses a run loop to handle incoming data and to schedule work. The run loop handles events from two different types of sources: data sources and timers. Data sources represent communication interfaces like an UART or an USB driver. Timers are used by BTstack to implement various Bluetooth-related timeouts. They can also be used to handle periodic events. Data sources and timers are represented by the \emph{data\_source\_t} and \emph{timer\_source\_t} structs respectively. Each of these structs contain a linked list node and a pointer to a callback function. All active timers and data sources are kept in link lists. While the list of data sources is unsorted, the timers are sorted by expiration timeout for efficient processing. The complete run loop cycle looks like this: first, the callback function of all registered data sources are called in a round robin way. Then, the callback functions of timers that are ready are executed. Finally, it will be checked if another run loop iteration has been requested by an interrupt handler. If not, the run loop will put the MCU into sleep mode. Incoming data over the UART, USB, or timer ticks will generate an interrupt and wake up the microcontroller. In order to avoid the situation where a data source becomes ready just before the run loop enters sleep mode, an interrupt-driven data source has to call the \emph{embedded\_trigger} function. The call to \emph{embedded\_trigger} sets an internal flag that is checked in the critical section just before entering sleep mode. Timers are single shot: a timer will be removed from the timer list before its event handler callback is executed. If you need a periodic timer, you can re-register the same timer source in the callback function, as shown in Listing \ref{PeriodicTimerHandler}. Note that BTstack expects to get called periodically to keep its time, see Section \ref{section:timeAbstraction} for more on the tick hardware abstraction. The Run loop API is provided in Appendix \ref{appendix:api_run_loop}. To enable the use of timers, make sure that you defined HAVE\_TICK in the config file. In your code, you'll have to configure the run loop before you start it as shown in Listing \ref{listing:btstackInit}. The application can register data sources as well as timers, e.g., periodical sampling of sensors, or communication over the UART. The run loop is set up by calling \emph{run\_loop\_init} function for embedded systems: \begin{lstlisting} run_loop_init(RUN_LOOP_EMBEDDED); \end{lstlisting} \begin{lstlisting}[float, caption=Periodic counter, label=PeriodicTimerHandler] #define TIMER_PERIOD_MS 1000 timer_source_t periodic_timer; void register_timer(timer_source_t *timer, uint16_t period){ run_loop_set_timer(timer, period); run_loop_add_timer(timer); } void timer_handler(timer_source_t *ts){ // do something, ... e.g., increase counter, // then re-register timer register_timer(ts, TIMER_PERIOD_MS); } void timer_setup(){ // set one-shot timer run_loop_set_timer_handler(&periodic_timer, &timer_handler); register_timer(&periodic_timer, TIMER_PERIOD_MS); } \end{lstlisting} \subsection{BTstack initialization} \label{section:btstack_initialization} To initialize BTstack you need to initialize the memory and the run loop as explained in Sections \ref{section:memory_configuration} and \ref{section:run_loop} respectively, then setup HCI and all needed higher level protocols. The HCI initialization has to adapt BTstack to the used platform and requires four arguments. These are: \begin{itemize} \item \emph{Bluetooth hardware control}: The Bluetooth hardware control API can provide the HCI layer with a custom initialization script, a vendor-specific baud rate change command, and system power notifications. It is also used to control the power mode of the Bluetooth module, i.e., turning it on/off and putting to sleep. In addition, it provides an error handler \emph{hw\_error} that is called when a Hardware Error is reported by the Bluetooth module. The callback allows for persistent logging or signaling of this failure. Overall, the struct \emph{bt\_control\_t} encapsulates common functionality that is not covered by the Bluetooth specification. As an example, the \emph{bt\_con-trol\_cc256x\_in-stance} function returns a pointer to a control struct suitable for the CC256x chipset. \end{itemize} \begin{lstlisting} bt_control_t * control = bt_control_cc256x_instance(); \end{lstlisting} \begin{itemize} \item \emph{HCI Transport implementation}: On embedded systems, a Bluetooth module can be connected via USB or an UART port. BTstack implements two UART based protocols: HCI UART Transport Layer (H4) and H4 with eHCILL support, a lightweight low-power variant by Texas Instruments. These are accessed by linking the appropriate file (\path{src/hci_transport_h4_dma.c} resp. \path{src/hci_transport_h4_ehcill_dma.c)} and then getting a pointer to HCI Transport implementation. For more information on adapting HCI Transport to different environments, see Section \ref{section:hci_transport}. \end{itemize} \begin{lstlisting} hci_transport_t * transport = hci_transport_h4_dma_instance(); \end{lstlisting} \begin{itemize} \item \emph {HCI Transport configuration}: As the configuration of the UART used in the H4 transport interface are not standardized, it has to be provided by the main application to BTstack. In addition to the initial UART baud rate, the main baud rate can be specified. The HCI layer of BTstack will change the init baud rate to the main one after the basic setup of the Bluetooth module. A baud rate change has to be done in a coordinated way at both HCI and hardware level. First, the HCI command to change the baud rate is sent, then it is necessary to wait for the confirmation event from the Bluetooth module. Only now, can the UART baud rate changed. As an example, the CC256x has to be initialized at 115200 and can then be used at higher speeds. \end{itemize} \begin{lstlisting} hci_uart_config_t* config = hci_uart_config_cc256x_instance(); \end{lstlisting} \begin{itemize} \item \emph {Persistent storage} - specifies where to persist data like link keys or remote device names. This commonly requires platform specific code to access the MCU's EEPROM of Flash storage. For the first steps, BTstack provides a (non) persistent store in memory. For more see Section \ref{section:persistent_storage}. \end{itemize} \begin{lstlisting} remote_device_db_t * remote_db = &remote_device_db_memory; \end{lstlisting} After these are ready, HCI is initialized like this: \begin{lstlisting} hci_init(transport, config, control, remote_db); \end{lstlisting} The higher layers only rely on BTstack and are initialized by calling the respective \emph{*\_init} function. These init functions register themselves with the underlying layer. In addition, the application can register packet handlers to get events and data as explained in the following section. \subsection{Services} One important construct of BTstack is \emph{service}. A service represents a server side component that handles incoming connections. So far, BTstack provides L2CAP and RFCOMM services. An L2CAP service handles incoming connections for an L2CAP channel and is registered with its protocol service multiplexer ID (PSM). Similarly, an RFCOMM service handles incoming RFCOMM connections and is registered with the RFCOMM channel ID. Outgoing connections require no special registration, they are created by the application when needed. \begin{lstlisting}[float, caption=Memory configuration for an SPP service with a minimal L2CAP MTU., label=memoryConfigurationSPP] #define HCI_ACL_PAYLOAD_SIZE 52 #define MAX_SPP_CONNECTIONS 1 #define MAX_NO_HCI_CONNECTIONS MAX_SPP_CONNECTIONS #define MAX_NO_L2CAP_SERVICES 2 #define MAX_NO_L2CAP_CHANNELS (1+MAX_SPP_CONNECTIONS) #define MAX_NO_RFCOMM_MULTIPLEXERS MAX_SPP_CONNECTIONS #define MAX_NO_RFCOMM_SERVICES 1 #define MAX_NO_RFCOMM_CHANNELS MAX_SPP_CONNECTIONS #define MAX_NO_DB_MEM_DEVICE_NAMES 0 #define MAX_NO_DB_MEM_LINK_KEYS 3 #define MAX_NO_DB_MEM_SERVICES 1 \end{lstlisting} \subsection{Where to get data - packet handlers} \label{section:packetHandlers} After the hardware and BTstack are set up, the run loop is entered. From now on everything is event driven. The application calls BTstack functions, which in turn may send commands to the Bluetooth module. The resulting events are delivered back to the application. Instead of writing a single callback handler for each possible event (as it is done in some other Bluetooth stacks), BTstack groups events logically and provides them over a single generic interface. Appendix \ref{appendix:api_events_and_errors} summarizes the parameters and event codes of L2CAP and RFCOMM events, as well as possible errors and the corresponding error codes. Here is summarized list of packet handlers that an application might use: \begin{itemize} \item HCI packet handler - handles HCI and general BTstack events if L2CAP is not used (rare case). \item L2CAP packet handler - handles HCI and general BTstack events. \item L2CAP service packet handler - handles incoming L2CAP connections, i.e., channels initiated by the remote. \item L2CAP channel packet handler - handles outgoing L2CAP connections, i.e., channels initiated internally. \item RFCOMM packet handler - handles RFCOMM incoming/outgoing events and data. \end{itemize} \begin{table*}\centering \caption{Functions for registering packet handlers} \begin{tabular}{rl}\toprule Packet Handler & Registering Function\\ \midrule HCI packet handler & \emph{hci\_register\_packet\_handler}\\ L2CAP packet handler & \emph{l2cap\_register\_packet\_handler}\\ L2CAP service packet handler & \emph{l2cap\_register\_service\_internal}\\ L2CAP channel packet handler & \emph{l2cap\_create\_channel\_internal}\\ RFCOMM packet handler & \emph{rfcomm\_register\_packet\_handler}\\ \bottomrule \label{table:registeringFunction} \end{tabular} \end{table*} These handlers are registered with the functions listed in Table \ref{table:registeringFunction}. HCI and general BTstack events are delivered to the packet handler specified by \emph{l2cap\_register\_packet\_handler} function, or \emph{hci\_register\_packet\_handler}, if L2CAP is not used. In L2CAP, BTstack discriminates incoming and outgoing connections, i.e., event and data packets are delivered to different packet handlers. Outgoing connections are used access remote services, incoming connections are used to provide services. For incoming connections, the packet handler specified by \emph{l2cap\_register\_service} is used. For outgoing connections, the handler provided by \emph{l2cap\_create\_channel\_internal} is used. Currently, RFCOMM provides only a single packet handler specified by \emph{rfcomm\_register\_packet\_handler} for all RFCOMM connections, but this will be fixed in the next API overhaul. The application can register a single shared packet handler for all protocols and services, or use separate packet handlers for each protocol layer and service. A shared packet handler is often used for stack initialization and connection management. Separate packet handlers can be used for each L2CAP service and outgoing connection. For example, to connect with a Bluetooth HID keyboard, your application could use three packet handlers: one to handle HCI events during discovery of a keyboard registered by \emph{l2cap\_register\_packet\_handler}; one that will be registered to an outgoing L2CAP channel to connect to keyboard and to receive keyboard data registered by \emph{l2cap\_create\_channel\_internal}; after that keyboard can reconnect by itself. For this, you need to register L2CAP services for the HID Control and HID Interrupt PSMs using \emph{l2cap\_register\_service\_internal}. In this call, you'll also specify a packet handler to accept and receive keyboard data. \newcommand{\BluetoothSpecification}{\urlfoot{https://www.bluetooth.org/Technical/Specifications/adopted.htm}{Bluetooth Specification}} \newcommand{\BluetoothSpecificationURL}{\href{https://www.bluetooth.org/Technical/Specifications/adopted.htm}{\color{blue} Bluetooth Specification}} \input{protocols_profiles} \pagebreak \section{Examples} \label{section:examples} In this section, we will describe a number of examples from the \emph{example/embedded} folder. To allow code-reuse with different platforms as well as with new ports, the low-level initialization of BTstack and the hardware configuration has been extracted to the various \emph{platforms/PLATFORM/main.c} files. The examples only contain the platform-independent Bluetooth logic. But let's have a look at the common init code. Listing \ref{listing:btstackInit} shows a minimal platform setup for an embedded system with a Bluetooth chipset connected via UART. \begin{lstlisting}[float, caption=Exemplary platform init in main.c, label=listing:btstackInit] int main(){ // ... hardware init: watchdoch, IOs, timers, etc... // setup BTstack memory pools btstack_memory_init(); // select embedded run loop run_loop_init(RUN_LOOP_EMBEDDED); // use logger: format HCI_DUMP_PACKETLOGGER, HCI_DUMP_BLUEZ or HCI_DUMP_STDOUT hci_dump_open(NULL, HCI_DUMP_STDOUT); // init HCI hci_transport_t * transport = hci_transport_h4_dma_instance(); remote_device_db_t * remote_db = (remote_device_db_t *) &remote_device_db_memory; hci_init(transport, NULL, NULL, remote_db); // setup example btstack_main(argc, argv); // go run_loop_execute(); } \end{lstlisting} First, BTstack's memory pools are setup up. Then, the standard run loop implementation for embedded systems is selected. The call to \emph{hci\_dump\_open} configures BTstack to output all Bluetooth packets and it's own debug and error message via printf. The Python script \emph{tools/create\_packet\_log.py} can be used to convert the console output into a Bluetooth PacketLogger format that can be opened by the OS X PacketLogger tool as well as by Wireshark for further inspection. When asking for help, please always include a log created with HCI dump. The \emph{hci\_init} function sets up HCI to use the HCI H4 Transport implementation. It doesn't provide a special transport configuration nor a special implementation for a particular Bluetooth chipset. It makes use of the \emph{remote\_device\_db\_memory} implementation that allows for re-connects without a new pairing but doesn't persist the bonding information. Finally, it calls \emph{btstack\_main()} of the actual example before executing the run loop. The examples are grouped like this: \input{examples} % \section{Platforms} \section{Porting to Other Platforms} In this chapter, we highlight the BTstack components that need to be adjusted for different hardware platforms. \subsection{Time Abstraction Layer} \label{section:timeAbstraction} BTstack requires a way to learn about passing time. \emph{run\_loop\_embedded.c} supports two different modes: system ticks or a system clock with millisecond resolution. BTstack's timing requirements are quite low as only Bluetooth timeouts in the second range need to be handled. \subsubsection{Tick Hardware Abstraction} \label{section:tickAbstraction} If your platform doesn't require a system clock or if you already have a system tick (as it is the default with CMSIS on ARM Cortex devices), you can use that to implement BTstack's time abstraction in \emph{include/btstack/hal\_tick.h>}. For this, you need to define \emph{HAVE\_TICK} in \emph{btstack-config.h}: \begin{lstlisting} #define HAVE_TICK \end{lstlisting} Then, you need to implement the functions \emph{hal\_tick\_init} and \emph{hal\_tick\_set\_handler}, which will be called during the initialization of the run loop. \begin{lstlisting} void hal_tick_init(void); void hal_tick_set_handler(void (*tick_handler)(void)); int hal_tick_get_tick_period_in_ms(void); \end{lstlisting} After BTstack calls \emph{hal\_tick\_init()} and \emph{hal\_tick\_set\_handler(tick\_handler)}, it expects that the \emph{tick\_handler} gets called every \emph{hal\_tick\_get\_tick\_period\_in\_ms()} ms. \subsubsection{Time MS Hardware Abstraction} \label{section:timeMSAbstraction} If your platform already has a system clock or it is more convenient to provide such a clock, you can use the Time MS Hardware Abstraction in \emph{include/btstack/hal\_time\_ms.h}. For this, you need to define \emph{HAVE\_TIME\_MS} in \emph{btstack-config.h}: \begin{lstlisting} #define HAVE_TIME_MS \end{lstlisting} Then, you need to implement the function \emph{hal\_time\_ms()}, which will be called from BTstack's run loop and when setting a timer for the future. It has to return the time in milliseconds. \begin{lstlisting} uint32_t hal_time_ms(void); \end{lstlisting} \subsection{Bluetooth Hardware Control API} \label{section:bt_hw_control} The Bluetooth hardware control API can provide the HCI layer with a custom initialization script, a vendor-specific baud rate change command, and system power notifications. It is also used to control the power mode of the Bluetooth module, i.e., turning it on/off and putting to sleep. In addition, it provides an error handler \emph{hw\_error} that is called when a Hardware Error is reported by the Bluetooth module. The callback allows for persistent logging or signaling of this failure. \todo{add recipe} Overall, the struct \emph{bt\_control\_t} encapsulates common functionality that is not covered by the Bluetooth specification. As an example, the \emph{bt\_control\_cc256x\_in-stance} function returns a pointer to a control struct suitable for the CC256x chipset. \subsection{HCI Transport Implementation} \label{section:hci_transport} On embedded systems, a Bluetooth module can be connected via USB or an UART port. BTstack implements two UART based protocols for carrying HCI commands, events and data between a host and a Bluetooth module: HCI UART Transport Layer (H4) and H4 with eHCILL support, a lightweight low-power variant by Texas Instruments. \subsubsection{HCI UART Transport Layer (H4)} \label{section:hciUART} Most embedded UART interfaces operate on the byte level and generate a processor interrupt when a byte was received. In the interrupt handler, common UART drivers then place the received data in a ring buffer and set a flag for further processing or notify the higher-level code, i.e., in our case the Bluetooth stack. Bluetooth communication is packet-based and a single packet may contain up to 1021 bytes. Calling a data received handler of the Bluetooth stack for every byte creates an unnecessary overhead. To avoid that, a Bluetooth packet can be read as multiple blocks where the amount of bytes to read is known in advance. Even better would be the use of on-chip DMA modules for these block reads, if available. %During the BTstack will request up to three reads: first to get the packet type, second to get ACL or Event header, and last one to read the payload. The BTstack UART Hardware Abstraction Layer API reflects this design approach and the underlying UART driver has to implement the following API: \begin{lstlisting} void hal_uart_dma_init(void); void hal_uart_dma_set_block_received(void (*block_handler)(void)); void hal_uart_dma_set_block_sent(void (*block_handler)(void)); int hal_uart_dma_set_baud(uint32_t baud); void hal_uart_dma_send_block(const uint8_t *buffer, uint16_t len); void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t len); \end{lstlisting} The main HCI H4 implementations for embedded system is \emph{hci\_h4\_transport-\_dma} function. This function calls the following sequence: \emph{hal\_uart\_dma\_init}, \emph{hal\_uart\_dma\_set\_block\_received} and \emph{hal\_uart\_dma\_set\_block\_sent} functions. \mbox{After} this sequence, the HCI layer will start packet processing by calling \emph{hal\_uart-\_dma\_receive\_block} function. The HAL implementation is responsible for reading the requested amount of bytes, stopping incoming data via the RTS line when the requested amount of data was received and has to call the handler. By this, the HAL implementation can stay generic, while requiring only three callbacks per HCI packet. \subsubsection{H4 with eHCILL support} With the standard H4 protocol interface, it is not possible for either the host nor the baseband controller to enter a sleep mode. Besides the official H5 protocol, various chip vendors came up with proprietary solutions to this. The eHCILL support by Texas Instruments allows both the host and the baseband controller to independently enter sleep mode without loosing their synchronization with the HCI H4 Transport Layer. In addition to the IRQ-driven block-wise RX and TX, eHCILL requires a callback for CTS interrupts. \begin{lstlisting} void hal_uart_dma_set_cts_irq_handler(void(*cts_irq_handler)(void)); void hal_uart_dma_set_sleep(uint8_t sleep); \end{lstlisting} \subsection{Persistent Storage API} \label{section:persistent_storage} On embedded systems there is no generic way to persist data like link keys or remote device names, as every type of a device has its own capabilities, particularities and limitations. The persistent storage API provides an interface to implement concrete drivers for a particular system. As an example and for testing purposes, BTstack provides the memory-only implementation \emph{remote\_device\_db\_memory}. An implementation has to conform to the interface in Listing \ref{persistentDB}. \\ \begin{lstlisting}[float, caption=Persistent Storage Interface., label=persistentDB] typedef struct { // management void (*open)(); void (*close)(); // link key int (*get_link_key)(bd_addr_t bd_addr, link_key_t link_key); void (*put_link_key)(bd_addr_t bd_addr, link_key_t key); void (*delete_link_key)(bd_addr_t bd_addr); // remote name int (*get_name)(bd_addr_t bd_addr, device_name_t *device_name); void(*put_name)(bd_addr_t bd_addr, device_name_t *device_name); void(*delete_name)(bd_addr_t bd_addr); } remote_device_db_t; \end{lstlisting} \section{Integrating with Existing Systems} While the run loop provided by BTstack is sufficient for new designs, BTstack is often used with or added to existing projects. In this case, the run loop, data sources, and timers may need to be adapted. The following two sections provides a guideline for single and multi-threaded environments. To simplify the discussion, we'll consider an application split into "Main \mbox{Application}", "Communication Logic", and "BTstack". The Communication Logic contains the packet handler (PH) that handles all asynchronous events and data packets from BTstack. The Main Application makes use of the Communication Logic for its Bluetooth communication. \subsection{Adapting BTstack for Single-Threaded Environments} \label{section:singlethreading} In a single-threaded environment, all application components run on the same (single) thread and use direct function calls as shown in Figure \ref{fig:BTstackSingle}. \begin{figure}[htbp] % figure placement: here, top, bottom, or page \centering \includegraphics[width=0.3\textwidth]{picts/singlethreading-btstack.pdf} \caption{BTstack in single-threaded environment. } \label{fig:BTstackSingle} \end{figure} BTstack provides a basic run loop that supports the concept of data sources and timers, which can be registered centrally. This works well when working with a small MCU and without an operating system. To adapt to a basic operating system or a different scheduler, BTstack's run loop can be implemented based on the functions and mechanism of the existing system. Currently, we have two examples for this: \begin{itemize} \item \emph{run\_loop\_cocoa.c} is an implementation for the CoreFoundation Framework used in OS X and iOS. All run loop functions are implemented in terms of CoreFoundation calls, data sources and timers are modeled as CFSockets and CFRunLoopTimer respectively. \item \emph{run\_loop\_posix.c} is an implementation for POSIX compliant systems. The data sources are modeled as file descriptors and managed in a linked list. Then, the\emph{select} function is used to wait for the next file descriptor to become ready or timer to expire. \end{itemize} \subsection{Adapting BTstack for Multi-Threaded Environments} \label{section:multithreading} The basic execution model of BTstack is a general while loop. Aside from interrupt-driven UART and timers, everything happens in sequence. When using BTstack in a multi-threaded environment, this assumption has to stay valid - at least with respect to BTstack. For this, there are two common options: \begin{figure}[ht] \begin{minipage}[b]{\linewidth} \centering \includegraphics[width=0.8\textwidth]{picts/multithreading-monolithic.pdf} \caption{BTstack in multi-threaded environment - monolithic solution.} \label{fig:BTstackMonolithic} \vspace{0.8cm} \end{minipage} \begin{minipage}[b]{\linewidth} \centering \includegraphics[width=0.8\textwidth]{picts/multithreading-btdaemon.pdf} \caption{BTstack in multi-threaded environment - solution with daemon.} \label{fig:BTstackDaemon} \end{minipage} \end{figure} \begin{itemize} \item The Communication Logic is implemented on a dedicated BTstack thread, and the Main Application communicates with the BTstack thread via application-specific messages over an Interprocess Communication (IPC) as depicted in Figure \ref{fig:BTstackMonolithic}. This option results in less code and quick adaption. \item BTstack must be extended to run standalone, i.e, as a Daemon, on a dedicated thread and the Main Application controls this daemon via BTstack extended HCI command over IPC - this is used for the non-embedded version of BTstack e.g., on the iPhone and it is depicted in Figure \ref{fig:BTstackDaemon}. This option requires more code but provides more flexibility. \end{itemize} \pagebreak \appendix \input{appendix_apis} \input{api_events_and_errors} \pagebreak \section{Revision History} \label{appendix:revision_history} \begin{table}[!htbp] \begin{tabular*}{\textwidth}{lp{3.5cm}p{8.5cm}}\toprule Rev & Date & Comments\\ \midrule 1.x & April 3, 2015 & Added Time MS Hardware Abstraction.\\ 1.3 & November 6, 2014 & Introducing GATT client and server. Work in progress.\\ 1.2 & November 1, 2013 & Explained Secure Simple Pairing in "Pairing of devices".\\ 1.1 & August 30, 2013 & Introduced SDP client. Updated Quick Recipe on "Query remote SDP service".\\ \bottomrule \end{tabular*} \end{table} %\section {TODO} % %\section {Maybe Missing} %\begin{itemize} %\item profiles in BTstack (SPP) %\item More examples: HID mouse host, HID mouse device, HID keyboard device, BLE Client, .. %\end{itemize} % % \bibliographystyle{IEEEtran} % \bibliography{btstack-manual} % \section*{Bibliography} %\textbf{P. W. Wachulak} received the degree${\ldots}$ \\[6pt] %\textbf{M. C. Marconi} received the degree${\ldots}$ \\[6pt] %\textbf{R. A. Bartels} received the degree${\ldots}$ \\[6pt] %\textbf{C. S. Menoni} received the degree${\ldots}$ \\[6pt] %\textbf{J. J. Rocca} received the degree${\ldots}$ \end{document}