BlueToe
an alternative GATT/BLE implementation
Loading...
Searching...
No Matches
l2cap_signaling_channel.hpp
1#ifndef BLUETOE_LINK_LAYER_L2CAP_SIGNALING_CHANNEL_HPP
2#define BLUETOE_LINK_LAYER_L2CAP_SIGNALING_CHANNEL_HPP
3
4#include <bluetoe/ll_meta_types.hpp>
5#include <bluetoe/codes.hpp>
6#include <bluetoe/l2cap_channels.hpp>
7
8#include <cstdlib>
9#include <cstdint>
10
11namespace bluetoe {
12
13namespace details {
14 struct signaling_channel_meta_type {};
15}
16
17namespace l2cap {
18
24 template < typename ... Options >
26 {
27 public:
29
33 template < typename ConnectionData >
34 void l2cap_input( const std::uint8_t* input, std::size_t in_size, std::uint8_t* output, std::size_t& out_size, ConnectionData& );
35
39 template < typename ConnectionData >
40 void l2cap_output( std::uint8_t* output, std::size_t& out_size, ConnectionData& );
41
48 bool connection_parameter_update_request( std::uint16_t interval_min, std::uint16_t interval_max, std::uint16_t latency, std::uint16_t timeout );
49
53 constexpr std::size_t channel_mtu_size() const;
54
56 static constexpr std::uint16_t channel_id = l2cap_channel_ids::signaling;
57 static constexpr std::size_t minimum_channel_mtu_size = bluetoe::details::default_att_mtu_size;
58 static constexpr std::size_t maximum_channel_mtu_size = bluetoe::details::default_att_mtu_size;
59
60 template < class PreviousData >
61 using channel_data_t = PreviousData;
62
63 struct meta_type :
64 bluetoe::details::signaling_channel_meta_type,
65 bluetoe::link_layer::details::valid_link_layer_option_meta_type {};
67 private:
68 void reject_command( const std::uint8_t* input, std::size_t in_size, std::uint8_t* output, std::size_t& out_size );
69
70 static constexpr std::uint8_t command_reject_code = 0x01;
71 static constexpr std::uint8_t connection_parameter_update_request_code = 0x12;
72 static constexpr std::uint8_t connection_parameter_update_response_code = 0x13;
73
74 std::uint16_t interval_min_;
75 std::uint16_t interval_max_;
76 std::uint16_t latency_;
77 std::uint16_t timeout_;
78
79 enum {
80 idle,
81 queued,
82 transmitted
83 } pending_status_;
84
85 static constexpr std::uint8_t invalid_identifier = 0x00;
86 std::uint8_t identifier_;
87 };
88
93 {
94 public:
98 template < typename ConnectionData >
99 void l2cap_input( const std::uint8_t*, std::size_t, std::uint8_t*, std::size_t& out_size, ConnectionData& )
100 {
101 out_size = 0;
102 }
103
107 template < typename ConnectionData >
108 void l2cap_output( std::uint8_t*, std::size_t& out_size, ConnectionData& )
109 {
110 out_size = 0;
111 }
112
116 bool connection_parameter_update_request( std::uint16_t, std::uint16_t, std::uint16_t, std::uint16_t )
117 {
118 return false;
119 }
120
124 constexpr std::size_t channel_mtu_size() const
125 {
126 return bluetoe::details::default_att_mtu_size;
127 }
128
130 static constexpr std::uint16_t channel_id = l2cap_channel_ids::signaling;
131 static constexpr std::size_t minimum_channel_mtu_size = 0;
132 static constexpr std::size_t maximum_channel_mtu_size = 0;
133
134 template < class PreviousData >
135 using channel_data_t = PreviousData;
136
137 typedef bluetoe::details::signaling_channel_meta_type meta_type;
139 };
140
141 template < typename ... Options >
142 signaling_channel< Options... >::signaling_channel()
143 : pending_status_( idle )
144 , identifier_( 0x01 )
145 {
146 }
147
148 template < typename ... Options >
149 template < typename ConnectionData >
150 void signaling_channel< Options... >::l2cap_input( const std::uint8_t* input, std::size_t in_size, std::uint8_t* output, std::size_t& out_size, ConnectionData& )
151 {
152 const std::uint8_t code = in_size > 0 ? input[ 0 ] : 0;
153
154 if ( code == connection_parameter_update_response_code && pending_status_ == transmitted )
155 {
156 pending_status_ = idle;
157 identifier_ = static_cast< std::uint8_t >( identifier_ + 1 );
158
159 if ( identifier_ == invalid_identifier )
160 identifier_ = static_cast< std::uint8_t >( identifier_ + 1 );
161
162 out_size = 0;
163 }
164 else
165 {
166 reject_command( input, in_size, output, out_size );
167 }
168 }
169
170 template < typename ... Options >
171 template < typename ConnectionData >
172 void signaling_channel< Options... >::l2cap_output( std::uint8_t* output, std::size_t& out_size, ConnectionData& )
173 {
174 static constexpr std::size_t pdu_size = 8 + 4;
175 assert( out_size >= pdu_size );
176
177 if ( pending_status_ == queued )
178 {
179 pending_status_ = transmitted;
180
181 out_size = pdu_size;
182 output[ 0 ] = connection_parameter_update_request_code;
183 output[ 1 ] = identifier_;
184 output[ 2 ] = pdu_size - 4;
185 output[ 3 ] = 0;
186 output[ 4 ] = static_cast< std::uint8_t >( interval_min_ );
187 output[ 5 ] = static_cast< std::uint8_t >( interval_min_ >> 8 );
188 output[ 6 ] = static_cast< std::uint8_t >( interval_max_ );
189 output[ 7 ] = static_cast< std::uint8_t >( interval_max_ >> 8 );
190 output[ 8 ] = static_cast< std::uint8_t >( latency_ );
191 output[ 9 ] = static_cast< std::uint8_t >( latency_ >> 8 );
192 output[ 10 ] = static_cast< std::uint8_t >( timeout_ );
193 output[ 11 ] = static_cast< std::uint8_t >( timeout_ >> 8 );
194 }
195 else
196 {
197 out_size = 0;
198 }
199 }
200
201 template < typename ... Options >
202 bool signaling_channel< Options... >::connection_parameter_update_request( std::uint16_t interval_min, std::uint16_t interval_max, std::uint16_t latency, std::uint16_t timeout )
203 {
204 if ( pending_status_ == idle )
205 {
206 interval_min_ = interval_min;
207 interval_max_ = interval_max;
208 latency_ = latency;
209 timeout_ = timeout;
210
211 pending_status_ = queued;
212 return true;
213 }
214
215 return false;
216 }
217
218 template < typename ... Options >
220 {
221 return bluetoe::details::default_att_mtu_size;
222 }
223
224 template < typename ... Options >
225 void signaling_channel< Options... >::reject_command( const std::uint8_t* input, std::size_t in_size, std::uint8_t* output, std::size_t& out_size )
226 {
227 static constexpr std::size_t pdu_size = 6;
228 static constexpr std::uint16_t command_not_understood = 0;
229 assert( out_size >= pdu_size );
230 out_size = 0;
231
232 if ( in_size < 2 )
233 return;
234
235 const std::uint8_t identifier = input[ 1 ];
236
237 if ( identifier == invalid_identifier )
238 return;
239
240 out_size = pdu_size;
241 output[ 0 ] = command_reject_code;
242 output[ 1 ] = identifier;
243 output[ 2 ] = 2; // length
244 output[ 3 ] = 0; // length
245 output[ 4 ] = static_cast< std::uint8_t >( command_not_understood );
246 output[ 5 ] = static_cast< std::uint8_t >( command_not_understood >> 8 );
247 }
248}
249}
250
251#endif
signaling channel implementations that does simply nothing
Definition: l2cap_signaling_channel.hpp:93
bool connection_parameter_update_request(std::uint16_t, std::uint16_t, std::uint16_t, std::uint16_t)
queues a connection parameter update request.
Definition: l2cap_signaling_channel.hpp:116
void l2cap_output(std::uint8_t *, std::size_t &out_size, ConnectionData &)
output to the l2cap layer
Definition: l2cap_signaling_channel.hpp:108
constexpr std::size_t channel_mtu_size() const
supported MTU size
Definition: l2cap_signaling_channel.hpp:124
void l2cap_input(const std::uint8_t *, std::size_t, std::uint8_t *, std::size_t &out_size, ConnectionData &)
input from the l2cap layer
Definition: l2cap_signaling_channel.hpp:99
very basic l2cap signaling channel implementation
Definition: l2cap_signaling_channel.hpp:26
constexpr std::size_t channel_mtu_size() const
supported MTU size
Definition: l2cap_signaling_channel.hpp:219
void l2cap_input(const std::uint8_t *input, std::size_t in_size, std::uint8_t *output, std::size_t &out_size, ConnectionData &)
input from the l2cap layer
Definition: l2cap_signaling_channel.hpp:150
void l2cap_output(std::uint8_t *output, std::size_t &out_size, ConnectionData &)
output to the l2cap layer
Definition: l2cap_signaling_channel.hpp:172
bool connection_parameter_update_request(std::uint16_t interval_min, std::uint16_t interval_max, std::uint16_t latency, std::uint16_t timeout)
queues a connection parameter update request.
Definition: l2cap_signaling_channel.hpp:202