6 * Copyright (c) Maksim Yevmenkin <m_evmenkin@yahoo.com>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * $Id: ng_l2cap_ulpi.c,v 1.1 2002/11/24 19:47:06 max Exp $
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/endian.h>
38 #include <sys/malloc.h>
40 #include <sys/queue.h>
41 #include <netgraph/ng_message.h>
42 #include <netgraph/netgraph.h>
43 #include <netgraph/bluetooth/include/ng_hci.h>
44 #include <netgraph/bluetooth/include/ng_l2cap.h>
45 #include <netgraph/bluetooth/l2cap/ng_l2cap_var.h>
46 #include <netgraph/bluetooth/l2cap/ng_l2cap_cmds.h>
47 #include <netgraph/bluetooth/l2cap/ng_l2cap_evnt.h>
48 #include <netgraph/bluetooth/l2cap/ng_l2cap_llpi.h>
49 #include <netgraph/bluetooth/l2cap/ng_l2cap_ulpi.h>
50 #include <netgraph/bluetooth/l2cap/ng_l2cap_misc.h>
52 /******************************************************************************
53 ******************************************************************************
54 ** Upper Layer Protocol Interface module
55 ******************************************************************************
56 ******************************************************************************/
59 * Process L2CA_Connect request from the upper layer protocol.
63 ng_l2cap_l2ca_con_req(ng_l2cap_p l2cap, struct ng_mesg *msg)
65 ng_l2cap_l2ca_con_ip *ip = NULL;
66 ng_l2cap_con_p con = NULL;
67 ng_l2cap_chan_p ch = NULL;
68 ng_l2cap_cmd_p cmd = NULL;
72 if (msg->header.arglen != sizeof(*ip)) {
74 "%s: %s - invalid L2CA_Connect request message size, size=%d\n",
75 __func__, NG_NODE_NAME(l2cap->node),
81 ip = (ng_l2cap_l2ca_con_ip *)(msg->data);
83 /* Check if we have connection to the remote unit */
84 con = ng_l2cap_con_by_addr(l2cap, &ip->bdaddr);
86 /* Submit LP_ConnectReq to the lower layer */
87 error = ng_l2cap_lp_con_req(l2cap, &ip->bdaddr);
90 "%s: %s - unable to send LP_ConnectReq message, error=%d\n",
91 __func__, NG_NODE_NAME(l2cap->node), error);
95 /* This should not fail */
96 con = ng_l2cap_con_by_addr(l2cap, &ip->bdaddr);
97 KASSERT((con != NULL),
98 ("%s: %s - could not find connection!\n", __func__, NG_NODE_NAME(l2cap->node)));
102 * Create new empty channel descriptor. In case of any failure do
103 * not touch connection descriptor.
106 ch = ng_l2cap_new_chan(l2cap, con, ip->psm);
112 /* Now create L2CAP_ConnectReq command */
113 cmd = ng_l2cap_new_cmd(ch->con, ch, ng_l2cap_get_ident(con),
114 NG_L2CAP_CON_REQ, msg->header.token);
116 ng_l2cap_free_chan(ch);
121 if (cmd->ident == NG_L2CAP_NULL_IDENT) {
122 ng_l2cap_free_cmd(cmd);
123 ng_l2cap_free_chan(ch);
128 /* Create L2CAP command packet */
129 _ng_l2cap_con_req(cmd->aux, cmd->ident, ch->psm, ch->scid);
130 if (cmd->aux == NULL) {
131 ng_l2cap_free_cmd(cmd);
132 ng_l2cap_free_chan(ch);
137 ch->state = NG_L2CAP_W4_L2CAP_CON_RSP;
139 /* Link command to the queue */
140 ng_l2cap_link_cmd(ch->con, cmd);
141 ng_l2cap_lp_deliver(ch->con);
144 } /* ng_l2cap_l2ca_con_req */
147 * Send L2CA_Connect response to the upper layer protocol.
151 ng_l2cap_l2ca_con_rsp(ng_l2cap_chan_p ch, u_int32_t token, u_int16_t result,
154 ng_l2cap_p l2cap = ch->con->l2cap;
155 struct ng_mesg *msg = NULL;
156 ng_l2cap_l2ca_con_op *op = NULL;
159 /* Check if upstream hook is connected and valid */
160 if (l2cap->l2c == NULL || NG_HOOK_NOT_VALID(l2cap->l2c)) {
162 "%s: %s - unable to send L2CA_Connect response message. " \
163 "Hook is not connected or valid, psm=%d\n",
164 __func__, NG_NODE_NAME(l2cap->node), ch->psm);
169 /* Create and send L2CA_Connect response message */
170 NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_CON,
171 sizeof(*op), M_NOWAIT);
175 msg->header.token = token;
176 msg->header.flags |= NGF_RESP;
178 op = (ng_l2cap_l2ca_con_op *)(msg->data);
181 * XXX Spec. says we should only populate LCID when result == 0
182 * What about PENDING? What the heck, for now always populate
190 NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->l2c, 0);
194 } /* ng_l2cap_l2ca_con_rsp */
197 * Process L2CA_ConnectRsp request from the upper layer protocol.
201 ng_l2cap_l2ca_con_rsp_req(ng_l2cap_p l2cap, struct ng_mesg *msg)
203 ng_l2cap_l2ca_con_rsp_ip *ip = NULL;
204 ng_l2cap_con_p con = NULL;
205 ng_l2cap_chan_p ch = NULL;
206 ng_l2cap_cmd_p cmd = NULL;
211 if (msg->header.arglen != sizeof(*ip)) {
213 "%s: %s - invalid L2CA_ConnectRsp request message size, size=%d\n",
214 __func__, NG_NODE_NAME(l2cap->node),
220 ip = (ng_l2cap_l2ca_con_rsp_ip *)(msg->data);
222 /* Check if we have this channel */
223 ch = ng_l2cap_chan_by_scid(l2cap, ip->lcid);
226 "%s: %s - unexpected L2CA_ConnectRsp request message. " \
227 "Channel does not exist, lcid=%d\n",
228 __func__, NG_NODE_NAME(l2cap->node), ip->lcid);
233 /* Check channel state */
234 if (ch->state != NG_L2CAP_W4_L2CA_CON_RSP) {
236 "%s: %s - unexpected L2CA_ConnectRsp request message. " \
237 "Invalid channel state, state=%d, lcid=%d\n",
238 __func__, NG_NODE_NAME(l2cap->node), ch->state,
248 * Now we are pretty much sure it is our response. So create and send
249 * L2CAP_ConnectRsp message to our peer.
252 if (ch->ident != ip->ident)
254 "%s: %s - channel ident and response ident do not match, scid=%d, ident=%d. " \
255 "Will use response ident=%d\n",
256 __func__, NG_NODE_NAME(l2cap->node), ch->scid,
257 ch->ident, ip->ident);
260 switch (ip->result) {
261 case NG_L2CAP_SUCCESS:
262 ch->state = NG_L2CAP_CONFIG;
266 case NG_L2CAP_PENDING:
270 ng_l2cap_free_chan(ch);
275 /* Create L2CAP command */
276 cmd = ng_l2cap_new_cmd(con, ch, ip->ident, NG_L2CAP_CON_RSP,
280 ng_l2cap_free_chan(ch);
286 _ng_l2cap_con_rsp(cmd->aux, cmd->ident, ip->lcid, dcid,
287 ip->result, ip->status);
288 if (cmd->aux == NULL) {
290 ng_l2cap_free_chan(ch);
292 ng_l2cap_free_cmd(cmd);
297 /* Link command to the queue */
298 ng_l2cap_link_cmd(con, cmd);
299 ng_l2cap_lp_deliver(con);
302 } /* ng_l2cap_l2ca_con_rsp_req */
305 * Send L2CAP_ConnectRsp response to the upper layer
309 ng_l2cap_l2ca_con_rsp_rsp(ng_l2cap_chan_p ch, u_int32_t token, u_int16_t result)
311 ng_l2cap_p l2cap = ch->con->l2cap;
312 struct ng_mesg *msg = NULL;
313 ng_l2cap_l2ca_con_rsp_op *op = NULL;
316 /* Check if upstream hook is connected and valid */
317 if (l2cap->l2c == NULL || NG_HOOK_NOT_VALID(l2cap->l2c)) {
319 "%s: %s - unable to send L2CA_ConnectRsp response message. " \
320 "Hook is not connected or valid, psm=%d\n",
321 __func__, NG_NODE_NAME(l2cap->node), ch->psm);
326 /* Create and send L2CA_ConnectRsp response message */
327 NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_CON_RSP,
328 sizeof(*op), M_NOWAIT);
332 msg->header.token = token;
333 msg->header.flags |= NGF_RESP;
335 op = (ng_l2cap_l2ca_con_rsp_op *)(msg->data);
338 NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->l2c, 0);
342 } /* ng_l2cap_l2ca_con_rsp_rsp */
345 * Send L2CA_ConnectInd message to the upper layer protocol.
349 ng_l2cap_l2ca_con_ind(ng_l2cap_chan_p ch)
351 ng_l2cap_p l2cap = ch->con->l2cap;
352 struct ng_mesg *msg = NULL;
353 ng_l2cap_l2ca_con_ind_ip *ip = NULL;
356 /* Check if upstream hook is connected and valid */
357 if (l2cap->l2c == NULL || NG_HOOK_NOT_VALID(l2cap->l2c)) {
359 "%s: %s - unable to send L2CA_ConnectInd message. " \
360 "Hook is not connected or valid, psm=%d\n",
361 __func__, NG_NODE_NAME(l2cap->node), ch->psm);
366 /* Create and send L2CA_ConnectInd message */
367 NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_CON_IND,
368 sizeof(*ip), M_NOWAIT);
372 ip = (ng_l2cap_l2ca_con_ind_ip *)(msg->data);
374 bcopy(&ch->con->remote, &ip->bdaddr, sizeof(ip->bdaddr));
377 ip->ident = ch->ident;
379 NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->l2c, 0);
383 } /* ng_l2cap_l2ca_con_ind */
386 * Process L2CA_Config request from the upper layer protocol
390 ng_l2cap_l2ca_cfg_req(ng_l2cap_p l2cap, struct ng_mesg *msg)
392 ng_l2cap_l2ca_cfg_ip *ip = NULL;
393 ng_l2cap_chan_p ch = NULL;
394 ng_l2cap_cmd_p cmd = NULL;
395 struct mbuf *opt = NULL;
396 u_int16_t *mtu = NULL, *flush_timo = NULL;
397 ng_l2cap_flow_p flow = NULL;
401 if (msg->header.arglen != sizeof(*ip)) {
403 "%s: %s - Invalid L2CA_Config request message size, size=%d\n",
404 __func__, NG_NODE_NAME(l2cap->node),
410 ip = (ng_l2cap_l2ca_cfg_ip *)(msg->data);
412 /* Check if we have this channel */
413 ch = ng_l2cap_chan_by_scid(l2cap, ip->lcid);
416 "%s: %s - unexpected L2CA_Config request message. " \
417 "Channel does not exist, lcid=%d\n",
418 __func__, NG_NODE_NAME(l2cap->node), ip->lcid);
423 /* Check channel state */
424 if (ch->state != NG_L2CAP_OPEN && ch->state != NG_L2CAP_CONFIG) {
426 "%s: %s - unexpected L2CA_Config request message. " \
427 "Invalid channel state, state=%d, lcid=%d\n",
428 __func__, NG_NODE_NAME(l2cap->node), ch->state,
434 /* Set requested channel configuration options */
436 bcopy(&ip->oflow, &ch->oflow, sizeof(ch->oflow));
437 ch->flush_timo = ip->flush_timo;
438 ch->link_timo = ip->link_timo;
440 /* Compare channel settings with defaults */
441 if (ch->imtu != NG_L2CAP_MTU_DEFAULT)
443 if (ch->flush_timo != NG_L2CAP_FLUSH_TIMO_DEFAULT)
444 flush_timo = &ch->flush_timo;
445 if (bcmp(ng_l2cap_default_flow(), &ch->oflow, sizeof(ch->oflow)) != 0)
448 /* Create configuration options */
449 _ng_l2cap_build_cfg_options(opt, mtu, flush_timo, flow);
455 /* Create L2CAP command descriptor */
456 cmd = ng_l2cap_new_cmd(ch->con, ch, ng_l2cap_get_ident(ch->con),
457 NG_L2CAP_CFG_REQ, msg->header.token);
464 if (cmd->ident == NG_L2CAP_NULL_IDENT) {
465 ng_l2cap_free_cmd(cmd);
471 /* Create L2CAP command packet */
472 _ng_l2cap_cfg_req(cmd->aux, cmd->ident, ch->dcid, 0, opt);
473 if (cmd->aux == NULL) {
474 ng_l2cap_free_cmd(cmd);
479 /* Adjust channel state for re-configuration */
480 if (ch->state == NG_L2CAP_OPEN) {
481 ch->state = NG_L2CAP_CONFIG;
485 /* Link command to the queue */
486 ng_l2cap_link_cmd(ch->con, cmd);
487 ng_l2cap_lp_deliver(ch->con);
490 } /* ng_l2cap_l2ca_cfg_req */
493 * Send L2CA_Config response to the upper layer protocol
497 ng_l2cap_l2ca_cfg_rsp(ng_l2cap_chan_p ch, u_int32_t token, u_int16_t result)
499 ng_l2cap_p l2cap = ch->con->l2cap;
500 struct ng_mesg *msg = NULL;
501 ng_l2cap_l2ca_cfg_op *op = NULL;
504 /* Check if upstream hook is connected and valid */
505 if (l2cap->l2c == NULL || NG_HOOK_NOT_VALID(l2cap->l2c)) {
507 "%s: %s - unable to send L2CA_Config response message. " \
508 "Hook is not connected or valid, psm=%d\n",
509 __func__, NG_NODE_NAME(l2cap->node), ch->psm);
514 /* Create and send L2CA_Config response message */
515 NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_CFG,
516 sizeof(*op), M_NOWAIT);
520 msg->header.token = token;
521 msg->header.flags |= NGF_RESP;
523 op = (ng_l2cap_l2ca_cfg_op *)(msg->data);
526 bcopy(&ch->oflow, &op->oflow, sizeof(op->oflow));
527 op->flush_timo = ch->flush_timo;
529 NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->l2c, 0);
531 if (error == 0 && result == NG_L2CAP_SUCCESS) {
532 ch->cfg_state |= NG_L2CAP_CFG_IN;
534 if (ch->cfg_state == NG_L2CAP_CFG_BOTH)
535 ch->state = NG_L2CAP_OPEN;
540 } /* ng_l2cap_l2ca_cfg_rsp */
543 * Process L2CA_ConfigRsp request from the upper layer protocol
547 * NOTE: The Bluetooth specification says that Configuration_Response
548 * (L2CA_ConfigRsp) should be used to issue response to configuration request
549 * indication. The minor problem here is L2CAP command ident. We should use
550 * ident from original L2CAP request to make sure our peer can match request
551 * and response. For some reason Bluetooth specification does not include
552 * ident field into L2CA_ConfigInd and L2CA_ConfigRsp messages. This seems
553 * strange to me, because L2CA_ConnectInd and L2CA_ConnectRsp do have ident
554 * field. So we should store last known L2CAP request command ident in channel.
555 * Also it seems that upper layer can not reject configuration request, as
556 * Configuration_Response message does not have status/reason field.
560 ng_l2cap_l2ca_cfg_rsp_req(ng_l2cap_p l2cap, struct ng_mesg *msg)
562 ng_l2cap_l2ca_cfg_rsp_ip *ip = NULL;
563 ng_l2cap_chan_p ch = NULL;
564 ng_l2cap_cmd_p cmd = NULL;
565 struct mbuf *opt = NULL;
566 u_int16_t *mtu = NULL;
567 ng_l2cap_flow_p flow = NULL;
571 if (msg->header.arglen != sizeof(*ip)) {
573 "%s: %s - invalid L2CA_ConfigRsp request message size, size=%d\n",
574 __func__, NG_NODE_NAME(l2cap->node),
580 ip = (ng_l2cap_l2ca_cfg_rsp_ip *)(msg->data);
582 /* Check if we have this channel */
583 ch = ng_l2cap_chan_by_scid(l2cap, ip->lcid);
586 "%s: %s - unexpected L2CA_ConfigRsp request message. " \
587 "Channel does not exist, lcid=%d\n",
588 __func__, NG_NODE_NAME(l2cap->node), ip->lcid);
593 /* Check channel state */
594 if (ch->state != NG_L2CAP_CONFIG) {
596 "%s: %s - unexpected L2CA_ConfigRsp request message. " \
597 "Invalid channel state, state=%d, lcid=%d\n",
598 __func__, NG_NODE_NAME(l2cap->node), ch->state,
604 /* Set channel settings */
605 if (ip->omtu != ch->omtu) {
610 if (bcmp(&ip->iflow, &ch->iflow, sizeof(ch->iflow)) != 0) {
611 bcopy(&ip->iflow, &ch->iflow, sizeof(ch->iflow));
615 if (mtu != NULL || flow != NULL) {
616 _ng_l2cap_build_cfg_options(opt, mtu, NULL, flow);
623 /* Create L2CAP command */
624 cmd = ng_l2cap_new_cmd(ch->con, ch, ch->ident, NG_L2CAP_CFG_RSP,
632 _ng_l2cap_cfg_rsp(cmd->aux,cmd->ident,ch->dcid,0,NG_L2CAP_SUCCESS,opt);
633 if (cmd->aux == NULL) {
634 ng_l2cap_free_cmd(cmd);
639 /* XXX FIXME - not here ??? */
640 ch->cfg_state |= NG_L2CAP_CFG_OUT;
641 if (ch->cfg_state == NG_L2CAP_CFG_BOTH)
642 ch->state = NG_L2CAP_OPEN;
644 /* Link command to the queue */
645 ng_l2cap_link_cmd(ch->con, cmd);
646 ng_l2cap_lp_deliver(ch->con);
649 } /* ng_l2cap_l2ca_cfg_rsp_req */
652 * Send L2CA_ConfigRsp response to the upper layer protocol
656 ng_l2cap_l2ca_cfg_rsp_rsp(ng_l2cap_chan_p ch, u_int32_t token, u_int16_t result)
658 ng_l2cap_p l2cap = ch->con->l2cap;
659 struct ng_mesg *msg = NULL;
660 ng_l2cap_l2ca_cfg_rsp_op *op = NULL;
663 /* Check if upstream hook is connected and valid */
664 if (l2cap->l2c == NULL || NG_HOOK_NOT_VALID(l2cap->l2c)) {
666 "%s: %s - unable to send L2CA_ConfigRsp response message. " \
667 "Hook is not connected or valid, psm=%d\n",
668 __func__, NG_NODE_NAME(l2cap->node), ch->psm);
673 /* Create and send L2CA_ConfigRsp response message */
674 NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_CFG_RSP,
675 sizeof(*op), M_NOWAIT);
679 msg->header.token = token;
680 msg->header.flags |= NGF_RESP;
682 op = (ng_l2cap_l2ca_cfg_rsp_op *)(msg->data);
685 NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->l2c, 0);
689 } /* ng_l2cap_l2ca_cfg_rsp_rsp */
692 * Send L2CA_ConfigInd message to the upper layer protocol
696 * NOTE: The Bluetooth specification says that Configuration_Response
697 * (L2CA_ConfigRsp) should be used to issue response to configuration request
698 * indication. The minor problem here is L2CAP command ident. We should use
699 * ident from original L2CAP request to make sure our peer can match request
700 * and response. For some reason Bluetooth specification does not include
701 * ident field into L2CA_ConfigInd and L2CA_ConfigRsp messages. This seems
702 * strange to me, because L2CA_ConnectInd and L2CA_ConnectRsp do have ident
703 * field. So we should store last known L2CAP request command ident in channel.
704 * Also it seems that upper layer can not reject configuration request, as
705 * Configuration_Response message does not have status/reason field.
709 ng_l2cap_l2ca_cfg_ind(ng_l2cap_chan_p ch)
711 ng_l2cap_p l2cap = ch->con->l2cap;
712 struct ng_mesg *msg = NULL;
713 ng_l2cap_l2ca_cfg_ind_ip *ip = NULL;
716 /* Check if upstream hook is connected and valid */
717 if (l2cap->l2c == NULL || NG_HOOK_NOT_VALID(l2cap->l2c)) {
719 "%s: %s - Unable to send L2CA_ConfigInd message. " \
720 "Hook is not connected or valid, psm=%d\n",
721 __func__, NG_NODE_NAME(l2cap->node), ch->psm);
726 /* Create and send L2CA_ConnectInd message */
727 NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_CFG_IND,
728 sizeof(*ip), M_NOWAIT);
732 ip = (ng_l2cap_l2ca_cfg_ind_ip *)(msg->data);
735 bcopy(&ch->iflow, &ip->iflow, sizeof(ip->iflow));
736 ip->flush_timo = ch->flush_timo;
738 NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->l2c, 0);
742 } /* ng_l2cap_l2ca_cfg_ind */
745 * Process L2CA_Write event
749 ng_l2cap_l2ca_write_req(ng_l2cap_p l2cap, struct mbuf *m)
751 ng_l2cap_l2ca_hdr_t *l2ca_hdr = NULL;
752 ng_l2cap_chan_p ch = NULL;
753 ng_l2cap_cmd_p cmd = NULL;
757 /* Make sure we can access L2CA data packet header */
758 if (m->m_pkthdr.len < sizeof(*l2ca_hdr)) {
760 "%s: %s - L2CA Data packet too small, len=%d\n",
761 __func__,NG_NODE_NAME(l2cap->node),m->m_pkthdr.len);
766 /* Get L2CA data packet header */
767 NG_L2CAP_M_PULLUP(m, sizeof(*l2ca_hdr));
771 l2ca_hdr = mtod(m, ng_l2cap_l2ca_hdr_t *);
772 token = l2ca_hdr->token;
773 m_adj(m, sizeof(*l2ca_hdr));
775 /* Verify payload size */
776 if (l2ca_hdr->length != m->m_pkthdr.len) {
778 "%s: %s - invalid L2CA Data packet. " \
779 "Payload length does not match, length=%d, len=%d\n",
780 __func__, NG_NODE_NAME(l2cap->node), l2ca_hdr->length,
786 /* Check channel ID */
787 if (l2ca_hdr->lcid < NG_L2CAP_FIRST_CID) {
789 "%s: %s - invalid L2CA Data packet. Inavlid channel ID, cid=%d\n",
790 __func__, NG_NODE_NAME(l2cap->node), l2ca_hdr->lcid);
795 /* Verify that we have the channel and make sure it is open */
796 ch = ng_l2cap_chan_by_scid(l2cap, l2ca_hdr->lcid);
799 "%s: %s - invalid L2CA Data packet. Channel does not exist, cid=%d\n",
800 __func__, NG_NODE_NAME(l2cap->node), l2ca_hdr->lcid);
805 if (ch->state != NG_L2CAP_OPEN) {
807 "%s: %s - invalid L2CA Data packet. Invalid channel state, scid=%d, state=%d\n",
808 __func__, NG_NODE_NAME(l2cap->node), ch->scid,
811 goto drop; /* XXX not always - re-configure */
814 /* Create L2CAP command descriptor */
815 cmd = ng_l2cap_new_cmd(ch->con, ch, 0, NGM_L2CAP_L2CA_WRITE, token);
821 /* Attach data packet and link command to the queue */
823 ng_l2cap_link_cmd(ch->con, cmd);
824 ng_l2cap_lp_deliver(ch->con);
831 } /* ng_l2cap_l2ca_write_req */
834 * Send L2CA_Write response
838 ng_l2cap_l2ca_write_rsp(ng_l2cap_chan_p ch, u_int32_t token, u_int16_t result,
841 ng_l2cap_p l2cap = ch->con->l2cap;
842 struct ng_mesg *msg = NULL;
843 ng_l2cap_l2ca_write_op *op = NULL;
846 /* Check if upstream hook is connected and valid */
847 if (l2cap->l2c == NULL || NG_HOOK_NOT_VALID(l2cap->l2c)) {
849 "%s: %s - unable to send L2CA_WriteRsp message. " \
850 "Hook is not connected or valid, psm=%d\n",
851 __func__, NG_NODE_NAME(l2cap->node), ch->psm);
856 /* Create and send L2CA_WriteRsp message */
857 NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_WRITE,
858 sizeof(*op), M_NOWAIT);
862 msg->header.token = token;
863 msg->header.flags |= NGF_RESP;
865 op = (ng_l2cap_l2ca_write_op *)(msg->data);
870 NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->l2c, 0);
874 } /* ng_l2cap_l2ca_write_rsp */
877 * Receive packet from the lower layer protocol and send it to the upper
878 * layer protocol (L2CAP_Read)
882 ng_l2cap_l2ca_receive(ng_l2cap_con_p con)
884 ng_l2cap_p l2cap = con->l2cap;
885 ng_l2cap_hdr_t *hdr = NULL;
886 ng_l2cap_chan_p ch = NULL;
889 NG_L2CAP_M_PULLUP(con->rx_pkt, sizeof(*hdr));
890 if (con->rx_pkt == NULL)
893 hdr = mtod(con->rx_pkt, ng_l2cap_hdr_t *);
896 ch = ng_l2cap_chan_by_scid(l2cap, hdr->dcid);
899 "%s: %s - unexpected L2CAP data packet. Channel does not exist, cid=%d\n",
900 __func__, NG_NODE_NAME(l2cap->node), hdr->dcid);
905 /* Check channel state */
906 if (ch->state != NG_L2CAP_OPEN) {
908 "%s: %s - unexpected L2CAP data packet. " \
909 "Invalid channel state, cid=%d, state=%d\n",
910 __func__, NG_NODE_NAME(l2cap->node), ch->scid,
912 error = EHOSTDOWN; /* XXX not always - re-configuration */
916 /* Check payload size and channel's MTU */
917 if (hdr->length > ch->imtu) {
919 "%s: %s - invalid L2CAP data packet. " \
920 "Packet too big, length=%d, imtu=%d, cid=%d\n",
921 __func__, NG_NODE_NAME(l2cap->node), hdr->length,
928 * If we got here then everything looks good and we can sent packet
929 * to the upper layer protocol.
932 /* Check if upstream hook is connected and valid */
933 if (l2cap->l2c == NULL || NG_HOOK_NOT_VALID(l2cap->l2c)) {
935 "%s: %s - unable to send L2CAP data packet. " \
936 "Hook is not connected or valid, psm=%d\n",
937 __func__, NG_NODE_NAME(l2cap->node), ch->psm);
942 NG_SEND_DATA_ONLY(error, l2cap->l2c, con->rx_pkt);
945 NG_FREE_M(con->rx_pkt); /* checks for != NULL */
948 } /* ng_l2cap_receive */
951 * Receive connectioless (multicast) packet from the lower layer protocol and
952 * send it to the upper layer protocol
956 ng_l2cap_l2ca_clt_receive(ng_l2cap_con_p con)
960 ng_l2cap_clt_hdr_t c_h;
961 } __attribute__ ((packed)) *hdr = NULL;
962 ng_l2cap_p l2cap = con->l2cap;
963 int length, error = 0;
965 NG_L2CAP_M_PULLUP(con->rx_pkt, sizeof(*hdr));
966 if (con->rx_pkt == NULL)
969 hdr = mtod(con->rx_pkt, struct _clt_pkt *);
972 length = con->rx_pkt->m_pkthdr.len - sizeof(*hdr);
975 "%s: %s - invalid L2CAP CLT data packet. Packet too small, length=%d\n",
976 __func__, NG_NODE_NAME(l2cap->node), length);
981 /* Check payload size against CLT MTU */
982 if (length > NG_L2CAP_MTU_DEFAULT) {
984 "%s: %s - invalid L2CAP CLT data packet. Packet too big, length=%d, mtu=%d\n",
985 __func__, NG_NODE_NAME(l2cap->node), length,
986 NG_L2CAP_MTU_DEFAULT);
991 hdr->c_h.psm = le16toh(hdr->c_h.psm);
994 * If we got here then everything looks good and we can sent packet
995 * to the upper layer protocol.
998 /* Select upstream hook based on PSM */
999 switch (hdr->c_h.psm) {
1000 case NG_L2CAP_PSM_SDP:
1001 if (l2cap->flags & NG_L2CAP_CLT_SDP_DISABLED)
1005 case NG_L2CAP_PSM_RFCOMM:
1006 if (l2cap->flags & NG_L2CAP_CLT_RFCOMM_DISABLED)
1010 case NG_L2CAP_PSM_TCP:
1011 if (l2cap->flags & NG_L2CAP_CLT_TCP_DISABLED)
1016 /* Check if upstream hook is connected and valid */
1017 if (l2cap->l2c == NULL || NG_HOOK_NOT_VALID(l2cap->l2c)) {
1019 "%s: %s - unable to send L2CAP CLT data packet. " \
1020 "Hook is not connected or valid, psm=%d\n",
1021 __func__, NG_NODE_NAME(l2cap->node), hdr->c_h.psm);
1026 NG_SEND_DATA_ONLY(error, l2cap->l2c, con->rx_pkt);
1029 NG_FREE_M(con->rx_pkt); /* checks for != NULL */
1032 } /* ng_l2cap_l2ca_clt_receive */
1035 * Send L2CA_QoSViolationInd to the upper layer protocol
1039 ng_l2cap_l2ca_qos_ind(ng_l2cap_chan_p ch)
1041 ng_l2cap_p l2cap = ch->con->l2cap;
1042 struct ng_mesg *msg = NULL;
1043 ng_l2cap_l2ca_qos_ind_ip *ip = NULL;
1046 /* Check if upstream hook is connected and valid */
1047 if (l2cap->l2c == NULL || NG_HOOK_NOT_VALID(l2cap->l2c)) {
1049 "%s: %s - unable to send L2CA_QoSViolationInd message. " \
1050 "Hook is not connected or valid, psm=%d\n",
1051 __func__, NG_NODE_NAME(l2cap->node), ch->psm);
1056 /* Create and send L2CA_QoSViolationInd message */
1057 NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_QOS_IND,
1058 sizeof(*ip), M_NOWAIT);
1062 ip = (ng_l2cap_l2ca_qos_ind_ip *)(msg->data);
1063 bcopy(&ch->con->remote, &ip->bdaddr, sizeof(ip->bdaddr));
1064 NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->l2c, 0);
1068 } /* ng_l2cap_l2ca_qos_ind */
1071 * Process L2CA_Disconnect request from the upper layer protocol.
1075 ng_l2cap_l2ca_discon_req(ng_l2cap_p l2cap, struct ng_mesg *msg)
1077 ng_l2cap_l2ca_discon_ip *ip = NULL;
1078 ng_l2cap_chan_p ch = NULL;
1079 ng_l2cap_cmd_p cmd = NULL;
1083 if (msg->header.arglen != sizeof(*ip)) {
1085 "%s: %s - invalid L2CA_Disconnect request message size, size=%d\n",
1086 __func__, NG_NODE_NAME(l2cap->node),
1087 msg->header.arglen);
1092 ip = (ng_l2cap_l2ca_discon_ip *)(msg->data);
1094 /* Check if we have this channel */
1095 ch = ng_l2cap_chan_by_scid(l2cap, ip->lcid);
1098 "%s: %s - unexpected L2CA_Disconnect request message. " \
1099 "Channel does not exist, lcid=%d\n",
1100 __func__, NG_NODE_NAME(l2cap->node), ip->lcid);
1105 /* Check channel state */
1106 if (ch->state != NG_L2CAP_CONFIG && ch->state != NG_L2CAP_OPEN &&
1107 ch->state != NG_L2CAP_W4_L2CAP_DISCON_RSP) {
1109 "%s: %s - unexpected L2CA_Disconnect request message. " \
1110 "Invalid channel state, state=%d, lcid=%d\n",
1111 __func__, NG_NODE_NAME(l2cap->node), ch->state,
1117 /* Create and send L2CAP_DisconReq message */
1118 cmd = ng_l2cap_new_cmd(ch->con, ch, ng_l2cap_get_ident(ch->con),
1119 NG_L2CAP_DISCON_REQ, msg->header.token);
1121 ng_l2cap_free_chan(ch);
1126 if (cmd->ident == NG_L2CAP_NULL_IDENT) {
1127 ng_l2cap_free_chan(ch);
1128 ng_l2cap_free_cmd(cmd);
1133 _ng_l2cap_discon_req(cmd->aux, cmd->ident, ch->dcid, ch->scid);
1134 if (cmd->aux == NULL) {
1135 ng_l2cap_free_chan(ch);
1136 ng_l2cap_free_cmd(cmd);
1141 ch->state = NG_L2CAP_W4_L2CAP_DISCON_RSP;
1143 /* Link command to the queue */
1144 ng_l2cap_link_cmd(ch->con, cmd);
1145 ng_l2cap_lp_deliver(ch->con);
1148 } /* ng_l2cap_l2ca_discon_req */
1151 * Send L2CA_Disconnect response to the upper layer protocol
1155 ng_l2cap_l2ca_discon_rsp(ng_l2cap_chan_p ch, u_int32_t token, u_int16_t result)
1157 ng_l2cap_p l2cap = ch->con->l2cap;
1158 struct ng_mesg *msg = NULL;
1159 ng_l2cap_l2ca_discon_op *op = NULL;
1162 /* Check if upstream hook is connected and valid */
1163 if (l2cap->l2c == NULL || NG_HOOK_NOT_VALID(l2cap->l2c)) {
1165 "%s: %s - unable to send L2CA_Disconnect response message. " \
1166 "Hook is not connected or valid, psm=%d\n",
1167 __func__, NG_NODE_NAME(l2cap->node), ch->psm);
1172 /* Create and send L2CA_Disconnect response message */
1173 NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_DISCON,
1174 sizeof(*op), M_NOWAIT);
1178 msg->header.token = token;
1179 msg->header.flags |= NGF_RESP;
1181 op = (ng_l2cap_l2ca_discon_op *)(msg->data);
1182 op->result = result;
1184 NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->l2c, 0);
1188 } /* ng_l2cap_l2ca_discon_rsp */
1191 * Send L2CA_DisconnectInd message to the upper layer protocol.
1195 ng_l2cap_l2ca_discon_ind(ng_l2cap_chan_p ch)
1197 ng_l2cap_p l2cap = ch->con->l2cap;
1198 struct ng_mesg *msg = NULL;
1199 ng_l2cap_l2ca_discon_ind_ip *ip = NULL;
1202 /* Check if upstream hook is connected and valid */
1203 if (l2cap->l2c == NULL || NG_HOOK_NOT_VALID(l2cap->l2c)) {
1205 "%s: %s - unable to send L2CA_DisconnectInd message. " \
1206 "Hook is not connected or valid, psm=%d\n",
1207 __func__, NG_NODE_NAME(l2cap->node), ch->psm);
1212 /* Create and send L2CA_DisconnectInd message */
1213 NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_DISCON_IND,
1214 sizeof(*ip), M_NOWAIT);
1218 ip = (ng_l2cap_l2ca_discon_ind_ip *)(msg->data);
1219 ip->lcid = ch->scid;
1220 NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->l2c, 0);
1224 } /* ng_l2cap_l2ca_discon_ind */
1227 * Process L2CA_GroupCreate request from the upper layer protocol.
1232 ng_l2cap_l2ca_grp_create(ng_l2cap_p l2cap, struct ng_mesg *msg)
1235 } /* ng_l2cap_l2ca_grp_create */
1238 * Process L2CA_GroupClose request from the upper layer protocol
1243 ng_l2cap_l2ca_grp_close(ng_l2cap_p l2cap, struct ng_mesg *msg)
1246 } /* ng_l2cap_l2ca_grp_close */
1249 * Process L2CA_GroupAddMember request from the upper layer protocol.
1254 ng_l2cap_l2ca_grp_add_member_req(ng_l2cap_p l2cap, struct ng_mesg *msg)
1257 } /* ng_l2cap_l2ca_grp_add_member_req */
1260 * Send L2CA_GroupAddMember response to the upper layer protocol.
1265 ng_l2cap_l2ca_grp_add_member_rsp(ng_l2cap_chan_p ch, u_int32_t token,
1269 } /* ng_l2cap_l2ca_grp_add_member_rsp */
1272 * Process L2CA_GroupDeleteMember request from the upper layer protocol
1277 ng_l2cap_l2ca_grp_rem_member(ng_l2cap_p l2cap, struct ng_mesg *msg)
1280 } /* ng_l2cap_l2ca_grp_rem_member */
1283 * Process L2CA_GroupGetMembers request from the upper layer protocol
1288 ng_l2cap_l2ca_grp_get_members(ng_l2cap_p l2cap, struct ng_mesg *msg)
1291 } /* ng_l2cap_l2ca_grp_get_members */
1294 * Process L2CA_Ping request from the upper layer protocol
1298 ng_l2cap_l2ca_ping_req(ng_l2cap_p l2cap, struct ng_mesg *msg)
1300 ng_l2cap_l2ca_ping_ip *ip = NULL;
1301 ng_l2cap_con_p con = NULL;
1302 ng_l2cap_cmd_p cmd = NULL;
1305 /* Verify message */
1306 if (msg->header.arglen < sizeof(*ip)) {
1308 "%s: %s - invalid L2CA_Ping request message size, size=%d\n",
1309 __func__, NG_NODE_NAME(l2cap->node),
1310 msg->header.arglen);
1315 ip = (ng_l2cap_l2ca_ping_ip *)(msg->data);
1316 if (ip->echo_size > NG_L2CAP_MAX_ECHO_SIZE) {
1318 "%s: %s - invalid L2CA_Ping request. Echo size is too big, echo_size=%d\n",
1319 __func__, NG_NODE_NAME(l2cap->node), ip->echo_size);
1324 /* Check if we have connection to the unit */
1325 con = ng_l2cap_con_by_addr(l2cap, &ip->bdaddr);
1327 /* Submit LP_ConnectReq to the lower layer */
1328 error = ng_l2cap_lp_con_req(l2cap, &ip->bdaddr);
1331 "%s: %s - unable to send LP_ConnectReq message, error=%d\n",
1332 __func__, NG_NODE_NAME(l2cap->node), error);
1336 /* This should not fail */
1337 con = ng_l2cap_con_by_addr(l2cap, &ip->bdaddr);
1338 KASSERT((con != NULL),
1339 ("%s: %s - could not find connection!\n", __func__, NG_NODE_NAME(l2cap->node)));
1342 /* Create L2CAP command descriptor */
1343 cmd = ng_l2cap_new_cmd(con, NULL, ng_l2cap_get_ident(con),
1344 NG_L2CAP_ECHO_REQ, msg->header.token);
1350 if (cmd->ident == NG_L2CAP_NULL_IDENT) {
1351 ng_l2cap_free_cmd(cmd);
1356 /* Create L2CAP command packet */
1357 _ng_l2cap_echo_req(cmd->aux, cmd->ident,
1358 msg->data + sizeof(*ip), ip->echo_size);
1359 if (cmd->aux == NULL) {
1360 ng_l2cap_free_cmd(cmd);
1365 /* Link command to the queue */
1366 ng_l2cap_link_cmd(con, cmd);
1367 ng_l2cap_lp_deliver(con);
1370 } /* ng_l2cap_l2ca_ping_req */
1373 * Send L2CA_Ping response to the upper layer protocol
1377 ng_l2cap_l2ca_ping_rsp(ng_l2cap_con_p con, u_int32_t token, u_int16_t result,
1380 ng_l2cap_p l2cap = con->l2cap;
1381 struct ng_mesg *msg = NULL;
1382 ng_l2cap_l2ca_ping_op *op = NULL;
1383 int error = 0, size = 0;
1385 /* Check if control hook is connected and valid */
1386 if (l2cap->ctl == NULL || NG_HOOK_NOT_VALID(l2cap->ctl)) {
1388 "%s: %s - unable to send L2CA_Ping response message. " \
1389 "Hook is not connected or valid\n",
1390 __func__, NG_NODE_NAME(l2cap->node));
1395 size = (data == NULL)? 0 : data->m_pkthdr.len;
1397 /* Create and send L2CA_Ping response message */
1398 NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_PING,
1399 sizeof(*op) + size, M_NOWAIT);
1403 msg->header.token = token;
1404 msg->header.flags |= NGF_RESP;
1406 op = (ng_l2cap_l2ca_ping_op *)(msg->data);
1407 op->result = result;
1408 bcopy(&con->remote, &op->bdaddr, sizeof(op->bdaddr));
1409 if (data != NULL && size > 0) {
1410 op->echo_size = size;
1411 m_copydata(data, 0, size, (caddr_t) op + sizeof(*op));
1414 NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->ctl, 0);
1420 } /* ng_l2cap_l2ca_ping_rsp */
1423 * Process L2CA_GetInfo request from the upper layer protocol
1427 ng_l2cap_l2ca_get_info_req(ng_l2cap_p l2cap, struct ng_mesg *msg)
1429 ng_l2cap_l2ca_get_info_ip *ip = NULL;
1430 ng_l2cap_con_p con = NULL;
1431 ng_l2cap_cmd_p cmd = NULL;
1434 /* Verify message */
1435 if (msg->header.arglen != sizeof(*ip)) {
1437 "%s: %s - invalid L2CA_GetInfo request message size, size=%d\n",
1438 __func__, NG_NODE_NAME(l2cap->node),
1439 msg->header.arglen);
1444 ip = (ng_l2cap_l2ca_get_info_ip *)(msg->data);
1446 /* Check if we have connection to the unit */
1447 con = ng_l2cap_con_by_addr(l2cap, &ip->bdaddr);
1449 /* Submit LP_ConnectReq to the lower layer */
1450 error = ng_l2cap_lp_con_req(l2cap, &ip->bdaddr);
1453 "%s: %s - unable to send LP_ConnectReq message, error=%d\n",
1454 __func__, NG_NODE_NAME(l2cap->node), error);
1458 /* This should not fail */
1459 con = ng_l2cap_con_by_addr(l2cap, &ip->bdaddr);
1460 KASSERT((con != NULL),
1461 ("%s: %s - could not find connection!\n", __func__, NG_NODE_NAME(l2cap->node)));
1464 /* Create L2CAP command descriptor */
1465 cmd = ng_l2cap_new_cmd(con, NULL, ng_l2cap_get_ident(con),
1466 NG_L2CAP_INFO_REQ, msg->header.token);
1472 if (cmd->ident == NG_L2CAP_NULL_IDENT) {
1473 ng_l2cap_free_cmd(cmd);
1478 /* Create L2CAP command packet */
1479 _ng_l2cap_info_req(cmd->aux, cmd->ident, ip->info_type);
1480 if (cmd->aux == NULL) {
1481 ng_l2cap_free_cmd(cmd);
1486 /* Link command to the queue */
1487 ng_l2cap_link_cmd(con, cmd);
1488 ng_l2cap_lp_deliver(con);
1491 } /* ng_l2cap_l2ca_get_info_req */
1494 * Send L2CA_GetInfo response to the upper layer protocol
1498 ng_l2cap_l2ca_get_info_rsp(ng_l2cap_con_p con, u_int32_t token,
1499 u_int16_t result, struct mbuf *data)
1501 ng_l2cap_p l2cap = con->l2cap;
1502 struct ng_mesg *msg = NULL;
1503 ng_l2cap_l2ca_get_info_op *op = NULL;
1504 int error = 0, size;
1506 /* Check if control hook is connected and valid */
1507 if (l2cap->ctl == NULL || NG_HOOK_NOT_VALID(l2cap->ctl)) {
1509 "%s: %s - unable to send L2CA_GetInfo response message. " \
1510 "Hook is not connected or valid\n",
1511 __func__, NG_NODE_NAME(l2cap->node));
1516 size = (data == NULL)? 0 : data->m_pkthdr.len;
1518 /* Create and send L2CA_GetInfo response message */
1519 NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_GET_INFO,
1520 sizeof(*op) + size, M_NOWAIT);
1524 msg->header.token = token;
1525 msg->header.flags |= NGF_RESP;
1527 op = (ng_l2cap_l2ca_get_info_op *)(msg->data);
1528 op->result = result;
1529 if (data != NULL && size > 0) {
1530 op->info_size = size;
1531 m_copydata(data, 0, size, (caddr_t) op + sizeof(*op));
1534 NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->ctl, 0);
1540 } /* ng_l2cap_l2ca_get_info_rsp */
1543 * Process L2CA_EnableCLT message from the upper layer protocol
1544 * XXX convert to NGN_L2CAP_NODE_SET_FLAGS?
1548 ng_l2cap_l2ca_enable_clt(ng_l2cap_p l2cap, struct ng_mesg *msg)
1550 ng_l2cap_l2ca_enable_clt_ip *ip = NULL;
1553 * ng_l2cap_l2ca_enable_clt_op *op = NULL;
1559 if (msg->header.arglen != sizeof(*ip)) {
1561 "%s: %s - invalid L2CA_EnableCLT message size, size=%d\n",
1562 __func__, NG_NODE_NAME(l2cap->node),
1563 msg->header.arglen);
1568 /* Process request */
1569 ip = (ng_l2cap_l2ca_enable_clt_ip *) (msg->data);
1571 * result = NG_L2CAP_SUCCESS;
1577 /* Special case: disable/enable all PSM */
1579 l2cap->flags &= ~(NG_L2CAP_CLT_SDP_DISABLED |
1580 NG_L2CAP_CLT_RFCOMM_DISABLED |
1581 NG_L2CAP_CLT_TCP_DISABLED);
1583 l2cap->flags |= (NG_L2CAP_CLT_SDP_DISABLED |
1584 NG_L2CAP_CLT_RFCOMM_DISABLED |
1585 NG_L2CAP_CLT_TCP_DISABLED);
1588 case NG_L2CAP_PSM_SDP:
1590 l2cap->flags &= ~NG_L2CAP_CLT_SDP_DISABLED;
1592 l2cap->flags |= NG_L2CAP_CLT_SDP_DISABLED;
1595 case NG_L2CAP_PSM_RFCOMM:
1597 l2cap->flags &= ~NG_L2CAP_CLT_RFCOMM_DISABLED;
1599 l2cap->flags |= NG_L2CAP_CLT_RFCOMM_DISABLED;
1602 case NG_L2CAP_PSM_TCP:
1604 l2cap->flags &= ~NG_L2CAP_CLT_TCP_DISABLED;
1606 l2cap->flags |= NG_L2CAP_CLT_TCP_DISABLED;
1611 "%s: %s - unsupported PSM=%d\n", __func__, NG_NODE_NAME(l2cap->node), ip->psm);
1613 * result = NG_L2CAP_PSM_NOT_SUPPORTED;
1620 * /* Create and send response message */
1621 * token = msg->header.token;
1623 * NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_ENABLE_CLT,
1624 * sizeof(*op), M_NOWAIT);
1628 * msg->header.token = token;
1629 * msg->header.flags |= NGF_RESP;
1631 * op = (ng_l2cap_l2ca_enable_clt_op *)(msg->data);
1632 * op->result = result;
1635 * /* Send response to control hook */
1636 * if (l2cap->ctl != NULL && NG_HOOK_IS_VALID(l2cap->ctl))
1637 * NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->ctl, 0);
1641 } /* ng_l2cap_l2ca_enable_clt */