PowerBlocks SDK
 
Loading...
Searching...
No Matches
l2cap.c File Reference

Bluetooth L2CAP Layer. More...

#include "l2cap.h"
#include "hci.h"
#include "powerblocks/core/utils/log.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "blerror.h"
#include <stdlib.h>
#include <string.h>
#include <endian.h>
#include <stdalign.h>

Macros

#define L2CAP_TASK_STACK_SIZE   8192
 
#define L2CAP_TASK_PRIORITY   (configMAX_PRIORITIES / 4 * 3)
 
#define L2CAP_SIGNAL_TIMEOUT   1000
 
#define L2CAP_ERROR_LOGGING
 
#define L2CAP_INFO_LOGGING
 
#define L2CAP_LOG_ERROR(fmt, ...)
 
#define L2CAP_LOG_INFO(fmt, ...)
 
#define L2CAP_LOG_DEBUG(fmt, ...)
 
#define L2CAP_SIGNAL_CODE_REJECT   0x01
 
#define L2CAP_SIGNAL_CODE_CONNECTION_REQUEST   0x02
 
#define L2CAP_SIGNAL_CODE_CONNECTION_RESPONSE   0x03
 
#define L2CAP_SIGNAL_CODE_CONFIGURE_REQUEST   0x04
 
#define L2CAP_SIGNAL_CODE_CONFIGURE_RESPONSE   0x05
 
#define L2CAP_SIGNAL_CODE_DISCONNECTION_REQUEST   0x06
 
#define L2CAP_SIGNAL_CODE_DISCONNECTION_RESPONSE   0x07
 
#define L2CAP_SIGNAL_CODE_ECHO_REQUEST   0x08
 
#define L2CAP_SIGNAL_CODE_ECHO_RESPONSE   0x09
 
#define L2CAP_SIGNAL_CODE_INFORMATION_REQUEST   0x0A
 
#define L2CAP_SIGNAL_CODE_INFORMATION_RESPONSE   0x0B
 

Functions

int l2cap_initialize ()
 Initalized L2CAP.
 
void l2cap_signal_close ()
 Begins closing out of L2CAP.
 
void l2cap_close ()
 Closes out of L2CAP.
 
int l2cap_open_device (l2cap_device_t *device_handle, uint16_t hci_device_handle, const uint8_t *mac_address)
 Opens a L2CAP Connections.
 
void l2cap_close_device (l2cap_device_t *device_handle)
 Closes a L2CAP Connection.
 
int l2cap_open_channel (l2cap_device_t *device_handle, l2cap_channel_t *channel, uint16_t protocol_id, uint8_t *rx_buffer, int rx_buffer_size)
 Opens a L2CAP Channel.
 
void l2cap_close_channel (l2cap_channel_t *channel)
 Closes a L2CAP Channel.
 
int l2cap_send_channel (l2cap_channel_t *channel, const void *data, uint16_t size)
 Sends data over a L2CAP Channel.
 
int l2cap_receive_channel (l2cap_channel_t *channel, void *data, uint16_t size)
 Receives from a L2CAP Channel.
 
void l2cap_set_channel_receive_event (l2cap_channel_t *channel, l2cap_channel_event_t event, void *param)
 Sets the L2CAP on packet receive event.
 
void l2cap_task_write_channel_buffer (l2cap_channel_t *channel, const uint8_t *buffer, size_t size)
 

Variables

int round = 0
 

Detailed Description

Bluetooth L2CAP Layer.

L2CAP is a higher level ontop of HCI's ACI packets used to send and receive data from devices.

Its in charge of multiplexing data and reassembling/disassembling packets.

Author
Samuel Fitzsimons (rainbain)
Date
2025

Macro Definition Documentation

◆ L2CAP_LOG_ERROR

#define L2CAP_LOG_ERROR ( fmt,
... )
Value:
LOG_ERROR(TAG, fmt, ##__VA_ARGS__)

◆ L2CAP_LOG_INFO

#define L2CAP_LOG_INFO ( fmt,
... )
Value:
LOG_INFO(TAG, fmt, ##__VA_ARGS__)

Function Documentation

◆ l2cap_close()

void l2cap_close ( )

Closes out of L2CAP.

Must come after l2cap_signal_close and the HCI is closed. Will wait for the task to exit.

◆ l2cap_close_channel()

void l2cap_close_channel ( l2cap_channel_t * channel)

Closes a L2CAP Channel.

Closes a channel and frees its resources.

This will automatically be done for any remaining open channels when calling l2cap_close_device.

Parameters
channelChannel to close.

◆ l2cap_close_device()

void l2cap_close_device ( l2cap_device_t * device_handle)

Closes a L2CAP Connection.

Frees a L2CAP device and closes and frees all associated open channels.

Parameters
device_handleL2CAP device to close

◆ l2cap_initialize()

int l2cap_initialize ( )

Initalized L2CAP.

Its recommended this is called after hci_initialize but before working with any bluetooth devices.

This allows you to use L2CAP once a connection has been established.

Returns
Negative if Error

◆ l2cap_open_channel()

int l2cap_open_channel ( l2cap_device_t * device_handle,
l2cap_channel_t * channel,
uint16_t protocol_id,
uint8_t * rx_buffer,
int rx_buffer_size )

Opens a L2CAP Channel.

Once a device is open, channels can be opened and closed. Channels are much like sockets, and each one has its own protocol.

By default, the signal channel is already open and used by L2CAP.

Parameters
device_handleL2CAP device to open the channel on
channelChannel data structure to write into
protocol_idProtocol of the channel. Like the socket.
rx_bufferThe receiving buffer for the channel.
rx_buffer_sizeSize of the receiving buffer. Must be a power of 2.
Returns
Negative if Error.

◆ l2cap_open_device()

int l2cap_open_device ( l2cap_device_t * device_handle,
uint16_t hci_device_handle,
const uint8_t * mac_address )

Opens a L2CAP Connections.

Sets up L2CAP to communicate with a device. This sets up the default signal channel L2CAP uses, and adds the device to L2CAPS list of active devices.

Parameters
device_handleL2CAP Device Handle To Create
hci_device_handleDevice handle created by hci_create_connection
mac_addressMAC address of the device. Used to prevent duplicate connections.
Returns
Negative if Error.

◆ l2cap_receive_channel()

int l2cap_receive_channel ( l2cap_channel_t * channel,
void * data,
uint16_t size )

Receives from a L2CAP Channel.

Receives data from the internal buffer specified when creating the channel.

The buffer is treated as a FIFO and can hold multiple packets. In the event of an overflow, packet truncation and packet drops are logged and this will just return truncated or 0 byte packets.

Packets should never be truly lost, just that you will have saved up a bunch of 0 byte packets.

Will error on incomplete FIFO fragments.

Parameters
channelChannel to talk to
dataData Buffer
sizeSize of buffer. Up to 65535.
Returns
Total bytes read (even if they did not fit into buffer). Negative if error.

◆ l2cap_send_channel()

int l2cap_send_channel ( l2cap_channel_t * channel,
const void * data,
uint16_t size )

Sends data over a L2CAP Channel.

Sends a buffer over a L2CAP channel. Channels in L2CAP can be thought of as a lot like sockets. One device can run multiple protocols, and we expect to see specific protocols on specific channels.

Parameters
channelChannel to talk to
dataData Buffer
sizeSize of data. Up to 65535.
Returns
Negative if Error

◆ l2cap_set_channel_receive_event()

void l2cap_set_channel_receive_event ( l2cap_channel_t * channel,
l2cap_channel_event_t event,
void * param )

Sets the L2CAP on packet receive event.

When a packet is received on a channel, this event will be called to receive it if you please.

Parameters
channelChannel to set it in
eventEvent Handler
paramParameter passed to event.

◆ l2cap_signal_close()

void l2cap_signal_close ( )

Begins closing out of L2CAP.

I don't currently have a good way to cancel the blocking ACL read from it, so this will signal the thread to begin exiting. Once HCI is closed, it will actually exist.