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