ng_l2cap_cmds.h revision 107120
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.9 2002/04/16 00:43:56 max Exp $
29 * $FreeBSD: head/sys/netgraph/bluetooth/l2cap/ng_l2cap_cmds.h 107120 2002-11-20 23:01:59Z julian $
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)	\
50do {									\
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)			\
85do {									\
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)	\
108do {									\
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)		\
133do {									\
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		m_cat((_m), (_data));					\
156		c->hdr.length += (_data)->m_pkthdr.len;			\
157		(_m)->m_pkthdr.len += (_data)->m_pkthdr.len;		\
158	}								\
159									\
160	c->hdr.length = htole16(c->hdr.length);				\
161} while (0)
162
163/* L2CAP_ConfigRsp */
164#define _ng_l2cap_cfg_rsp(_m, _ident, _scid, _flags, _result, _data)	\
165do {									\
166	struct _cfg_rsp {						\
167		ng_l2cap_cmd_hdr_t	 hdr;				\
168		ng_l2cap_cfg_rsp_cp	 param;				\
169	} __attribute__ ((packed))	*c = NULL;			\
170									\
171	MGETHDR((_m), M_DONTWAIT, MT_DATA);				\
172	if ((_m) == NULL) { 						\
173		NG_FREE_M((_data));					\
174		break;							\
175	}								\
176									\
177	(_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c);			\
178									\
179	c = mtod((_m), struct _cfg_rsp *);				\
180	c->hdr.code = NG_L2CAP_CFG_RSP;					\
181	c->hdr.ident = (_ident);					\
182	c->hdr.length = sizeof(c->param);				\
183									\
184	c->param.scid = htole16((_scid));				\
185	c->param.flags = htole16((_flags));				\
186	c->param.result = htole16((_result));				\
187	if ((_data) != NULL) {						\
188		m_cat((_m), (_data));					\
189		c->hdr.length += (_data)->m_pkthdr.len;			\
190		(_m)->m_pkthdr.len += (_data)->m_pkthdr.len;		\
191	}								\
192									\
193	c->hdr.length = htole16(c->hdr.length);				\
194} while (0)
195
196/* Build configuration options */
197#define _ng_l2cap_build_cfg_options(_m, _mtu, _flush_timo, _flow)	\
198do {									\
199	u_int8_t	*p = NULL;					\
200									\
201	MGETHDR((_m), M_DONTWAIT, MT_DATA);				\
202	if ((_m) == NULL)						\
203		break;							\
204									\
205	(_m)->m_pkthdr.len = (_m)->m_len = 0;				\
206	p = mtod((_m), u_int8_t *);					\
207									\
208	if ((_mtu) != NULL) {						\
209		struct _cfg_opt_mtu {					\
210			ng_l2cap_cfg_opt_t	 hdr;			\
211			u_int16_t		 val;			\
212		} __attribute__ ((packed))	*o = NULL;		\
213									\
214		o = (struct _cfg_opt_mtu *) p;				\
215		o->hdr.type = NG_L2CAP_OPT_MTU;				\
216		o->hdr.length = sizeof(o->val);				\
217		o->val = htole16(*(u_int16_t *)(_mtu));			\
218									\
219		(_m)->m_pkthdr.len += sizeof(*o);			\
220		p += sizeof(*o);					\
221	}								\
222									\
223	if ((_flush_timo) != NULL) {					\
224		struct _cfg_opt_flush {					\
225			ng_l2cap_cfg_opt_t	 hdr;			\
226			u_int16_t		 val;			\
227		} __attribute__ ((packed))	*o = NULL;		\
228									\
229		o = (struct _cfg_opt_flush *) p;			\
230		o->hdr.type = NG_L2CAP_OPT_FLUSH_TIMO;			\
231		o->hdr.length = sizeof(o->val);				\
232		o->val = htole16(*(u_int16_t *)(_flush_timo));		\
233									\
234		(_m)->m_pkthdr.len += sizeof(*o);			\
235		p += sizeof(*o);					\
236	}								\
237									\
238	if ((_flow) != NULL) {						\
239		struct _cfg_opt_flow {					\
240			ng_l2cap_cfg_opt_t	 hdr;			\
241			ng_l2cap_flow_t		 val;			\
242		} __attribute__ ((packed))	*o = NULL;		\
243									\
244		o = (struct _cfg_opt_flow *) p;				\
245		o->hdr.type = NG_L2CAP_OPT_QOS;				\
246		o->hdr.length = sizeof(o->val);				\
247		o->val.flags = ((ng_l2cap_flow_p)(_flow))->flags;	\
248		o->val.service_type = ((ng_l2cap_flow_p)		\
249				(_flow))->service_type;			\
250		o->val.token_rate =					\
251			htole32(((ng_l2cap_flow_p)(_flow))->token_rate);\
252		o->val.token_bucket_size =				\
253			htole32(((ng_l2cap_flow_p)			\
254				(_flow))->token_bucket_size);		\
255		o->val.peak_bandwidth = 				\
256			htole32(((ng_l2cap_flow_p)			\
257				(_flow))->peak_bandwidth);		\
258		o->val.latency = htole32(((ng_l2cap_flow_p)		\
259				(_flow))->latency);			\
260		o->val.delay_variation = 				\
261			htole32(((ng_l2cap_flow_p)			\
262				(_flow))->delay_variation);		\
263									\
264		(_m)->m_pkthdr.len += sizeof(*o);			\
265	}								\
266									\
267	(_m)->m_len = (_m)->m_pkthdr.len;				\
268} while (0)
269
270/* L2CAP_DisconnectReq */
271#define	_ng_l2cap_discon_req(_m, _ident, _dcid, _scid)			\
272do {									\
273	struct _discon_req {						\
274		ng_l2cap_cmd_hdr_t	 hdr;				\
275		ng_l2cap_discon_req_cp	 param;				\
276	} __attribute__ ((packed))	*c = NULL;			\
277									\
278	MGETHDR((_m), M_DONTWAIT, MT_DATA);				\
279	if ((_m) == NULL)						\
280		break;							\
281									\
282	(_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c);			\
283									\
284	c = mtod((_m), struct _discon_req *);				\
285	c->hdr.code = NG_L2CAP_DISCON_REQ;				\
286	c->hdr.ident = (_ident);					\
287	c->hdr.length = htole16(sizeof(c->param));			\
288									\
289	c->param.dcid = htole16((_dcid));				\
290	c->param.scid = htole16((_scid));				\
291} while (0)
292
293/* L2CA_DisconnectRsp */
294#define	_ng_l2cap_discon_rsp(_m, _ident, _dcid, _scid)			\
295do {									\
296	struct _discon_rsp {						\
297		ng_l2cap_cmd_hdr_t	 hdr;				\
298		ng_l2cap_discon_rsp_cp	 param;				\
299	} __attribute__ ((packed))	*c = NULL;			\
300									\
301	MGETHDR((_m), M_DONTWAIT, MT_DATA);				\
302	if ((_m) == NULL)						\
303		break;							\
304									\
305	(_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c);			\
306									\
307	c = mtod((_m), struct _discon_rsp *);				\
308	c->hdr.code = NG_L2CAP_DISCON_RSP;				\
309	c->hdr.ident = (_ident);					\
310	c->hdr.length = htole16(sizeof(c->param));			\
311									\
312	c->param.dcid = htole16((_dcid));				\
313	c->param.scid = htole16((_scid));				\
314} while (0)
315
316/* L2CAP_EchoReq */
317#define	_ng_l2cap_echo_req(_m, _ident, _data, _size)			\
318do {									\
319	ng_l2cap_cmd_hdr_t	*c = NULL;				\
320									\
321	MGETHDR((_m), M_DONTWAIT, MT_DATA);				\
322	if ((_m) == NULL) 						\
323		break;							\
324									\
325	(_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c);			\
326									\
327	c = mtod((_m), ng_l2cap_cmd_hdr_t *);				\
328	c->code = NG_L2CAP_ECHO_REQ;					\
329	c->ident = (_ident);						\
330	c->length = 0;							\
331									\
332	if ((_data) != NULL) {						\
333		m_copyback((_m), sizeof(*c), (_size), (_data));		\
334		c->length += (_size);					\
335	}								\
336									\
337	c->length = htole16(c->length);					\
338} while (0)
339
340/* L2CAP_InfoReq */
341#define	_ng_l2cap_info_req(_m, _ident, _type)				\
342do {									\
343	struct _info_req {						\
344		ng_l2cap_cmd_hdr_t	 hdr;				\
345		ng_l2cap_info_req_cp	 param;				\
346	} __attribute__ ((packed))	*c = NULL;			\
347									\
348	MGETHDR((_m), M_DONTWAIT, MT_DATA);				\
349	if ((_m) == NULL)						\
350		break;							\
351									\
352	(_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c);			\
353									\
354	c = mtod((_m), struct _info_req *);				\
355	c->hdr.code = NG_L2CAP_INFO_REQ;				\
356	c->hdr.ident = (_ident);					\
357	c->hdr.length = htole16(sizeof(c->param));			\
358									\
359	c->param.type = htole16((_type));				\
360} while (0)
361
362/* L2CAP_InfoRsp */
363#define	_ng_l2cap_info_rsp(_m, _ident, _type, _result, _mtu)		\
364do {									\
365	struct _info_rsp {						\
366		ng_l2cap_cmd_hdr_t	 hdr;				\
367		ng_l2cap_info_rsp_cp	 param;				\
368		ng_l2cap_info_rsp_data_t data;				\
369	} __attribute__ ((packed))	*c = NULL;			\
370									\
371	MGETHDR((_m), M_DONTWAIT, MT_DATA);				\
372	if ((_m) == NULL) 						\
373		break;							\
374									\
375	c = mtod((_m), struct _info_rsp *);				\
376	c->hdr.code = NG_L2CAP_INFO_REQ;				\
377	c->hdr.ident = (_ident);					\
378	c->hdr.length = sizeof(c->param);				\
379									\
380	c->param.type = htole16((_type));				\
381	c->param.result = htole16((_result));				\
382									\
383	if ((_result) == NG_L2CAP_SUCCESS) {				\
384		switch ((_type)) {					\
385		case NG_L2CAP_CONNLESS_MTU:				\
386			c->data.mtu.mtu = htole16((_mtu));		\
387			c->hdr.length += sizeof((c->data.mtu.mtu));	\
388			break;						\
389		}							\
390	}								\
391									\
392	(_m)->m_pkthdr.len = (_m)->m_len = sizeof(c->hdr) +		\
393					c->hdr.length;			\
394									\
395	c->hdr.length = htole16(c->hdr.length);		 		\
396} while (0)
397
398void ng_l2cap_con_wakeup              (ng_l2cap_con_p);
399void ng_l2cap_con_fail                (ng_l2cap_con_p, u_int16_t);
400void ng_l2cap_process_command_timeout (node_p, hook_p, void *, int);
401
402#endif /* ndef _NETGRAPH_L2CAP_CMDS_H_ */
403
404