Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/netgraph/bluetooth/l2cap/ng_l2cap_cmds.h
34814 views
1
/*
2
* ng_l2cap_cmds.h
3
*/
4
5
/*-
6
* SPDX-License-Identifier: BSD-2-Clause
7
*
8
* Copyright (c) Maksim Yevmenkin <[email protected]>
9
* All rights reserved.
10
*
11
* Redistribution and use in source and binary forms, with or without
12
* modification, are permitted provided that the following conditions
13
* are met:
14
* 1. Redistributions of source code must retain the above copyright
15
* notice, this list of conditions and the following disclaimer.
16
* 2. Redistributions in binary form must reproduce the above copyright
17
* notice, this list of conditions and the following disclaimer in the
18
* documentation and/or other materials provided with the distribution.
19
*
20
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
* SUCH DAMAGE.
31
*
32
* $Id: ng_l2cap_cmds.h,v 1.4 2003/04/01 18:15:26 max Exp $
33
*/
34
35
#ifndef _NETGRAPH_L2CAP_CMDS_H_
36
#define _NETGRAPH_L2CAP_CMDS_H_
37
38
/******************************************************************************
39
******************************************************************************
40
** L2CAP to L2CAP signaling command macros
41
******************************************************************************
42
******************************************************************************/
43
44
/*
45
* Note: All L2CAP implementations are required to support minimal signaling
46
* MTU of 48 bytes. In order to simplify things we will send one command
47
* per one L2CAP packet. Given evrything above we can assume that one
48
* signaling packet will fit into single mbuf.
49
*/
50
51
/* L2CAP_CommandRej */
52
#define _ng_l2cap_cmd_rej(_m, _ident, _reason, _mtu, _scid, _dcid) \
53
do { \
54
struct _cmd_rej { \
55
ng_l2cap_cmd_hdr_t hdr; \
56
ng_l2cap_cmd_rej_cp param; \
57
ng_l2cap_cmd_rej_data_t data; \
58
} __attribute__ ((packed)) *c = NULL; \
59
\
60
MGETHDR((_m), M_NOWAIT, MT_DATA); \
61
if ((_m) == NULL) \
62
break; \
63
\
64
c = mtod((_m), struct _cmd_rej *); \
65
c->hdr.code = NG_L2CAP_CMD_REJ; \
66
c->hdr.ident = (_ident); \
67
c->hdr.length = sizeof(c->param); \
68
\
69
c->param.reason = htole16((_reason)); \
70
\
71
if ((_reason) == NG_L2CAP_REJ_MTU_EXCEEDED) { \
72
c->data.mtu.mtu = htole16((_mtu)); \
73
c->hdr.length += sizeof(c->data.mtu); \
74
} else if ((_reason) == NG_L2CAP_REJ_INVALID_CID) { \
75
c->data.cid.scid = htole16((_scid)); \
76
c->data.cid.dcid = htole16((_dcid)); \
77
c->hdr.length += sizeof(c->data.cid); \
78
} \
79
\
80
(_m)->m_pkthdr.len = (_m)->m_len = sizeof(c->hdr) + \
81
c->hdr.length; \
82
\
83
c->hdr.length = htole16(c->hdr.length); \
84
} while (0)
85
86
/* L2CAP_ConnectReq */
87
#define _ng_l2cap_con_req(_m, _ident, _psm, _scid) \
88
do { \
89
struct _con_req { \
90
ng_l2cap_cmd_hdr_t hdr; \
91
ng_l2cap_con_req_cp param; \
92
} __attribute__ ((packed)) *c = NULL; \
93
\
94
MGETHDR((_m), M_NOWAIT, MT_DATA); \
95
if ((_m) == NULL) \
96
break; \
97
\
98
(_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \
99
\
100
c = mtod((_m), struct _con_req *); \
101
c->hdr.code = NG_L2CAP_CON_REQ; \
102
c->hdr.ident = (_ident); \
103
c->hdr.length = htole16(sizeof(c->param)); \
104
\
105
c->param.psm = htole16((_psm)); \
106
c->param.scid = htole16((_scid)); \
107
} while (0)
108
109
/* L2CAP_ConnectRsp */
110
#define _ng_l2cap_con_rsp(_m, _ident, _dcid, _scid, _result, _status) \
111
do { \
112
struct _con_rsp { \
113
ng_l2cap_cmd_hdr_t hdr; \
114
ng_l2cap_con_rsp_cp param; \
115
} __attribute__ ((packed)) *c = NULL; \
116
\
117
MGETHDR((_m), M_NOWAIT, MT_DATA); \
118
if ((_m) == NULL) \
119
break; \
120
\
121
(_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \
122
\
123
c = mtod((_m), struct _con_rsp *); \
124
c->hdr.code = NG_L2CAP_CON_RSP; \
125
c->hdr.ident = (_ident); \
126
c->hdr.length = htole16(sizeof(c->param)); \
127
\
128
c->param.dcid = htole16((_dcid)); \
129
c->param.scid = htole16((_scid)); \
130
c->param.result = htole16((_result)); \
131
c->param.status = htole16((_status)); \
132
} while (0)
133
134
/* L2CAP_ConfigReq */
135
#define _ng_l2cap_cfg_req(_m, _ident, _dcid, _flags, _data) \
136
do { \
137
struct _cfg_req { \
138
ng_l2cap_cmd_hdr_t hdr; \
139
ng_l2cap_cfg_req_cp param; \
140
} __attribute__ ((packed)) *c = NULL; \
141
\
142
MGETHDR((_m), M_NOWAIT, MT_DATA); \
143
if ((_m) == NULL) { \
144
NG_FREE_M((_data)); \
145
break; \
146
} \
147
\
148
(_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \
149
\
150
c = mtod((_m), struct _cfg_req *); \
151
c->hdr.code = NG_L2CAP_CFG_REQ; \
152
c->hdr.ident = (_ident); \
153
c->hdr.length = sizeof(c->param); \
154
\
155
c->param.dcid = htole16((_dcid)); \
156
c->param.flags = htole16((_flags)); \
157
if ((_data) != NULL) { \
158
int l = (_data)->m_pkthdr.len; \
159
\
160
m_cat((_m), (_data)); \
161
c->hdr.length += l; \
162
(_m)->m_pkthdr.len += l; \
163
} \
164
\
165
c->hdr.length = htole16(c->hdr.length); \
166
} while (0)
167
168
/* L2CAP_ConfigRsp */
169
#define _ng_l2cap_cfg_rsp(_m, _ident, _scid, _flags, _result, _data) \
170
do { \
171
struct _cfg_rsp { \
172
ng_l2cap_cmd_hdr_t hdr; \
173
ng_l2cap_cfg_rsp_cp param; \
174
} __attribute__ ((packed)) *c = NULL; \
175
\
176
MGETHDR((_m), M_NOWAIT, MT_DATA); \
177
if ((_m) == NULL) { \
178
NG_FREE_M((_data)); \
179
break; \
180
} \
181
\
182
(_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \
183
\
184
c = mtod((_m), struct _cfg_rsp *); \
185
c->hdr.code = NG_L2CAP_CFG_RSP; \
186
c->hdr.ident = (_ident); \
187
c->hdr.length = sizeof(c->param); \
188
\
189
c->param.scid = htole16((_scid)); \
190
c->param.flags = htole16((_flags)); \
191
c->param.result = htole16((_result)); \
192
if ((_data) != NULL) { \
193
int l = (_data)->m_pkthdr.len; \
194
\
195
m_cat((_m), (_data)); \
196
c->hdr.length += l; \
197
(_m)->m_pkthdr.len += l; \
198
} \
199
\
200
c->hdr.length = htole16(c->hdr.length); \
201
} while (0)
202
203
#define _ng_l2cap_cmd_urs(_m, _ident, _result) \
204
do { \
205
struct _cmd_urs{ \
206
ng_l2cap_cmd_hdr_t hdr; \
207
uint16_t result; \
208
} __attribute__ ((packed)) *c = NULL; \
209
\
210
MGETHDR((_m), M_NOWAIT, MT_DATA); \
211
\
212
(_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \
213
\
214
c = mtod((_m), struct _cmd_urs *); \
215
c->hdr.code = NG_L2CAP_CMD_PARAM_UPDATE_RESPONSE; \
216
c->hdr.ident = (_ident); \
217
c->hdr.length = sizeof(c->result); \
218
\
219
c->result = htole16((_result)); \
220
} while (0)
221
222
/* Build configuration options */
223
#define _ng_l2cap_build_cfg_options(_m, _mtu, _flush_timo, _flow) \
224
do { \
225
u_int8_t *p = NULL; \
226
\
227
MGETHDR((_m), M_NOWAIT, MT_DATA); \
228
if ((_m) == NULL) \
229
break; \
230
\
231
(_m)->m_pkthdr.len = (_m)->m_len = 0; \
232
p = mtod((_m), u_int8_t *); \
233
\
234
if ((_mtu) != NULL) { \
235
struct _cfg_opt_mtu { \
236
ng_l2cap_cfg_opt_t hdr; \
237
u_int16_t val; \
238
} __attribute__ ((packed)) *o = NULL; \
239
\
240
o = (struct _cfg_opt_mtu *) p; \
241
o->hdr.type = NG_L2CAP_OPT_MTU; \
242
o->hdr.length = sizeof(o->val); \
243
o->val = htole16(*(u_int16_t *)(_mtu)); \
244
\
245
(_m)->m_pkthdr.len += sizeof(*o); \
246
p += sizeof(*o); \
247
} \
248
\
249
if ((_flush_timo) != NULL) { \
250
struct _cfg_opt_flush { \
251
ng_l2cap_cfg_opt_t hdr; \
252
u_int16_t val; \
253
} __attribute__ ((packed)) *o = NULL; \
254
\
255
o = (struct _cfg_opt_flush *) p; \
256
o->hdr.type = NG_L2CAP_OPT_FLUSH_TIMO; \
257
o->hdr.length = sizeof(o->val); \
258
o->val = htole16(*(u_int16_t *)(_flush_timo)); \
259
\
260
(_m)->m_pkthdr.len += sizeof(*o); \
261
p += sizeof(*o); \
262
} \
263
\
264
if ((_flow) != NULL) { \
265
struct _cfg_opt_flow { \
266
ng_l2cap_cfg_opt_t hdr; \
267
ng_l2cap_flow_t val; \
268
} __attribute__ ((packed)) *o = NULL; \
269
\
270
o = (struct _cfg_opt_flow *) p; \
271
o->hdr.type = NG_L2CAP_OPT_QOS; \
272
o->hdr.length = sizeof(o->val); \
273
o->val.flags = ((ng_l2cap_flow_p)(_flow))->flags; \
274
o->val.service_type = ((ng_l2cap_flow_p) \
275
(_flow))->service_type; \
276
o->val.token_rate = \
277
htole32(((ng_l2cap_flow_p)(_flow))->token_rate);\
278
o->val.token_bucket_size = \
279
htole32(((ng_l2cap_flow_p) \
280
(_flow))->token_bucket_size); \
281
o->val.peak_bandwidth = \
282
htole32(((ng_l2cap_flow_p) \
283
(_flow))->peak_bandwidth); \
284
o->val.latency = htole32(((ng_l2cap_flow_p) \
285
(_flow))->latency); \
286
o->val.delay_variation = \
287
htole32(((ng_l2cap_flow_p) \
288
(_flow))->delay_variation); \
289
\
290
(_m)->m_pkthdr.len += sizeof(*o); \
291
} \
292
\
293
(_m)->m_len = (_m)->m_pkthdr.len; \
294
} while (0)
295
296
/* L2CAP_DisconnectReq */
297
#define _ng_l2cap_discon_req(_m, _ident, _dcid, _scid) \
298
do { \
299
struct _discon_req { \
300
ng_l2cap_cmd_hdr_t hdr; \
301
ng_l2cap_discon_req_cp param; \
302
} __attribute__ ((packed)) *c = NULL; \
303
\
304
MGETHDR((_m), M_NOWAIT, MT_DATA); \
305
if ((_m) == NULL) \
306
break; \
307
\
308
(_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \
309
\
310
c = mtod((_m), struct _discon_req *); \
311
c->hdr.code = NG_L2CAP_DISCON_REQ; \
312
c->hdr.ident = (_ident); \
313
c->hdr.length = htole16(sizeof(c->param)); \
314
\
315
c->param.dcid = htole16((_dcid)); \
316
c->param.scid = htole16((_scid)); \
317
} while (0)
318
319
/* L2CA_DisconnectRsp */
320
#define _ng_l2cap_discon_rsp(_m, _ident, _dcid, _scid) \
321
do { \
322
struct _discon_rsp { \
323
ng_l2cap_cmd_hdr_t hdr; \
324
ng_l2cap_discon_rsp_cp param; \
325
} __attribute__ ((packed)) *c = NULL; \
326
\
327
MGETHDR((_m), M_NOWAIT, MT_DATA); \
328
if ((_m) == NULL) \
329
break; \
330
\
331
(_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \
332
\
333
c = mtod((_m), struct _discon_rsp *); \
334
c->hdr.code = NG_L2CAP_DISCON_RSP; \
335
c->hdr.ident = (_ident); \
336
c->hdr.length = htole16(sizeof(c->param)); \
337
\
338
c->param.dcid = htole16((_dcid)); \
339
c->param.scid = htole16((_scid)); \
340
} while (0)
341
342
/* L2CAP_EchoReq */
343
#define _ng_l2cap_echo_req(_m, _ident, _data, _size) \
344
do { \
345
ng_l2cap_cmd_hdr_t *c = NULL; \
346
\
347
MGETHDR((_m), M_NOWAIT, MT_DATA); \
348
if ((_m) == NULL) \
349
break; \
350
\
351
(_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \
352
\
353
c = mtod((_m), ng_l2cap_cmd_hdr_t *); \
354
c->code = NG_L2CAP_ECHO_REQ; \
355
c->ident = (_ident); \
356
c->length = 0; \
357
\
358
if ((_data) != NULL) { \
359
m_copyback((_m), sizeof(*c), (_size), (_data)); \
360
c->length += (_size); \
361
} \
362
\
363
c->length = htole16(c->length); \
364
} while (0)
365
366
/* L2CAP_InfoReq */
367
#define _ng_l2cap_info_req(_m, _ident, _type) \
368
do { \
369
struct _info_req { \
370
ng_l2cap_cmd_hdr_t hdr; \
371
ng_l2cap_info_req_cp param; \
372
} __attribute__ ((packed)) *c = NULL; \
373
\
374
MGETHDR((_m), M_NOWAIT, MT_DATA); \
375
if ((_m) == NULL) \
376
break; \
377
\
378
(_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \
379
\
380
c = mtod((_m), struct _info_req *); \
381
c->hdr.code = NG_L2CAP_INFO_REQ; \
382
c->hdr.ident = (_ident); \
383
c->hdr.length = htole16(sizeof(c->param)); \
384
\
385
c->param.type = htole16((_type)); \
386
} while (0)
387
388
/* L2CAP_InfoRsp */
389
#define _ng_l2cap_info_rsp(_m, _ident, _type, _result, _mtu) \
390
do { \
391
struct _info_rsp { \
392
ng_l2cap_cmd_hdr_t hdr; \
393
ng_l2cap_info_rsp_cp param; \
394
ng_l2cap_info_rsp_data_t data; \
395
} __attribute__ ((packed)) *c = NULL; \
396
\
397
MGETHDR((_m), M_NOWAIT, MT_DATA); \
398
if ((_m) == NULL) \
399
break; \
400
\
401
c = mtod((_m), struct _info_rsp *); \
402
c->hdr.code = NG_L2CAP_INFO_RSP; \
403
c->hdr.ident = (_ident); \
404
c->hdr.length = sizeof(c->param); \
405
\
406
c->param.type = htole16((_type)); \
407
c->param.result = htole16((_result)); \
408
\
409
if ((_result) == NG_L2CAP_SUCCESS) { \
410
switch ((_type)) { \
411
case NG_L2CAP_CONNLESS_MTU: \
412
c->data.mtu.mtu = htole16((_mtu)); \
413
c->hdr.length += sizeof((c->data.mtu.mtu)); \
414
break; \
415
} \
416
} \
417
\
418
(_m)->m_pkthdr.len = (_m)->m_len = sizeof(c->hdr) + \
419
c->hdr.length; \
420
\
421
c->hdr.length = htole16(c->hdr.length); \
422
} while (0)
423
424
void ng_l2cap_con_wakeup (ng_l2cap_con_p);
425
void ng_l2cap_con_fail (ng_l2cap_con_p, u_int16_t);
426
void ng_l2cap_process_command_timeout (node_p, hook_p, void *, int);
427
428
#endif /* ndef _NETGRAPH_L2CAP_CMDS_H_ */
429
430