diff --git a/docs/manual/btstack_gettingstarted.tex b/docs/manual/btstack_gettingstarted.tex index e1d8c5248..34b5d7869 100644 --- a/docs/manual/btstack_gettingstarted.tex +++ b/docs/manual/btstack_gettingstarted.tex @@ -434,634 +434,6 @@ Separate packet handlers can be used for each L2CAP service and outgoing connect \newcommand{\BluetoothSpecificationURL}{\href{https://www.bluetooth.org/Technical/Specifications/adopted.htm}{\color{blue} Bluetooth Specification}} \input{protocols_profiles} -%\input{client_server} - -% \section{Quick Recipes} - -% % \subsection{Periodic time handler} -% % \label{section:periodicTimer} -% % As timers in BTstack are single shot, a periodic timer, e.g., to implement a counter or to periodically sample a sesor, is implemented by re-registering the \emph{timer\_source} in the \emph{timer\_handler} callback function, as shown in Listing \ref{PeriodicTimeHandler}. - -% % \begin{lstlisting}[caption=Periodic counter, label=PeriodicTimeHandler] -% % #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{Defining custom HCI command templates} - -% Each HCI command is assigned a 2 byte OpCode used to uniquely identify different types of commands. The OpCode parameter is divided into two fields, called the OpCode Group Field (OGF) and OpCode Command Field (OCF), see \BluetoothSpecification{} - Core Version 4.0, Volume 2, Part E, Chapter 5.4. In a HCI command, the OpCode is followed by parameter total length, and the actual parameters. - -% BTstack provides the \emph{hci\_cmd\_t} struct as a compact format to define HCI command packets, see Listing \ref{HCIcmdTemplate}, and \path{include/btstack/hci_cmds.h} file in the source code. The OpCode of a command can be calculated using the OPCODE macro. - - -% \noindent\begin{minipage}{\textwidth} -% \begin{lstlisting}[caption = hci\_cmds.h defines HCI command template., label=HCIcmdTemplate] -% // Calculate combined ogf/ocf value. -% #define OPCODE(ogf, ocf) (ocf | ogf << 10) - -% // Compact HCI Command packet description. -% typedef struct { -% uint16_t opcode; -% const char *format; -% } hci_cmd_t; - -% extern const hci_cmd_t hci_write_local_name; -% ... -% \end{lstlisting} -% \end{minipage} - -% \begin{lstlisting}[caption=hci.h defines possible OGFs used for creation of a HCI command., label=hciCmdOGF] -% #define OGF_LINK_CONTROL 0x01 -% #define OGF_LINK_POLICY 0x02 -% #define OGF_CONTROLLER_BASEBAND 0x03 -% #define OGF_INFORMATIONAL_PARAMETERS 0x04 -% #define OGF_LE_CONTROLLER 0x08 -% #define OGF_BTSTACK 0x3d -% #define OGF_VENDOR 0x3f -% \end{lstlisting} - -% Listing \ref{hciCmdOGF} shows the OGFs provided by BTstack in \path{src/hci.h} file. For all existing Bluetooth commands and their OCFs see \BluetoothSpecificationURL{} - Core Version 4.0, Volume 2, Part E, Chapter 7. - -% Listing \ref{HCIcmdExample} illustrates the \emph{hci\_write\_local\_name} HCI command template from \mbox{BTstack} library. It uses OGF\_CONTROLLER\_BASEBAND as OGF, 0x13 as OCF, and has one parameter with format "N" indicating a null terminated UTF-8 string. Table \ref{table:hciformat} lists the format specifiers supported by BTstack. Check \path{src/hci_cmds.c} for other predefined HCI commands and info on their parameters. - -% \begin{lstlisting}[caption= Example of HCI command template., label=HCIcmdExample] -% // Sets local Bluetooth name -% const hci_cmd_t hci_write_local_name = { -% OPCODE(OGF_CONTROLLER_BASEBAND, 0x13), "N" -% // Local name (UTF-8, Null Terminated, max 248 octets) -% }; -% \end{lstlisting} - -% \begin{table*}\centering -% \caption{Supported Format Specifiers of HCI Command Parameter} -% \begin{tabular}{cl}\toprule -% Format Specifier & Description\\ -% \midrule -% "1" & 8 bit value \\ -% "2" & 16 bit value \\ -% "H" & HCI handle \\ -% "3" & 24 bit value \\ -% "4" & 32 bit value \\ -% "B" & Bluetooth address \\ -% "D" & 8 byte data block \\ -% "E" & Extended Inquiry Information 240 octets \\ -% "N" & UTF8 string, null terminated \\ -% "P" & 16 byte PIN code or link key \\ -% "A" & 31 bytes advertising data \\ -% "S" & Service Record (Data Element Sequence)\\ -% \bottomrule -% \label{table:hciformat} -% \end{tabular} -% \end{table*} - -% \subsection{Sending HCI command based on a template} -% You can use the \emph{hci\_send-\_cmd} function to send HCI command based on a template and a list of parameters. However, it is necessary to check that the outgoing packet buffer is empty and that the Bluetooth module is ready to receive the next command - most modern Bluetooth modules only allow to send a single HCI command. This can be done by calling \emph{hci\_can\_send\_packet\_now(HCI\_COMMAND\_DATA\_PACKET)} function, which returns true, if it is ok to send. Note: we'll integrate that check into \emph{hci\_send\_cmd}. - -% Listing \ref{HCIcmdExampleLocalName} illustrates how to set the device name with the HCI Write Local Name command. - -% Please note, that an application rarely has to send HCI commands on its own. All higher level functions in BTstack for the L2CAP and RFCOMM APIs manage this automatically. The main use of HCI commands in application is during the startup phase. At this time, no L2CAP or higher level data is sent, and the setup is usually done in the packet handler where the reception of the last command complete event triggers sending of the next command, hereby asserting that the Bluetooth module is ready and the outgoing buffer is free as shown in Listing \ref{HCIcmdsExample} taken from \path{MSP-EXP430F5438-CC256x/example-ble/ble_server.c}. - -% \begin{lstlisting}[caption= Send hci\_write\_local\_name command that takes a string as a parameter., label=HCIcmdExampleLocalName] -% if (hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)){ -% hci_send_cmd(&hci_write_local_name, "BTstack Demo"); -% } -% \end{lstlisting} - -% \noindent\begin{minipage}{\textwidth} -% \begin{lstlisting}[caption=Example of sending a sequence of HCI Commands,label=HCIcmdsExample] -% void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ -% ... -% switch (event) { -% .. -% case HCI_EVENT_COMMAND_COMPLETE: -% ... -% if (COMMAND_COMPLETE_EVENT(packet, hci_read_local_supported_features)){ -% hci_send_cmd(&hci_set_event_mask, 0xffffffff, 0x20001fff); -% break; -% } -% if (COMMAND_COMPLETE_EVENT(packet, hci_set_event_mask)){ -% hci_send_cmd(&hci_write_le_host_supported, 1, 1); -% break; -% } -% if (COMMAND_COMPLETE_EVENT(packet, hci_write_le_host_supported)){ -% hci_send_cmd(&hci_le_set_event_mask, 0xffffffff, 0xffffffff); -% break; -% } -% if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_event_mask)){ -% hci_send_cmd(&hci_le_read_buffer_size); -% break; -% } -% ... -% break; -% ... -% } -% } -% \end{lstlisting} -% \end{minipage} - -% \subsection{Living with a single output buffer} -% \label{section:single_buffer} -% % l2cap checks hci_can_send_packet now -% 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. - -% \noindent\begin{minipage}{\textwidth} -% \begin{lstlisting}[caption=Preparing and sending data., label=SingleOutputBufferTryToSend] -% void prepareData(void){ -% ... -% } - -% void tryToSend(void){ -% if (!dataLen) return; -% if (!rfcomm_channel_id) return; - -% int err = rfcomm_send_internal(rfcomm_channel_id, dataBuffer, dataLen); -% switch (err){ -% case 0: -% // packet is sent prepare next one -% prepareData(); -% break; -% case RFCOMM_NO_OUTGOING_CREDITS: -% case BTSTACK_ACL_BUFFERS_FULL: -% break; -% default: -% printf("rfcomm_send_internal() -> err %d\n\r", err); -% break; -% } -% } -% \end{lstlisting} -% \begin{lstlisting}[ caption= Managing the speed of RFCOMM packet generation., label=SingleOutputBufferTryPH] -% void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ -% ... -% switch(event){ -% case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE: -% if (status) { -% printf("RFCOMM channel open failed."); -% } else { -% rfcomm_channel_id = READ_BT_16(packet, 12); -% rfcomm_mtu = READ_BT_16(packet, 14); -% printf("RFCOMM channel opened, mtu = %u.", rfcomm_mtu); -% } -% break; -% case RFCOMM_EVENT_CREDITS: -% case DAEMON_EVENT_HCI_PACKET_SENT: -% tryToSend(); -% break; -% case RFCOMM_EVENT_CHANNEL_CLOSED: -% rfcomm_channel_id = 0; -% break; -% ... -% } -% } -% \end{lstlisting} -% \end{minipage} - -% Independent from the number of output buffers, packet generation has to be adapted to the remote receiver and/or maximal link speed. Therefore, a packet can only be generated when it can get sent. With this assumption, the single output buffer design does not impose additional restrictions. In the following, we show how this is used for adapting the RFCOMM send rate. - -% BTstack returns BTSTACK\_ACL\_BUFFERS\_FULL, if the outgoing buffer is full and RFCOMM\_NO\_OUTGOING\_CREDITS, if no outgoing credits are available. In Listing \ref{SingleOutputBufferTryToSend}, we show how to resend data packets when credits or outgoing buffers become available. - -% \begin{lstlisting}[caption=Setting device as discoverable. OFF by default., label=Discoverable] -% int main(void){ -% ... -% // make discoverable -% hci_discoverable_control(1); -% run_loop_execute(); -% return 0; -% } -% void packet_handler (uint8_t packet_type, uint8_t *packet, uint16_t size){ -% ... -% switch(state){ -% case INIT: -% if (packet[2] == HCI_STATE_WORKING) { -% hci_send_cmd(&hci_write_local_name, "BTstack SPP Counter"); -% state = W4_CONNECTION; -% } -% break; -% case W4_CHANNEL_COMPLETE: -% // if connection is successful, make device undiscoverable -% hci_discoverable_control(0); -% ... -% } -% } -% \end{lstlisting} - - -% RFCOMM's mandatory credit-based flow-control imposes an additional constraint on sending a data packet - at least one new RFCOMM credit must be available. BTstack signals the availability of a credit by sending an RFCOMM credit (RFCOMM\_EVENT\_CREDITS) event. - -% These two events represent two orthogonal mechanisms that deal with flow control. Taking these mechanisms in account, the application should try to send data packets when one of these two events is received, see Listing \ref{SingleOutputBufferTryPH} for a RFCOMM example. - -% \subsection{Become discoverable} -% A remote unconnected Bluetooth device must be set as "discoverable" in order to be seen by a device performing the inquiry scan. To become discoverable, an application can call \emph{hci\_discoverable\_control} with input parameter 1. If you want to provide a helpful name for your device, the application can set its local name by sending the $hci\_write\_local\_name$ command. To save energy, you may set the device as undiscoverable again, once a connection is established. See Listing \ref{Discoverable} for an example. - - -% \subsection{Discover remote devices} -% \label{section:DiscoverDevices} -% To scan for remote devices, the \emph{hci\_inquiry} command is used. After that, the Bluetooth devices actively scans for other devices and reports these as part of HCI\_EVENT\_INQUIRY\_RESULT, HCI\_EVENT-\_INQUIRY\_RESULT\_WITH\_RSSI, or HCI\_EVENT\_EXTENDED\_INQUIRY\_RE-SPONSE 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 \ref{DiscoverDevices}. - -% By default, neither RSSI values nor EIR are reported. If the Bluetooth device implements Bluetooth Specification 2.1 or higher, the \emph{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 in Section \ref{example:GapInquiry}. - -% \begin{lstlisting}[float, caption=Discovering remote Bluetooth devices., label=DiscoverDevices] -% void print_inquiry_results(uint8_t *packet){ -% int event = packet[0]; -% int numResponses = packet[2]; -% uint16_t classOfDevice, clockOffset; -% uint8_t rssi, pageScanRepetitionMode; -% for (i=0; itype){ -% case SDP_QUERY_RFCOMM_SERVICE: -% ve = (sdp_query_rfcomm_service_event_t*) event; -% printf("Service name: '%s', RFCOMM port %u\n", ve->service_name, ve->channel_nr); -% break; -% case SDP_QUERY_COMPLETE: -% report_found_services(); -% printf("Client query response done with status %d. \n", ce->status); -% break; -% } -% } - -% int main(void){ -% hw_setup(); -% btstack_setup(); - -% // register callback to receive matching RFCOMM Services and -% // query complete event -% sdp_query_rfcomm_register_callback(handle_query_rfcomm_event, NULL); - -% // turn on! -% hci_power_control(HCI_POWER_ON); -% // go! -% run_loop_execute(); -% return 0; -% } - -% \end{lstlisting} \section{Examples} \label{examples} @@ -1248,7 +620,6 @@ void packet_handler (uint8_t packet_type, uint8_t *packet, uint16_t size){ switch(state){ case INIT: if (packet[2] == HCI_STATE_WORKING) { - hci_send_cmd(&hci_write_local_name, "BTstack Demo"); state = W4_CONNECTION; } break; diff --git a/docs/manual/protocols_profiles.tex b/docs/manual/protocols_profiles.tex index 73cd5e040..b64889597 100644 --- a/docs/manual/protocols_profiles.tex +++ b/docs/manual/protocols_profiles.tex @@ -580,12 +580,6 @@ int main(void){ void packet_handler (uint8_t packet_type, uint8_t *packet, uint16_t size){ ... switch(state){ - case INIT: - if (packet[2] == HCI_STATE_WORKING) { - hci_send_cmd(&hci_write_local_name, "BTstack SPP Counter"); - state = W4_CONNECTION; - } - break; case W4_CHANNEL_COMPLETE: // if connection is successful, make device undiscoverable hci_discoverable_control(0); diff --git a/example/embedded/spp_counter.c b/example/embedded/spp_counter.c index caa0f6c5a..378f3c5ad 100644 --- a/example/embedded/spp_counter.c +++ b/example/embedded/spp_counter.c @@ -82,7 +82,7 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha case BTSTACK_EVENT_STATE: // bt stack activated, get started - set local name if (packet[2] == HCI_STATE_WORKING) { - hci_send_cmd(&hci_write_local_name, "BTstack SPP Counter"); + printf("BTstack is up and running\n"); } break; @@ -204,6 +204,7 @@ int btstack_main(int argc, const char * argv[]){ run_loop_set_timer(&heartbeat, HEARTBEAT_PERIOD_MS); run_loop_add_timer(&heartbeat); + gap_set_local_name("BTstack SPP Counter"); // turn on! hci_power_control(HCI_POWER_ON); diff --git a/example/embedded/spp_flowcontrol.c b/example/embedded/spp_flowcontrol.c index c81b24782..dacdafd2f 100644 --- a/example/embedded/spp_flowcontrol.c +++ b/example/embedded/spp_flowcontrol.c @@ -78,9 +78,8 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha switch (packet[0]) { case BTSTACK_EVENT_STATE: - // bt stack activated, get started - set local name if (packet[2] == HCI_STATE_WORKING) { - hci_send_cmd(&hci_write_local_name, "BTstack SPP Flow Control"); + printf("BTstack is up and running\n"); } break; @@ -90,10 +89,6 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha printf("BD-ADDR: %s\n\r", bd_addr_to_str(event_addr)); break; } - if (COMMAND_COMPLETE_EVENT(packet, hci_write_local_name)){ - hci_discoverable_control(1); - break; - } break; case HCI_EVENT_LINK_KEY_REQUEST: @@ -184,6 +179,8 @@ int btstack_main(int argc, const char * argv[]){ run_loop_add_timer(&heartbeat); puts("SPP FlowControl Demo: simulates processing on received data...\n\r"); + gap_set_local_name("BTstack SPP Flow Control"); + hci_discoverable_control(1); // turn on! hci_power_control(HCI_POWER_ON); diff --git a/platforms/ez430-rf2560/example/ant-test.c b/platforms/ez430-rf2560/example/ant-test.c index f776107f8..50ea01113 100644 --- a/platforms/ez430-rf2560/example/ant-test.c +++ b/platforms/ez430-rf2560/example/ant-test.c @@ -55,9 +55,10 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha switch (packet[0]) { case BTSTACK_EVENT_STATE: - // bt stack activated, get started - set local name if (packet[2] == HCI_STATE_WORKING) { - hci_send_cmd(&hci_write_local_name, "BlueMSP-Demo"); + printf("BTstack is up and running\n"); + // start ANT init + ant_send_cmd(&ant_reset); } break; @@ -67,12 +68,7 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha printf("BD-ADDR: %s\n\r", bd_addr_to_str(event_addr)); break; } - if (COMMAND_COMPLETE_EVENT(packet, hci_write_local_name)){ - // start ANT init - ant_send_cmd(&ant_reset); - break; - } - break; + break; case HCI_EVENT_LINK_KEY_REQUEST: // deny link key request @@ -205,14 +201,14 @@ int btstack_main(int argc, const char * argv[]){ run_loop_set_timer(&heartbeat, HEARTBEAT_PERIOD_MS); run_loop_add_timer(&heartbeat); - printf("Run...\n\r"); - - // turn on! - hci_power_control(HCI_POWER_ON); - - // default to discoverable + // set local name + gap_set_local_name("BlueMSP-Demo"); + // make discoverable hci_discoverable_control(1); + printf("Run...\n\r"); + // turn on! + hci_power_control(HCI_POWER_ON); return 0; } diff --git a/platforms/ez430-rf2560/example/spp_accel.c b/platforms/ez430-rf2560/example/spp_accel.c index 19ffb2694..10ab3176a 100644 --- a/platforms/ez430-rf2560/example/spp_accel.c +++ b/platforms/ez430-rf2560/example/spp_accel.c @@ -95,9 +95,8 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha switch (packet[0]) { case BTSTACK_EVENT_STATE: - // bt stack activated, get started - set local name if (packet[2] == HCI_STATE_WORKING) { - hci_send_cmd(&hci_write_local_name, "BTstack SPP Sensor"); + printf("BTstack is up and running\n"); } break; @@ -107,10 +106,6 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha printf("BD-ADDR: %s\n\r", bd_addr_to_str(event_addr)); break; } - if (COMMAND_COMPLETE_EVENT(packet, hci_write_local_name)){ - hci_discoverable_control(1); - break; - } break; case HCI_EVENT_LINK_KEY_REQUEST: @@ -193,11 +188,12 @@ int btstack_main(int argc, const char * argv[]){ // ready - enable irq used in h4 task __enable_interrupt(); - // turn on! - hci_power_control(HCI_POWER_ON); + // set local name + gap_set_local_name("BTstack SPP Sensor"); // make discoverable hci_discoverable_control(1); - + // turn on! + hci_power_control(HCI_POWER_ON); return 0; } diff --git a/platforms/msp-exp430f5438-cc2564b/example/ant-test.c b/platforms/msp-exp430f5438-cc2564b/example/ant-test.c index f776107f8..d5727b3bd 100644 --- a/platforms/msp-exp430f5438-cc2564b/example/ant-test.c +++ b/platforms/msp-exp430f5438-cc2564b/example/ant-test.c @@ -55,10 +55,11 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha switch (packet[0]) { case BTSTACK_EVENT_STATE: - // bt stack activated, get started - set local name if (packet[2] == HCI_STATE_WORKING) { - hci_send_cmd(&hci_write_local_name, "BlueMSP-Demo"); - } + printf("BTstack is up and running\n"); + // start ANT init + ant_send_cmd(&ant_reset); + } break; case HCI_EVENT_COMMAND_COMPLETE: @@ -67,12 +68,7 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha printf("BD-ADDR: %s\n\r", bd_addr_to_str(event_addr)); break; } - if (COMMAND_COMPLETE_EVENT(packet, hci_write_local_name)){ - // start ANT init - ant_send_cmd(&ant_reset); - break; - } - break; + break; case HCI_EVENT_LINK_KEY_REQUEST: // deny link key request @@ -205,14 +201,14 @@ int btstack_main(int argc, const char * argv[]){ run_loop_set_timer(&heartbeat, HEARTBEAT_PERIOD_MS); run_loop_add_timer(&heartbeat); - printf("Run...\n\r"); - - // turn on! - hci_power_control(HCI_POWER_ON); - - // default to discoverable + // set local name + gap_set_local_name("BlueMSP-Demo"); + // make discoverable hci_discoverable_control(1); - + + printf("Run...\n\r"); + // turn on! + hci_power_control(HCI_POWER_ON); return 0; } diff --git a/platforms/msp-exp430f5438-cc2564b/example/spp_accel.c b/platforms/msp-exp430f5438-cc2564b/example/spp_accel.c index 19ffb2694..8de19827c 100644 --- a/platforms/msp-exp430f5438-cc2564b/example/spp_accel.c +++ b/platforms/msp-exp430f5438-cc2564b/example/spp_accel.c @@ -95,9 +95,8 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha switch (packet[0]) { case BTSTACK_EVENT_STATE: - // bt stack activated, get started - set local name if (packet[2] == HCI_STATE_WORKING) { - hci_send_cmd(&hci_write_local_name, "BTstack SPP Sensor"); + printf("BTstack is up and running.\n"); } break; @@ -107,10 +106,6 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha printf("BD-ADDR: %s\n\r", bd_addr_to_str(event_addr)); break; } - if (COMMAND_COMPLETE_EVENT(packet, hci_write_local_name)){ - hci_discoverable_control(1); - break; - } break; case HCI_EVENT_LINK_KEY_REQUEST: @@ -193,11 +188,13 @@ int btstack_main(int argc, const char * argv[]){ // ready - enable irq used in h4 task __enable_interrupt(); - // turn on! - hci_power_control(HCI_POWER_ON); + // set local name + gap_set_local_name("BTstack SPP Sensor"); // make discoverable hci_discoverable_control(1); - + + // turn on! + hci_power_control(HCI_POWER_ON); return 0; }