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