mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-29 22:20:37 +00:00
manual: corrected references
This commit is contained in:
parent
033f903fdd
commit
efaacf2645
@ -1,15 +1,20 @@
|
||||
all:
|
||||
./update_apis.py
|
||||
./update_listings.py
|
||||
rm -rf docs_tmp
|
||||
rm -rf docs_final
|
||||
cp -r docs docs_tmp
|
||||
cp -r docs docs_final
|
||||
./markdown2mkdocs.py
|
||||
rm -rf docs_tmp
|
||||
mkdocs build --clean
|
||||
echo "a.toctree-l4 { display: none; }" >> btstack/css/theme_extra.css
|
||||
mkdir -p latex
|
||||
cp -r docs/picts latex
|
||||
cp ../picts/bklogo.pdf latex/picts
|
||||
./markdown2pdf.py
|
||||
cp btstack_gettingstarted.tex latex
|
||||
cd latex && pdflatex btstack_gettingstarted.tex && pdflatex btstack_gettingstarted.tex
|
||||
mv latex/btstack_gettingstarted.pdf btstack
|
||||
mv latex/btstack_gettingstarted.pdf btstack.pdf
|
||||
rm -rf latex
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
\documentclass[a4paper,titlepage,oneside,12pt]{amsart} %amsart
|
||||
\usepackage{graphicx}
|
||||
\usepackage{hyperref}
|
||||
\usepackage[colorlinks=true]{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
|
||||
@ -147,6 +147,9 @@ morekeywords={*, timer_source_t, data_source_t, uint32_t, uint16_t, uint8_t, RUN
|
||||
\begin{document}
|
||||
|
||||
\maketitle
|
||||
\hypersetup{linkcolor=blue}
|
||||
\hypersetup{urlcolor=blue}
|
||||
\hypersetup{citecolor=blue}
|
||||
|
||||
\tableofcontents
|
||||
\pagebreak
|
||||
|
@ -1,6 +1,5 @@
|
||||
|
||||
## L2CAP Events
|
||||
<a name="appendix:events_and_errors"></a>
|
||||
## L2CAP Events {#sec:eventsAndErrorsAppendix}
|
||||
|
||||
L2CAP events and data packets are delivered to the packet handler
|
||||
specified by *l2cap_register_service* resp.
|
||||
|
@ -42,7 +42,7 @@ 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 check [here](integration/#adapting-btstack-for-multi-threaded-environments).
|
||||
For adapting BTstack to multi-threaded environments check [here](integration/#sec:multithreadingIntegration).
|
||||
|
||||
## No blocking anywhere
|
||||
|
||||
|
@ -12,9 +12,7 @@ an overview is provided here. Finally, we describe the RFCOMM
|
||||
credit-based flow-control, which may be necessary for
|
||||
resource-constraint devices.
|
||||
|
||||
<a name ="section:memory_configuration"></a>
|
||||
|
||||
## Memory configuration
|
||||
## Memory configuration {#sec:memoryConfigurationHowTo}
|
||||
|
||||
The structs for services, active connections and remote devices can be
|
||||
allocated in two different manners:
|
||||
@ -53,9 +51,8 @@ The memory is set up by calling *btstack_memory_init* function:
|
||||
|
||||
btstack_memory_init();
|
||||
|
||||
<a name"section:run_loop"></a>
|
||||
|
||||
## Run loop
|
||||
## Run loop {#sec:runLoopHowTo}
|
||||
|
||||
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
|
||||
@ -91,7 +88,8 @@ 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 [PeriodicTimerHandler]. Note that BTstack
|
||||
expects to get called periodically to keep its time, see Section
|
||||
[on time abstraction](#section:test) for more on the tick hardware abstraction.
|
||||
[on time abstraction](#sec:timeAbstractionPorting) for more on the
|
||||
tick hardware abstraction.
|
||||
|
||||
The run loop is set up by calling *run_loop_init* function for
|
||||
embedded systems:
|
||||
@ -100,7 +98,7 @@ embedded systems:
|
||||
|
||||
run_loop_init(RUN_LOOP_EMBEDDED);
|
||||
|
||||
The Run loop API is provided [here](appendix/apis/#appendix:api_run_loop). To
|
||||
The Run loop API is provided [here](appendix/apis/#sec:runLoopAPIAppendix). To
|
||||
enable the use of timers, make sure that you defined HAVE_TICK in the
|
||||
config file.
|
||||
|
||||
@ -109,12 +107,11 @@ as shown in Listing [listing:btstackInit]. The application can register
|
||||
data sources as well as timers, e.g., periodical sampling of sensors, or
|
||||
communication over the UART.
|
||||
|
||||
<a nam="sec:btstack_initialization"></a>
|
||||
|
||||
## BTstack initialization {#section:test}
|
||||
## BTstack initialization {#sec:btstackInitializationHowTo}
|
||||
|
||||
To initialize BTstack you need to [initialize the memory](#section:memory_configuration)
|
||||
and [the run loop](#section:run_loop) respectively, then setup HCI and all needed higher
|
||||
To initialize BTstack you need to [initialize the memory](#sec:memoryConfigurationHowTo)
|
||||
and [the run loop](#sec:runLoopHowTo) respectively, then setup HCI and all needed higher
|
||||
level protocols.
|
||||
|
||||
The HCI initialization has to adapt BTstack to the used platform and
|
||||
@ -146,7 +143,7 @@ requires four arguments. These are:
|
||||
[src/hci_transport_h4_dma.c]() resp. [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 [here](porting/#hci-transport-implementation).
|
||||
environments, see [here](porting/#sec:hciTransportPorting).
|
||||
|
||||
<!-- -->
|
||||
|
||||
@ -173,7 +170,7 @@ requires four arguments. These are:
|
||||
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 [here](porting/#persistent-storage-api).
|
||||
For more see [here](porting/#sec:persistentStoragePorting).
|
||||
|
||||
<!-- -->
|
||||
|
||||
@ -190,9 +187,8 @@ themselves with the underlying layer. In addition, the application can
|
||||
register packet handlers to get events and data as explained in the
|
||||
following section.
|
||||
|
||||
<a name="sec:services"></a>
|
||||
|
||||
## Services
|
||||
## Services {#sec:servicesHowTo}
|
||||
|
||||
One important construct of BTstack is *service*. A service represents a
|
||||
server side component that handles incoming connections. So far, BTstack
|
||||
@ -204,9 +200,8 @@ ID. Outgoing connections require no special registration, they are
|
||||
created by the application when needed.
|
||||
|
||||
|
||||
<a name="sec:packetHandlers"></a>
|
||||
|
||||
## Where to get data - packet handlers
|
||||
## Where to get data - packet handlers {#sec:packetHandlersHowTo}
|
||||
|
||||
|
||||
After the hardware and BTstack are set up, the run loop is entered. From
|
||||
@ -216,7 +211,7 @@ 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
|
||||
[Events and Errors](generated/appendix/#events_and_errors)
|
||||
[Events and Errors](generated/appendix/#sec:eventsAndErrorsAppendix)
|
||||
summarizes the parameters and event
|
||||
codes of L2CAP and RFCOMM events, as well as possible errors and the
|
||||
corresponding error codes.
|
||||
@ -282,9 +277,8 @@ services for the HID Control and HID Interrupt PSMs using
|
||||
a packet handler to accept and receive keyboard data.
|
||||
|
||||
|
||||
<a name="sec:packetlogs"></a>
|
||||
|
||||
## Bluetooth HCI Packet Logs
|
||||
## Bluetooth HCI Packet Logs {#sec:packetlogsHowTo}
|
||||
|
||||
|
||||
If things don't work as expected, having a look at the data exchanged
|
||||
|
@ -8,5 +8,6 @@ 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 changes in the documentation are listed in the [Revision History](revision_history).
|
||||
Finally, we outline the basic steps when integrating BTstack into existing
|
||||
single-threaded or even multi-threaded environments.
|
||||
|
||||
|
@ -11,9 +11,8 @@ 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.
|
||||
|
||||
<a name="sec:singlethreading"></a>
|
||||
|
||||
## Adapting BTstack for Single-Threaded Environments
|
||||
## Adapting BTstack for Single-Threaded Environments {#sec:singlethreadingIntegration}
|
||||
|
||||
|
||||
In a single-threaded environment, all application components run on the
|
||||
@ -41,9 +40,8 @@ Currently, we have two examples for this:
|
||||
managed in a linked list. Then, the*select* function is used to wait
|
||||
for the next file descriptor to become ready or timer to expire.
|
||||
|
||||
<a name="sec:multithreading"></a>
|
||||
|
||||
## Adapting BTstack for Multi-Threaded Environments
|
||||
## Adapting BTstack for Multi-Threaded Environments {#sec:multithreadingIntegration}
|
||||
|
||||
|
||||
The basic execution model of BTstack is a general while loop. Aside from
|
||||
|
@ -1,9 +1,8 @@
|
||||
In this section, we highlight the BTstack components that need to be
|
||||
adjusted for different hardware platforms.
|
||||
|
||||
<a name="section:timeAbstraction"></a>
|
||||
|
||||
## Time Abstraction Layer
|
||||
## Time Abstraction Layer {#sec:timeAbstractionPorting}
|
||||
|
||||
BTstack requires a way to learn about passing time.
|
||||
*run_loop_embedded.c* supports two different modes: system ticks or a
|
||||
@ -12,7 +11,7 @@ are quite low as only Bluetooth timeouts in the second range need to be
|
||||
handled.
|
||||
|
||||
|
||||
### Tick Hardware Abstraction ### {#section:tickAbstraction}
|
||||
### Tick Hardware Abstraction {#sec:tickAbstractionPorting}
|
||||
|
||||
|
||||
If your platform doesn’t require a system clock or if you already have a
|
||||
@ -37,9 +36,8 @@ After BTstack calls *hal_tick_init()* and
|
||||
*tick_handler* gets called every
|
||||
*hal_tick_get_tick_period_in_ms()* ms.
|
||||
|
||||
<a name="sec:timeMSAbstraction"></a>
|
||||
|
||||
### Time MS Hardware Abstraction
|
||||
### Time MS Hardware Abstraction {#sec:timeMSAbstractionPorting}
|
||||
|
||||
|
||||
If your platform already has a system clock or it is more convenient to
|
||||
@ -57,9 +55,7 @@ future. It has to return the time in milliseconds.
|
||||
uint32_t hal_time_ms(void);
|
||||
|
||||
|
||||
<a name="sec:bt_hw_control"></a>
|
||||
|
||||
## Bluetooth Hardware Control API
|
||||
## Bluetooth Hardware Control API {#sec:btHWControlPorting}
|
||||
|
||||
|
||||
The Bluetooth hardware control API can provide the HCI layer with a
|
||||
@ -76,9 +72,8 @@ that is not covered by the Bluetooth specification. As an example, the
|
||||
struct suitable for the CC256x chipset.
|
||||
|
||||
|
||||
<a name="sec:hci_transport"></a>
|
||||
|
||||
## HCI Transport Implementation
|
||||
## HCI Transport Implementation {#sec:hciTransportPorting}
|
||||
|
||||
|
||||
On embedded systems, a Bluetooth module can be connected via USB or an
|
||||
@ -87,9 +82,8 @@ 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.
|
||||
|
||||
<a name="sec:hciUART"></a>
|
||||
|
||||
### HCI UART Transport Layer (H4)
|
||||
### HCI UART Transport Layer (H4) {#sec:hciUARTPorting}
|
||||
|
||||
|
||||
Most embedded UART interfaces operate on the byte level and generate a
|
||||
@ -142,9 +136,8 @@ callback for CTS interrupts.
|
||||
void hal_uart_dma_set_cts_irq_handler(void(*cts_irq_handler)(void));
|
||||
void hal_uart_dma_set_sleep(uint8_t sleep);
|
||||
|
||||
<a name="sec:persistent_storage"></a>
|
||||
|
||||
## Persistent Storage API
|
||||
## Persistent Storage API {#sec:persistentStoragePorting}
|
||||
|
||||
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
|
||||
|
@ -43,10 +43,15 @@ undiscoverable again, once a connection is established. See Listing
|
||||
### Discover remote devices {#section:DiscoverRemoteDevices}
|
||||
|
||||
To scan for remote devices, the *hci_inquiry* command is used. Found
|
||||
remote devices are reported as a part of HCI_EVENT_INQUIRY_RESULT,
|
||||
HCI_EVENT-_INQUIRY_RESULT_WITH_RSSI, or
|
||||
HCI_EVENT_EXTENDED_INQUIRY_RESPONSE events. Each response contains
|
||||
at least the Bluetooth address, the class of device, the page scan
|
||||
remote devices are reported as a part of:
|
||||
|
||||
- HCI_EVENT_INQUIRY_RESULT,
|
||||
|
||||
- HCI_EVENT-_INQUIRY_RESULT_WITH_RSSI, or
|
||||
|
||||
- HCI_EVENT_EXTENDED_INQUIRY_RESPONSE events.
|
||||
|
||||
Each response contains at least the Bluetooth address, the class of device, the page scan
|
||||
repetition mode, and the clock offset of found device. The latter events
|
||||
add information about the received signal strength or provide the
|
||||
Extended Inquiry Result (EIR). A code snippet is shown in Listing
|
||||
@ -104,7 +109,7 @@ device implements Bluetooth Specification 2.1 or higher, the
|
||||
*hci_write_inquiry_mode* command enables reporting of this advanced
|
||||
features (0 for standard results, 1 for RSSI, 2 for RSSI and EIR).
|
||||
|
||||
A complete GAP inquiry example is provided [here](examples/#gapinquiry).
|
||||
A complete GAP inquiry example is provided [here](examples/generated/#sec:gapinquiryExample).
|
||||
|
||||
### Pairing of Devices
|
||||
|
||||
@ -150,8 +155,8 @@ user.
|
||||
|
||||
Regardless of the authentication mechanism (PIN/SSP), on success, both
|
||||
devices will generate a link key. The link key can be stored either in
|
||||
the Bluetooth module itself or in a persistent storage, see [here](#examples/#persistent_storage).
|
||||
The next time the device connects and
|
||||
the Bluetooth module itself or in a persistent storage, see
|
||||
[here](porting/#sec:persistentStoragePorting). The next time the device connects and
|
||||
requests an authenticated connection, both devices can use the
|
||||
previously generated link key. Please note that the pairing must be
|
||||
repeated if the link key is lost by one device.
|
||||
@ -177,22 +182,21 @@ for its SPP services. Section [subsection:querysdp] shows how to query
|
||||
for all RFCOMM channels. For SPP, you can do the same but use the SPP
|
||||
UUID 0x1101 for the query. After you have identified the correct RFCOMM
|
||||
channel, you can create an RFCOMM connection as shown
|
||||
[here](protocols/#sec:rfcommlient).
|
||||
[here](protocols/#sec:rfcommClientProtocols).
|
||||
|
||||
### Providing an SPP Server
|
||||
|
||||
To provide an SPP Server, you need to provide an RFCOMM service with a
|
||||
specific RFCOMM channel number as explained in section on
|
||||
[RFCOMM service](protocols/#sec:rfcomm_service). Then, you need to create
|
||||
[RFCOMM service](protocols/#sec:rfcommServiceProtocols). Then, you need to create
|
||||
an SDP record for it and publish it with the SDP server by calling
|
||||
*sdp_register_service_internal*. BTstack provides the
|
||||
*sdp_create_spp_service* function in that requires an empty buffer of
|
||||
approximately 200 bytes, the service channel number, and a service name.
|
||||
Have a look at the [SPP Counter example](examples/generated/#section:sppcounter].
|
||||
Have a look at the [SPP Counter example](examples/generated/#sec:sppcounterExample].
|
||||
|
||||
<a name="section:pan_profile"></a>
|
||||
|
||||
## PAN - Personal Area Networking Profile
|
||||
## PAN - Personal Area Networking Profile {#sec:panProfiles}
|
||||
|
||||
|
||||
The PAN profile uses BNEP to provide on-demand networking capabilities
|
||||
@ -234,7 +238,7 @@ information, you can connect BNEP to the remote PANU service with the
|
||||
|
||||
To provide a PANU service, you need to provide a BNEP service with the
|
||||
service UUID, e.g. the PANU UUID, and a a maximal ethernet frame size,
|
||||
as explained in Section [subsubsection:bnepserver]. Then, you need to
|
||||
as explained in Section [on BNEP service](protocols/#sec:bnepServiceProtocols). Then, you need to
|
||||
create an SDP record for it and publish it with the SDP server by
|
||||
calling *sdp_register_service_internal*. BTstack provides the
|
||||
*pan_create_panu_service* function in *src/pan.c* that requires an
|
||||
@ -266,8 +270,8 @@ To toggle privacy mode using private addresses, call the
|
||||
with *gap_random_address_set_update_period*.
|
||||
|
||||
After a connection is established, the Security Manager will try to
|
||||
resolve the peer Bluetooth address as explained in Section
|
||||
[section:smp].
|
||||
resolve the peer Bluetooth address as explained in Section on
|
||||
[SMP](protocols/#sec:smpProtocols).
|
||||
|
||||
### Advertising and Discovery
|
||||
|
||||
@ -283,8 +287,8 @@ commands can be used:
|
||||
- *hci_le_set_advertise_enable*
|
||||
|
||||
As these are direct HCI commands, please refer to Section
|
||||
[subsubsection:sendinghci] for details and have a look at the SPP and LE
|
||||
Counter example in Section [example:sppandlecounter].
|
||||
[subsubsection:sendinghci] for details and have a look at the [SPP and LE
|
||||
Counter example](examples/generated/#sec:sppandlecounterExample).
|
||||
|
||||
In addition to the Advertisement data, a device in the peripheral role
|
||||
can also provide Scan Response data, which has to be explicitly queried
|
||||
@ -317,9 +321,8 @@ Services are queried and modified via ATT operations.
|
||||
GATT defines both a server and a client role. A device can implement one
|
||||
or both GATT roles.
|
||||
|
||||
<a name = "section:GATTClient"></a>
|
||||
|
||||
### GATT Client
|
||||
### GATT Client {#sec:GATTClientProfiles}
|
||||
|
||||
The GATT Client is used to discover services, and their characteristics
|
||||
and descriptors on a peer device. It can also subscribe for
|
||||
@ -347,11 +350,10 @@ perform a GATT query on a particular connection using
|
||||
completes the query.
|
||||
|
||||
For more details on the available GATT queries, please consult
|
||||
[GATT Client API](#appendix:api_gatt_client).
|
||||
[GATT Client API](#sec:gattClientAPIAppendix).
|
||||
|
||||
<a name="section:GATTServer"></a>
|
||||
|
||||
### GATT Server
|
||||
### GATT Server {#sec:GATTServerProfiles}
|
||||
|
||||
The GATT server stores data and accepts GATT client requests, commands
|
||||
and confirmations. The GATT server sends responses to requests and when
|
||||
|
@ -137,8 +137,8 @@ and info on their parameters.
|
||||
S Service Record (Data Element Sequence)
|
||||
------------------- ----------------------------------------------------
|
||||
|
||||
### Sending HCI command based on a template
|
||||
<a name ="sec:sendinghci"></a>
|
||||
|
||||
### Sending HCI command based on a template {#sec:sendingHCIProtocols}
|
||||
|
||||
You can use the *hci_send_cmd* function to send HCI command based on a
|
||||
template and a list of parameters. However, it is necessary to check
|
||||
@ -163,8 +163,9 @@ Please note, that an application rarely has to send HCI commands on its
|
||||
own. Instead, BTstack provides convenience functions in GAP and higher
|
||||
level protocols use HCI automatically.
|
||||
|
||||
L2CAP - Logical Link Control and Adaptation Protocol
|
||||
----------------------------------------------------
|
||||
|
||||
## L2CAP - Logical Link Control and Adaptation Protocol
|
||||
|
||||
|
||||
The L2CAP protocol supports higher level protocol multiplexing and
|
||||
packet fragmentation. It provides the base for the RFCOMM and BNEP
|
||||
@ -185,7 +186,7 @@ To communicate with an L2CAP service on a remote device, the application
|
||||
on a local Bluetooth device initiates the L2CAP layer using the
|
||||
*l2cap_init* function, and then creates an outgoing L2CAP channel to
|
||||
the PSM of a remote device using the *l2cap_create_channel_internal*
|
||||
function. The *l2cap_-create_channel_internal* function will initiate
|
||||
function. The *l2cap_create_channel_internal* function will initiate
|
||||
a new baseband connection if it does not already exist. The packet
|
||||
handler that is given as an input parameter of the L2CAP create channel
|
||||
function will be assigned to the new outgoing L2CAP channel. This
|
||||
@ -298,8 +299,8 @@ BTstack provides an optimized *l2cap_le* implementation in the *ble*
|
||||
folder. This L2CAP LE variant can be used for single-mode devices and
|
||||
provides the base for the ATT and SMP protocols.
|
||||
|
||||
RFCOMM - Radio Frequency Communication Protocol
|
||||
-----------------------------------------------
|
||||
|
||||
## RFCOMM - Radio Frequency Communication Protocol
|
||||
|
||||
The Radio frequency communication (RFCOMM) protocol provides emulation
|
||||
of serial ports over the L2CAP protocol. and reassembly. It is the base
|
||||
@ -307,8 +308,8 @@ for the Serial Port Profile and other profiles used for
|
||||
telecommunication like Head-Set Profile, Hands-Free Profile, Object
|
||||
Exchange (OBEX) etc.
|
||||
|
||||
### RFCOMM flow control.
|
||||
<a name="sec:flowcontrol"></a>
|
||||
|
||||
### RFCOMM flow control {#sec:flowControlProtocols}
|
||||
|
||||
RFCOMM has a mandatory credit-based flow-control. This means that two
|
||||
devices that established RFCOMM connection, use credits to keep track of
|
||||
@ -326,24 +327,24 @@ is not much data transmitted and/or only one physical connection is
|
||||
used. If the management of credits is manual, credits are provided by
|
||||
the application such that it can manage its receive buffers explicitly.
|
||||
|
||||
### Access an RFCOMM service on a remote device
|
||||
<a name="sec:rfcommlient"></a>
|
||||
|
||||
### Access an RFCOMM service on a remote device {#sec:rfcommClientProtocols}
|
||||
|
||||
To communicate with an RFCOMM service on a remote device, the
|
||||
application on a local Bluetooth device initiates the RFCOMM layer using
|
||||
the *rfcomm_init* function, and then creates an outgoing RFCOMM channel
|
||||
to a given server channel on a remote device using the
|
||||
*rfcomm_create_channel_internal* function. The
|
||||
*rfcomm_create_channel_intern-al* function will initiate a new L2CAP
|
||||
*rfcomm_create_channel_internal* function will initiate a new L2CAP
|
||||
connection for the RFCOMM multiplexer, if it does not already exist. The
|
||||
channel will automatically provide enough credits to the remote side. To
|
||||
provide credits manually, you have to create the RFCOMM connection by
|
||||
calling *rfcomm_create_channel_with_initial_credits_internal* -
|
||||
see Section [on manual credit assignement](#sec:manualCredits).
|
||||
see Section [on manual credit assignement](#sec:manualCreditsProtocols).
|
||||
|
||||
The packet handler that is given as an input parameter of the RFCOMM
|
||||
create channel function will be assigned to the new outgoing channel.
|
||||
This handler receives the RFCOMM_EVENT_OPEN_CHAN-NEL_COMPLETE and
|
||||
This handler receives the RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE and
|
||||
RFCOMM_EVENT_CHANNEL_CLOSED events, and RFCOMM data packets, as shown in
|
||||
Listing [below](#lst:RFCOMMremoteService).
|
||||
|
||||
@ -376,8 +377,7 @@ Listing [below](#lst:RFCOMMremoteService).
|
||||
}
|
||||
|
||||
|
||||
### Provide an RFCOMM service
|
||||
<a name="sec:rfcomm_service"></a>
|
||||
### Provide an RFCOMM service {#sec:rfcommServiceProtocols}
|
||||
|
||||
To provide an RFCOMM service, the application on a local Bluetooth
|
||||
device must first init the L2CAP and RFCOMM layers and then register the
|
||||
@ -449,8 +449,9 @@ provides the RFCOMM service example code.
|
||||
}
|
||||
}
|
||||
|
||||
### Living with a single output buffer
|
||||
<a name="sec:single_buffer"></a>
|
||||
|
||||
### Living with a single output buffer {#sec:singleBufferProtocols}
|
||||
|
||||
Outgoing packets, both commands and data, are not queued in BTstack.
|
||||
This section explains the consequences of this design decision for
|
||||
sending data and why it is not as bad as it sounds.
|
||||
@ -533,7 +534,7 @@ Listing [below](#lst:SingleOutputBufferTryPH).
|
||||
|
||||
If the management of credits is manual, credits are provided by the
|
||||
application such that it can manage its receive buffers explicitly, see
|
||||
Listing [below].
|
||||
Listing [below](#lst:explicitFlowControl).
|
||||
|
||||
<a name "lst:explicitFlowControl"></a>
|
||||
<!-- -->
|
||||
@ -549,7 +550,7 @@ Listing [below].
|
||||
|
||||
|
||||
Manual credit management is recommended when received RFCOMM data cannot
|
||||
be processed immediately. In the [SPP flow control example](examples/#sec:sppflowcontrol),
|
||||
be processed immediately. In the [SPP flow control example](examples/generated/#sec:sppflowcontrolExample),
|
||||
delayed processing of received data is
|
||||
simulated with the help of a periodic timer. To provide new credits, you
|
||||
call the *rfcomm_grant_credits* function with the RFCOMM channel ID
|
||||
@ -572,8 +573,8 @@ for a minimal memory footprint. If possible, multiple RFCOMM buffers
|
||||
should be used to avoid pauses while the sender has to wait for a new
|
||||
credit.
|
||||
|
||||
### Slowing down RFCOMM data reception
|
||||
<a name="sec:manualCredits"></a>
|
||||
|
||||
### Slowing down RFCOMM data reception {#sec:manualCreditsProtocols}
|
||||
|
||||
RFCOMM’s credit-based flow-control can be used to adapt, i.e., slow down
|
||||
the RFCOMM data to your processing speed. For incoming data, BTstack
|
||||
@ -595,8 +596,7 @@ connection is used. See Listing [below](#lst:automaticFlowControl).
|
||||
}
|
||||
|
||||
|
||||
SDP - Service Discovery Protocol
|
||||
--------------------------------
|
||||
## SDP - Service Discovery Protocol
|
||||
|
||||
The SDP protocol allows to announce services and discover services
|
||||
provided by a remote Bluetooth device.
|
||||
@ -627,11 +627,11 @@ a sub-DES. The returned pointer is used to add elements to this sub-DES.
|
||||
After adding all UUIDs, the sub-DES is “closed” with
|
||||
*de_pop_sequence*.
|
||||
|
||||
### Query remote SDP service
|
||||
<a name="sec:querysdp"></a>
|
||||
|
||||
### Query remote SDP service {#sec:querySDPProtocols}
|
||||
|
||||
BTstack provides an SDP client to query SDP services of a remote device.
|
||||
The SDP Client API is shown in [here](appendix/apis/#appendix:api_sdp). The
|
||||
The SDP Client API is shown in [here](appendix/apis/#sec:sdpAPIAppendix). The
|
||||
*sdp_client_query* function initiates an L2CAP connection to the
|
||||
remote SDP server. Upon connect, a *Service Search Attribute* request
|
||||
with a *Service Search Pattern* and a *Attribute ID List* is sent. The
|
||||
@ -735,11 +735,12 @@ of L2CAP, and it specifies a minimum L2CAP MTU of 1691 bytes.
|
||||
To receive BNEP events, please register a packet handler with
|
||||
*bnep_register_packet_handler*.
|
||||
|
||||
### Access a BNEP service on a remote device {#subsubsection:bnepclient}
|
||||
|
||||
### Access a BNEP service on a remote device {#sec:bnepClientProtocols}
|
||||
|
||||
To connect to a remote BNEP service, you need to know its UUID. The set
|
||||
of available UUIDs can be queried by a SDP query for the PAN profile.
|
||||
Please see section on [PAN profile](profiles/#section:pan_profile) for details.
|
||||
Please see section on [PAN profile](profiles/#sec:panProfiles) for details.
|
||||
With the remote UUID, you can create a connection using the *bnep_connect*
|
||||
function. You’ll receive a *BNEP_EVENT_OPEN_CHANNEL_COMPLETE* on success or
|
||||
failure.
|
||||
@ -756,7 +757,8 @@ multicast filters with *bnep_set_net_type_filter* and
|
||||
|
||||
Finally, to close a BNEP connection, you can call *bnep_disconnect*.
|
||||
|
||||
### Provide BNEP service {#subsubsection:bnepserver}
|
||||
|
||||
### Provide BNEP service {#sec:bnepServiceProtocols}
|
||||
|
||||
To provide a BNEP service, call *bnep_register_service* with the
|
||||
provided service UUID and a max frame size.
|
||||
@ -781,11 +783,11 @@ attribute database and provided by the *att_server* implementation. The
|
||||
constant data are automatically served by the ATT server upon client
|
||||
request. To receive the dynamic data, such is characteristic value, the
|
||||
application needs to register read and/or write callback. In addition,
|
||||
notifications and indications can be sent. Please see Section
|
||||
[section:GATTClient] for more.
|
||||
notifications and indications can be sent. Please see Section on
|
||||
[GATT client](profiles/#sec:GATTClientProfiles) for more.
|
||||
|
||||
## SMP - Security Manager Protocol
|
||||
<a name="section:smp"></a>
|
||||
|
||||
## SMP - Security Manager Protocol {#sec:smpProtocols}
|
||||
|
||||
The SMP protocol allows to setup authenticated and encrypted LE
|
||||
connection. After initialization and configuration, SMP handles security
|
||||
@ -802,7 +804,8 @@ If you’re creating a product, you should also call *sm_set_ir()* and
|
||||
ER key seeds. If possible use a unique random number per device instead
|
||||
of deriving it from the product serial number or something similar. The
|
||||
encryption key generated by the BLE peripheral will be ultimately
|
||||
derived from the ER key seed. See [Bluetooth Specification](https://www.bluetooth.org/Technical/Specifications/adopted.htm) -
|
||||
derived from the ER key seed. See
|
||||
[Bluetooth Specification](https://www.bluetooth.org/Technical/Specifications/adopted.htm) -
|
||||
Bluetooth Core V4.0, Vol 3, Part G, 5.2.2 for more details on deriving
|
||||
the different keys. The IR key is used to identify a device if private,
|
||||
resolvable Bluetooth addresses are used.
|
||||
|
@ -16,7 +16,7 @@ and optionally git :
|
||||
Windows: Add Python installation folder to the Windows Path in
|
||||
Environment Variables.
|
||||
|
||||
Adding paths to the Windows Path variable <a name="sec:windowsPath"></a>:
|
||||
### Adding paths to the Windows Path variable {#sec:windowsPathQuickStart}
|
||||
|
||||
- Go to: Control Panel->System->Advanced tab->Environment Variables.
|
||||
|
||||
@ -33,7 +33,7 @@ Adding paths to the Windows Path variable <a name="sec:windowsPath"></a>:
|
||||
|
||||
Use git to clone the latest version:
|
||||
|
||||
git clone https://github.com/bluekitchen/btstack.git
|
||||
git clone https://github.com/bluekitchen/btstack.git
|
||||
|
||||
|
||||
Alternatively, you can download it as a ZIP archive from
|
||||
@ -54,7 +54,8 @@ provided, too.
|
||||
|
||||
## Run the Example
|
||||
|
||||
As a first test, we recommend [the SPP Counter example](examples/generated/#section:sppcounter). During the startup, for TI chipsets, the init
|
||||
As a first test, we recommend the [SPP Counter example](examples/generated/#sec:sppcounterExample).
|
||||
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
|
||||
@ -83,8 +84,8 @@ Bluetooth. For this, execute:
|
||||
|
||||
It’s also possible to run the examples on Win32 systems. For this:
|
||||
|
||||
- Install [MSYS](www.mingw.org/wiki/msys) and
|
||||
[MINGW32](www.mingw.org) using the MINGW installer
|
||||
- Install [MSYS](http://www.mingw.org/wiki/msys) and
|
||||
[MINGW32](http://www.mingw.org) using the MINGW installer
|
||||
|
||||
- Compile and install libusb-1.0.19 to [/usr/local/]() in msys command
|
||||
shell
|
||||
@ -113,7 +114,7 @@ and installation instructions are provided on the
|
||||
On Windows, you need to download and extract
|
||||
[mspgcc](http://sourceforge.net/projects/mspgcc/files/Windows/mingw32/)
|
||||
to [C:\mspgcc](). Add [C:\mspgcc\bin]() folder to the Windows Path in Environment
|
||||
variable as explained [here](#sec:windowsPath).
|
||||
variable as explained [here](#sec:windowsPathQuickStart).
|
||||
|
||||
**Loading Firmware.** To load firmware files onto the MSP430 MCU for the
|
||||
MSP-EXP430F5438 Experimeneter board, you need a programmer like the
|
||||
@ -129,7 +130,7 @@ following software tools:
|
||||
|
||||
<!-- -->
|
||||
|
||||
MSP430Flasher.exe -n MSP430F5438A -w "BINARY_FILE_NAME.hex" -v -g -z [VCC]
|
||||
MSP430Flasher.exe -n MSP430F5438A -w "BINARY_FILE_NAME.hex" -v -g -z [VCC]
|
||||
|
||||
|
||||
- [MSPDebug](http://mspdebug.sourceforge.net/):
|
||||
@ -175,9 +176,8 @@ the BLE part. The conversion script has been updated to detect
|
||||
*bluetooth_init_cc256x_1.2.bts* and adds *BLE_init_cc256x_1.2.bts*
|
||||
if present and merges them into a single .c file.
|
||||
|
||||
<a name="platform:msp430"></a>
|
||||
|
||||
### MSP-EXP430F5438 + CC256x Platform
|
||||
### MSP-EXP430F5438 + CC256x Platform {#sec:platformMSP430QuickStart}
|
||||
|
||||
**Hardware Setup.** We assume that a PAN1315, PAN1317, or PAN1323 module
|
||||
is plugged into RF1 and RF2 of the MSP-EXP430F5438 board and the “RF3
|
||||
@ -196,10 +196,11 @@ BTM805 Bluetooth module. In the port, the UART on the DAC daughter board
|
||||
was used for the debug output. Please remove the DAC board and connect a
|
||||
3.3V USB-2-UART converter to GND and TX to get the debug output.
|
||||
|
||||
In [platforms/pic32-harmony](), a project file for the MPLAB X IDE is provided as well as a regular
|
||||
In [platforms/pic32-harmony](), a project file for the MPLAB X IDE
|
||||
is provided as well as a regular
|
||||
Makefile. Both assume that the MPLAB XC32 compiler is installed. The
|
||||
project is set to use -Os optimization which will cause warnings if you
|
||||
only have the Free version. It will still compile a working example. For
|
||||
this platform, we only provide the SPP and LE Counter example directly.
|
||||
Other examples can be run by replacing the spp_and_le_counter.c file
|
||||
Other examples can be run by replacing the *spp_and_le_counter.c* file
|
||||
with one of the other example files.
|
||||
|
87
docs/manual/markdown/markdown2mkdocs.py
Executable file
87
docs/manual/markdown/markdown2mkdocs.py
Executable file
@ -0,0 +1,87 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys, yaml
|
||||
import os, re
|
||||
|
||||
def insert_anchor(mdout, reference):
|
||||
mdout.write("<a name=\"" + reference + "\"></a>\n\n")
|
||||
|
||||
def insert_reference(mdout, text, link):
|
||||
mdout.write("")
|
||||
|
||||
def fcopy(source_file, dest_file):
|
||||
with open(dest_file, 'w') as mdout:
|
||||
with open(source_file, 'r') as mdin:
|
||||
for line in mdin:
|
||||
mdout.write(line)
|
||||
|
||||
def process_sections(temp_file, dest_file):
|
||||
with open(dest_file, 'w') as mdout:
|
||||
with open(temp_file, 'r') as mdin:
|
||||
for line in mdin:
|
||||
section = re.match('(#+.*){#(sec:.*)}',line)
|
||||
if section:
|
||||
insert_anchor(mdout, section.group(2))
|
||||
mdout.write(section.group(1)+"\n")
|
||||
else:
|
||||
mdout.write(line)
|
||||
|
||||
fcopy(dest_file, temp_file)
|
||||
return
|
||||
|
||||
def process_figures(temp_file, dest_file):
|
||||
with open(dest_file, 'w') as mdout:
|
||||
with open(temp_file, 'r') as mdin:
|
||||
for line in mdin:
|
||||
# detect figure
|
||||
figure = re.match('\s*(\!.*)({#(fig:.*)})',line)
|
||||
if figure:
|
||||
insert_anchor(mdout, figure.group(3))
|
||||
mdout.write(figure.group(1)+"\n")
|
||||
else:
|
||||
figure_ref = re.match('.*({@(fig:.*)})',line)
|
||||
if figure_ref:
|
||||
md_reference = "[below](#"+figure_ref.group(2)+")"
|
||||
line = line.replace(figure_ref.group(1), md_reference)
|
||||
mdout.write(line)
|
||||
fcopy(dest_file, temp_file)
|
||||
return
|
||||
|
||||
# def process_listings(temp_file, dest_file):
|
||||
# with open(dest_file, 'w') as mdout:
|
||||
# with open(temp_file, 'r') as mdin:
|
||||
# for line in mdin:
|
||||
# mdout.write(line)
|
||||
# fcopy(dest_file, temp_file)
|
||||
# return
|
||||
|
||||
# def process_tables(temp_file, dest_file):
|
||||
# with open(dest_file, 'w') as mdout:
|
||||
# with open(temp_file, 'r') as mdin:
|
||||
# for line in mdin:
|
||||
# mdout.write(line)
|
||||
# fcopy(dest_file, temp_file)
|
||||
# return
|
||||
|
||||
|
||||
def main(argv):
|
||||
md_template = "docs"
|
||||
md_temp = "docs_tmp"
|
||||
md_final = "docs_final"
|
||||
yml_file = "mkdocs.yml"
|
||||
|
||||
with open(yml_file, 'r') as yin:
|
||||
doc = yaml.load(yin)
|
||||
for page in doc["pages"]:
|
||||
source_file = md_template +"/"+ page[0]
|
||||
temp_file = md_temp +"/"+ page[0]
|
||||
dest_file = md_final +"/"+ page[0]
|
||||
|
||||
process_sections(temp_file, dest_file)
|
||||
process_figures(temp_file, dest_file)
|
||||
# process_listings(temp_file, dest_file)
|
||||
# process_tables(temp_file, dest_file)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv[1:])
|
@ -24,9 +24,15 @@ def main(argv):
|
||||
with open(docs_folder +"/"+ md_file, 'r') as mdin:
|
||||
aout.write("\n\n#"+ title +"\n\n")
|
||||
for line in mdin:
|
||||
# remove path from section reference
|
||||
# e.g. [the SPP Counter example](examples/generated/#sec:sppcounterExample)
|
||||
# replace with [the SPP Counter example](#sec:sppcounterExample)
|
||||
section_ref = re.match('.*\(((.*)(#sec:.*))\).*',line)
|
||||
if section_ref:
|
||||
line = line.replace(section_ref.group(2),"")
|
||||
aout.write(line)
|
||||
|
||||
pandoc_cmd = "pandoc -f markdown -t latex --listings latex/btstack_generated.md -o latex/btstack_generated.tex"
|
||||
pandoc_cmd = "pandoc -f markdown -t latex --filter pandoc-fignos --listings latex/btstack_generated.md -o latex/btstack_generated.tex"
|
||||
p = os.popen(pandoc_cmd,"r")
|
||||
while 1:
|
||||
line = p.readline()
|
||||
|
@ -1,5 +1,6 @@
|
||||
site_name: BTstack Manual
|
||||
site_dir: btstack
|
||||
docs_dir: docs_final
|
||||
pages:
|
||||
- [index.md, Welcome]
|
||||
- [quick_start.md, Quick Start]
|
||||
|
@ -16,8 +16,7 @@ code_identation = " "
|
||||
|
||||
api_header = """
|
||||
|
||||
## API_TITLE API
|
||||
<a name ="appendix:API_LABLE"></a>
|
||||
## API_TITLE API {#sec:API_LABLEAPIAppendix}
|
||||
|
||||
"""
|
||||
|
||||
@ -26,18 +25,18 @@ api_ending = """
|
||||
|
||||
# [file_name, api_title, api_lable]
|
||||
list_of_apis = [
|
||||
[btstack_folder+"include/btstack/run_loop.h", "Run Loop", "api_run_loop"],
|
||||
[btstack_folder+"src/hci.h", "HCI", "api_hci"],
|
||||
[btstack_folder+"src/l2cap.h", "L2CAP", "api_l2cap"],
|
||||
[btstack_folder+"src/rfcomm.h", "RFCOMM", "api_rfcomm"],
|
||||
[btstack_folder+"src/sdp.h", "SDP", "api_sdp"],
|
||||
[btstack_folder+"src/sdp_client.h", "SDP Client", "api_sdp_client"],
|
||||
[btstack_folder+"src/sdp_query_rfcomm.h", "SDP RFCOMM Query", "api_sdp_queries"],
|
||||
[btstack_folder+"ble/gatt_client.h", "GATT Client", "api_gatt_client"],
|
||||
[btstack_folder+"src/pan.h", "PAN", "api_pan"],
|
||||
[btstack_folder+"src/bnep.h", "BNEP", "api_bnep"],
|
||||
[btstack_folder+"src/gap.h", "GAP", "api_gap"],
|
||||
[btstack_folder+"ble/sm.h", "SM", "api_sm"]
|
||||
[btstack_folder+"include/btstack/run_loop.h", "Run Loop", "runLoop"],
|
||||
[btstack_folder+"src/hci.h", "HCI", "hci"],
|
||||
[btstack_folder+"src/l2cap.h", "L2CAP", "l2cap"],
|
||||
[btstack_folder+"src/rfcomm.h", "RFCOMM", "rfcomm"],
|
||||
[btstack_folder+"src/sdp.h", "SDP", "sdp"],
|
||||
[btstack_folder+"src/sdp_client.h", "SDP Client", "sdpClient"],
|
||||
[btstack_folder+"src/sdp_query_rfcomm.h", "SDP RFCOMM Query", "sdpQueries"],
|
||||
[btstack_folder+"ble/gatt_client.h", "GATT Client", "gattClient"],
|
||||
[btstack_folder+"src/pan.h", "PAN", "pan"],
|
||||
[btstack_folder+"src/bnep.h", "BNEP", "bnep"],
|
||||
[btstack_folder+"src/gap.h", "GAP", "gap"],
|
||||
[btstack_folder+"ble/sm.h", "SM", "sm"]
|
||||
]
|
||||
|
||||
def replacePlaceholder(template, title, lable):
|
||||
|
@ -32,12 +32,11 @@ examples_header = """
|
||||
"""
|
||||
|
||||
example_item = """
|
||||
- [EXAMPLE_TITLE](#section:EXAMPLE_LABEL): EXAMPLE_DESC.
|
||||
- [EXAMPLE_TITLE](#sec:EXAMPLE_LABELExample): EXAMPLE_DESC.
|
||||
"""
|
||||
example_section = """
|
||||
|
||||
## EXAMPLE_TITLE: EXAMPLE_DESC
|
||||
<a name="section:EXAMPLE_LABEL"></a>
|
||||
## EXAMPLE_TITLE: EXAMPLE_DESC {#sec:EXAMPLE_LABELExample}
|
||||
|
||||
"""
|
||||
example_subsection = """
|
||||
@ -72,7 +71,7 @@ def latexText(text, ref_prefix):
|
||||
refs = re.match('.*(Section\s+)(\w+).*',brief)
|
||||
if refs:
|
||||
brief = brief.replace(refs.group(1), "[here]")
|
||||
brief = brief.replace(refs.group(2), "(#section:"+refs.group(2)+")")
|
||||
brief = brief.replace(refs.group(2), "(#sec:"+refs.group(2)+")")
|
||||
|
||||
return brief
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user