/* * ng_l2cap_cmds.h */ /*- * Copyright (c) Maksim Yevmenkin * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: ng_l2cap_cmds.h,v 1.4 2003/04/01 18:15:26 max Exp $ * $FreeBSD: src/sys/netgraph/bluetooth/l2cap/ng_l2cap_cmds.h,v 1.5 2005/01/07 01:45:43 imp Exp $ */ #ifndef _NETGRAPH_L2CAP_CMDS_H_ #define _NETGRAPH_L2CAP_CMDS_H_ /****************************************************************************** ****************************************************************************** ** L2CAP to L2CAP signaling command macros ****************************************************************************** ******************************************************************************/ /* * Note: All L2CAP implementations are required to support minimal signaling * MTU of 48 bytes. In order to simplify things we will send one command * per one L2CAP packet. Given evrything above we can assume that one * signaling packet will fit into single mbuf. */ /* L2CAP_CommandRej */ #define _ng_l2cap_cmd_rej(_m, _ident, _reason, _mtu, _scid, _dcid) \ do { \ struct _cmd_rej { \ ng_l2cap_cmd_hdr_t hdr; \ ng_l2cap_cmd_rej_cp param; \ ng_l2cap_cmd_rej_data_t data; \ } __attribute__ ((packed)) *c = NULL; \ \ MGETHDR((_m), M_NOWAIT, MT_DATA); \ if ((_m) == NULL) \ break; \ \ c = mtod((_m), struct _cmd_rej *); \ c->hdr.code = NG_L2CAP_CMD_REJ; \ c->hdr.ident = (_ident); \ c->hdr.length = sizeof(c->param); \ \ c->param.reason = htole16((_reason)); \ \ if ((_reason) == NG_L2CAP_REJ_MTU_EXCEEDED) { \ c->data.mtu.mtu = htole16((_mtu)); \ c->hdr.length += sizeof(c->data.mtu); \ } else if ((_reason) == NG_L2CAP_REJ_INVALID_CID) { \ c->data.cid.scid = htole16((_scid)); \ c->data.cid.dcid = htole16((_dcid)); \ c->hdr.length += sizeof(c->data.cid); \ } \ \ (_m)->m_pkthdr.len = (_m)->m_len = sizeof(c->hdr) + \ c->hdr.length; \ \ c->hdr.length = htole16(c->hdr.length); \ } while (0) /* L2CAP_ConnectReq */ #define _ng_l2cap_con_req(_m, _ident, _psm, _scid) \ do { \ struct _con_req { \ ng_l2cap_cmd_hdr_t hdr; \ ng_l2cap_con_req_cp param; \ } __attribute__ ((packed)) *c = NULL; \ \ MGETHDR((_m), M_NOWAIT, MT_DATA); \ if ((_m) == NULL) \ break; \ \ (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \ \ c = mtod((_m), struct _con_req *); \ c->hdr.code = NG_L2CAP_CON_REQ; \ c->hdr.ident = (_ident); \ c->hdr.length = htole16(sizeof(c->param)); \ \ c->param.psm = htole16((_psm)); \ c->param.scid = htole16((_scid)); \ } while (0) /* L2CAP_ConnectRsp */ #define _ng_l2cap_con_rsp(_m, _ident, _dcid, _scid, _result, _status) \ do { \ struct _con_rsp { \ ng_l2cap_cmd_hdr_t hdr; \ ng_l2cap_con_rsp_cp param; \ } __attribute__ ((packed)) *c = NULL; \ \ MGETHDR((_m), M_NOWAIT, MT_DATA); \ if ((_m) == NULL) \ break; \ \ (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \ \ c = mtod((_m), struct _con_rsp *); \ c->hdr.code = NG_L2CAP_CON_RSP; \ c->hdr.ident = (_ident); \ c->hdr.length = htole16(sizeof(c->param)); \ \ c->param.dcid = htole16((_dcid)); \ c->param.scid = htole16((_scid)); \ c->param.result = htole16((_result)); \ c->param.status = htole16((_status)); \ } while (0) /* L2CAP_ConfigReq */ #define _ng_l2cap_cfg_req(_m, _ident, _dcid, _flags, _data) \ do { \ struct _cfg_req { \ ng_l2cap_cmd_hdr_t hdr; \ ng_l2cap_cfg_req_cp param; \ } __attribute__ ((packed)) *c = NULL; \ \ MGETHDR((_m), M_NOWAIT, MT_DATA); \ if ((_m) == NULL) { \ NG_FREE_M((_data)); \ break; \ } \ \ (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \ \ c = mtod((_m), struct _cfg_req *); \ c->hdr.code = NG_L2CAP_CFG_REQ; \ c->hdr.ident = (_ident); \ c->hdr.length = sizeof(c->param); \ \ c->param.dcid = htole16((_dcid)); \ c->param.flags = htole16((_flags)); \ if ((_data) != NULL) { \ int l = (_data)->m_pkthdr.len; \ \ m_cat((_m), (_data)); \ c->hdr.length += l; \ (_m)->m_pkthdr.len += l; \ } \ \ c->hdr.length = htole16(c->hdr.length); \ } while (0) /* L2CAP_ConfigRsp */ #define _ng_l2cap_cfg_rsp(_m, _ident, _scid, _flags, _result, _data) \ do { \ struct _cfg_rsp { \ ng_l2cap_cmd_hdr_t hdr; \ ng_l2cap_cfg_rsp_cp param; \ } __attribute__ ((packed)) *c = NULL; \ \ MGETHDR((_m), M_NOWAIT, MT_DATA); \ if ((_m) == NULL) { \ NG_FREE_M((_data)); \ break; \ } \ \ (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \ \ c = mtod((_m), struct _cfg_rsp *); \ c->hdr.code = NG_L2CAP_CFG_RSP; \ c->hdr.ident = (_ident); \ c->hdr.length = sizeof(c->param); \ \ c->param.scid = htole16((_scid)); \ c->param.flags = htole16((_flags)); \ c->param.result = htole16((_result)); \ if ((_data) != NULL) { \ int l = (_data)->m_pkthdr.len; \ \ m_cat((_m), (_data)); \ c->hdr.length += l; \ (_m)->m_pkthdr.len += l; \ } \ \ c->hdr.length = htole16(c->hdr.length); \ } while (0) /* Build configuration options */ #define _ng_l2cap_build_cfg_options(_m, _mtu, _flush_timo, _flow) \ do { \ u_int8_t *p = NULL; \ \ MGETHDR((_m), M_NOWAIT, MT_DATA); \ if ((_m) == NULL) \ break; \ \ (_m)->m_pkthdr.len = (_m)->m_len = 0; \ p = mtod((_m), u_int8_t *); \ \ if ((_mtu) != NULL) { \ struct _cfg_opt_mtu { \ ng_l2cap_cfg_opt_t hdr; \ u_int16_t val; \ } __attribute__ ((packed)) *o = NULL; \ \ o = (struct _cfg_opt_mtu *) p; \ o->hdr.type = NG_L2CAP_OPT_MTU; \ o->hdr.length = sizeof(o->val); \ o->val = htole16(*(u_int16_t *)(_mtu)); \ \ (_m)->m_pkthdr.len += sizeof(*o); \ p += sizeof(*o); \ } \ \ if ((_flush_timo) != NULL) { \ struct _cfg_opt_flush { \ ng_l2cap_cfg_opt_t hdr; \ u_int16_t val; \ } __attribute__ ((packed)) *o = NULL; \ \ o = (struct _cfg_opt_flush *) p; \ o->hdr.type = NG_L2CAP_OPT_FLUSH_TIMO; \ o->hdr.length = sizeof(o->val); \ o->val = htole16(*(u_int16_t *)(_flush_timo)); \ \ (_m)->m_pkthdr.len += sizeof(*o); \ p += sizeof(*o); \ } \ \ if ((_flow) != NULL) { \ struct _cfg_opt_flow { \ ng_l2cap_cfg_opt_t hdr; \ ng_l2cap_flow_t val; \ } __attribute__ ((packed)) *o = NULL; \ \ o = (struct _cfg_opt_flow *) p; \ o->hdr.type = NG_L2CAP_OPT_QOS; \ o->hdr.length = sizeof(o->val); \ o->val.flags = ((ng_l2cap_flow_p)(_flow))->flags; \ o->val.service_type = ((ng_l2cap_flow_p) \ (_flow))->service_type; \ o->val.token_rate = \ htole32(((ng_l2cap_flow_p)(_flow))->token_rate);\ o->val.token_bucket_size = \ htole32(((ng_l2cap_flow_p) \ (_flow))->token_bucket_size); \ o->val.peak_bandwidth = \ htole32(((ng_l2cap_flow_p) \ (_flow))->peak_bandwidth); \ o->val.latency = htole32(((ng_l2cap_flow_p) \ (_flow))->latency); \ o->val.delay_variation = \ htole32(((ng_l2cap_flow_p) \ (_flow))->delay_variation); \ \ (_m)->m_pkthdr.len += sizeof(*o); \ } \ \ (_m)->m_len = (_m)->m_pkthdr.len; \ } while (0) /* L2CAP_DisconnectReq */ #define _ng_l2cap_discon_req(_m, _ident, _dcid, _scid) \ do { \ struct _discon_req { \ ng_l2cap_cmd_hdr_t hdr; \ ng_l2cap_discon_req_cp param; \ } __attribute__ ((packed)) *c = NULL; \ \ MGETHDR((_m), M_NOWAIT, MT_DATA); \ if ((_m) == NULL) \ break; \ \ (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \ \ c = mtod((_m), struct _discon_req *); \ c->hdr.code = NG_L2CAP_DISCON_REQ; \ c->hdr.ident = (_ident); \ c->hdr.length = htole16(sizeof(c->param)); \ \ c->param.dcid = htole16((_dcid)); \ c->param.scid = htole16((_scid)); \ } while (0) /* L2CA_DisconnectRsp */ #define _ng_l2cap_discon_rsp(_m, _ident, _dcid, _scid) \ do { \ struct _discon_rsp { \ ng_l2cap_cmd_hdr_t hdr; \ ng_l2cap_discon_rsp_cp param; \ } __attribute__ ((packed)) *c = NULL; \ \ MGETHDR((_m), M_NOWAIT, MT_DATA); \ if ((_m) == NULL) \ break; \ \ (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \ \ c = mtod((_m), struct _discon_rsp *); \ c->hdr.code = NG_L2CAP_DISCON_RSP; \ c->hdr.ident = (_ident); \ c->hdr.length = htole16(sizeof(c->param)); \ \ c->param.dcid = htole16((_dcid)); \ c->param.scid = htole16((_scid)); \ } while (0) /* L2CAP_EchoReq */ #define _ng_l2cap_echo_req(_m, _ident, _data, _size) \ do { \ ng_l2cap_cmd_hdr_t *c = NULL; \ \ MGETHDR((_m), M_NOWAIT, MT_DATA); \ if ((_m) == NULL) \ break; \ \ (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \ \ c = mtod((_m), ng_l2cap_cmd_hdr_t *); \ c->code = NG_L2CAP_ECHO_REQ; \ c->ident = (_ident); \ c->length = 0; \ \ if ((_data) != NULL) { \ m_copyback((_m), sizeof(*c), (_size), (_data)); \ c->length += (_size); \ } \ \ c->length = htole16(c->length); \ } while (0) /* L2CAP_InfoReq */ #define _ng_l2cap_info_req(_m, _ident, _type) \ do { \ struct _info_req { \ ng_l2cap_cmd_hdr_t hdr; \ ng_l2cap_info_req_cp param; \ } __attribute__ ((packed)) *c = NULL; \ \ MGETHDR((_m), M_NOWAIT, MT_DATA); \ if ((_m) == NULL) \ break; \ \ (_m)->m_pkthdr.len = (_m)->m_len = sizeof(*c); \ \ c = mtod((_m), struct _info_req *); \ c->hdr.code = NG_L2CAP_INFO_REQ; \ c->hdr.ident = (_ident); \ c->hdr.length = htole16(sizeof(c->param)); \ \ c->param.type = htole16((_type)); \ } while (0) /* L2CAP_InfoRsp */ #define _ng_l2cap_info_rsp(_m, _ident, _type, _result, _mtu) \ do { \ struct _info_rsp { \ ng_l2cap_cmd_hdr_t hdr; \ ng_l2cap_info_rsp_cp param; \ ng_l2cap_info_rsp_data_t data; \ } __attribute__ ((packed)) *c = NULL; \ \ MGETHDR((_m), M_NOWAIT, MT_DATA); \ if ((_m) == NULL) \ break; \ \ c = mtod((_m), struct _info_rsp *); \ c->hdr.code = NG_L2CAP_INFO_REQ; \ c->hdr.ident = (_ident); \ c->hdr.length = sizeof(c->param); \ \ c->param.type = htole16((_type)); \ c->param.result = htole16((_result)); \ \ if ((_result) == NG_L2CAP_SUCCESS) { \ switch ((_type)) { \ case NG_L2CAP_CONNLESS_MTU: \ c->data.mtu.mtu = htole16((_mtu)); \ c->hdr.length += sizeof((c->data.mtu.mtu)); \ break; \ } \ } \ \ (_m)->m_pkthdr.len = (_m)->m_len = sizeof(c->hdr) + \ c->hdr.length; \ \ c->hdr.length = htole16(c->hdr.length); \ } while (0) void ng_l2cap_con_wakeup (ng_l2cap_con_p); void ng_l2cap_con_fail (ng_l2cap_con_p, u_int16_t); void ng_l2cap_process_command_timeout (node_p, hook_p, void *, int); #endif /* ndef _NETGRAPH_L2CAP_CMDS_H_ */