The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * ng_btsocket_rfcomm.c
    3  */
    4 
    5 /*-
    6  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    7  *
    8  * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
    9  * All rights reserved.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  * $Id: ng_btsocket_rfcomm.c,v 1.28 2003/09/14 23:29:06 max Exp $
   33  * $FreeBSD$
   34  */
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/bitstring.h>
   39 #include <sys/domain.h>
   40 #include <sys/endian.h>
   41 #include <sys/errno.h>
   42 #include <sys/filedesc.h>
   43 #include <sys/ioccom.h>
   44 #include <sys/kernel.h>
   45 #include <sys/lock.h>
   46 #include <sys/malloc.h>
   47 #include <sys/mbuf.h>
   48 #include <sys/mutex.h>
   49 #include <sys/proc.h>
   50 #include <sys/protosw.h>
   51 #include <sys/queue.h>
   52 #include <sys/socket.h>
   53 #include <sys/socketvar.h>
   54 #include <sys/sysctl.h>
   55 #include <sys/taskqueue.h>
   56 #include <sys/uio.h>
   57 
   58 #include <net/vnet.h>
   59 
   60 #include <netgraph/ng_message.h>
   61 #include <netgraph/netgraph.h>
   62 #include <netgraph/bluetooth/include/ng_bluetooth.h>
   63 #include <netgraph/bluetooth/include/ng_hci.h>
   64 #include <netgraph/bluetooth/include/ng_l2cap.h>
   65 #include <netgraph/bluetooth/include/ng_btsocket.h>
   66 #include <netgraph/bluetooth/include/ng_btsocket_l2cap.h>
   67 #include <netgraph/bluetooth/include/ng_btsocket_rfcomm.h>
   68 
   69 /* MALLOC define */
   70 #ifdef NG_SEPARATE_MALLOC
   71 static MALLOC_DEFINE(M_NETGRAPH_BTSOCKET_RFCOMM, "netgraph_btsocks_rfcomm",
   72                 "Netgraph Bluetooth RFCOMM sockets");
   73 #else
   74 #define M_NETGRAPH_BTSOCKET_RFCOMM M_NETGRAPH
   75 #endif /* NG_SEPARATE_MALLOC */
   76 
   77 /* Debug */
   78 #define NG_BTSOCKET_RFCOMM_INFO \
   79         if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_INFO_LEVEL && \
   80             ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
   81                 printf
   82 
   83 #define NG_BTSOCKET_RFCOMM_WARN \
   84         if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_WARN_LEVEL && \
   85             ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
   86                 printf
   87 
   88 #define NG_BTSOCKET_RFCOMM_ERR \
   89         if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ERR_LEVEL && \
   90             ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
   91                 printf
   92 
   93 #define NG_BTSOCKET_RFCOMM_ALERT \
   94         if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ALERT_LEVEL && \
   95             ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
   96                 printf
   97 
   98 #define ALOT    0x7fff
   99 
  100 /* Local prototypes */
  101 static int ng_btsocket_rfcomm_upcall
  102         (struct socket *so, void *arg, int waitflag);
  103 static void ng_btsocket_rfcomm_sessions_task
  104         (void *ctx, int pending);
  105 static void ng_btsocket_rfcomm_session_task
  106         (ng_btsocket_rfcomm_session_p s);
  107 #define ng_btsocket_rfcomm_task_wakeup() \
  108         taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_rfcomm_task)
  109 
  110 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_connect_ind
  111         (ng_btsocket_rfcomm_session_p s, int channel);
  112 static void ng_btsocket_rfcomm_connect_cfm
  113         (ng_btsocket_rfcomm_session_p s);
  114 
  115 static int ng_btsocket_rfcomm_session_create
  116         (ng_btsocket_rfcomm_session_p *sp, struct socket *l2so,
  117          bdaddr_p src, bdaddr_p dst, struct thread *td);
  118 static int ng_btsocket_rfcomm_session_accept
  119         (ng_btsocket_rfcomm_session_p s0);
  120 static int ng_btsocket_rfcomm_session_connect
  121         (ng_btsocket_rfcomm_session_p s);
  122 static int ng_btsocket_rfcomm_session_receive
  123         (ng_btsocket_rfcomm_session_p s);
  124 static int ng_btsocket_rfcomm_session_send
  125         (ng_btsocket_rfcomm_session_p s);
  126 static void ng_btsocket_rfcomm_session_clean
  127         (ng_btsocket_rfcomm_session_p s);
  128 static void ng_btsocket_rfcomm_session_process_pcb
  129         (ng_btsocket_rfcomm_session_p s);
  130 static ng_btsocket_rfcomm_session_p ng_btsocket_rfcomm_session_by_addr
  131         (bdaddr_p src, bdaddr_p dst);
  132 
  133 static int ng_btsocket_rfcomm_receive_frame
  134         (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
  135 static int ng_btsocket_rfcomm_receive_sabm
  136         (ng_btsocket_rfcomm_session_p s, int dlci);
  137 static int ng_btsocket_rfcomm_receive_disc
  138         (ng_btsocket_rfcomm_session_p s, int dlci);
  139 static int ng_btsocket_rfcomm_receive_ua
  140         (ng_btsocket_rfcomm_session_p s, int dlci);
  141 static int ng_btsocket_rfcomm_receive_dm
  142         (ng_btsocket_rfcomm_session_p s, int dlci);
  143 static int ng_btsocket_rfcomm_receive_uih
  144         (ng_btsocket_rfcomm_session_p s, int dlci, int pf, struct mbuf *m0);
  145 static int ng_btsocket_rfcomm_receive_mcc
  146         (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
  147 static int ng_btsocket_rfcomm_receive_test
  148         (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
  149 static int ng_btsocket_rfcomm_receive_fc
  150         (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
  151 static int ng_btsocket_rfcomm_receive_msc
  152         (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
  153 static int ng_btsocket_rfcomm_receive_rpn
  154         (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
  155 static int ng_btsocket_rfcomm_receive_rls
  156         (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
  157 static int ng_btsocket_rfcomm_receive_pn
  158         (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
  159 static void ng_btsocket_rfcomm_set_pn
  160         (ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr, u_int8_t flow_control, 
  161          u_int8_t credits, u_int16_t mtu);
  162 
  163 static int ng_btsocket_rfcomm_send_command
  164         (ng_btsocket_rfcomm_session_p s, u_int8_t type, u_int8_t dlci);
  165 static int ng_btsocket_rfcomm_send_uih
  166         (ng_btsocket_rfcomm_session_p s, u_int8_t address, u_int8_t pf, 
  167          u_int8_t credits, struct mbuf *data);
  168 static int ng_btsocket_rfcomm_send_msc
  169         (ng_btsocket_rfcomm_pcb_p pcb);
  170 static int ng_btsocket_rfcomm_send_pn
  171         (ng_btsocket_rfcomm_pcb_p pcb);
  172 static int ng_btsocket_rfcomm_send_credits
  173         (ng_btsocket_rfcomm_pcb_p pcb);
  174 
  175 static int ng_btsocket_rfcomm_pcb_send
  176         (ng_btsocket_rfcomm_pcb_p pcb, int limit);
  177 static void ng_btsocket_rfcomm_pcb_kill
  178         (ng_btsocket_rfcomm_pcb_p pcb, int error);
  179 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_by_dlci
  180         (ng_btsocket_rfcomm_session_p s, int dlci);
  181 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_listener
  182         (bdaddr_p src, int channel);
  183 
  184 static void ng_btsocket_rfcomm_timeout
  185         (ng_btsocket_rfcomm_pcb_p pcb);
  186 static void ng_btsocket_rfcomm_untimeout
  187         (ng_btsocket_rfcomm_pcb_p pcb);
  188 static void ng_btsocket_rfcomm_process_timeout
  189         (void *xpcb);
  190 
  191 static struct mbuf * ng_btsocket_rfcomm_prepare_packet
  192         (struct sockbuf *sb, int length);
  193 
  194 /* Globals */
  195 extern int                                      ifqmaxlen;
  196 static u_int32_t                                ng_btsocket_rfcomm_debug_level;
  197 static u_int32_t                                ng_btsocket_rfcomm_timo;
  198 struct task                                     ng_btsocket_rfcomm_task;
  199 static LIST_HEAD(, ng_btsocket_rfcomm_session)  ng_btsocket_rfcomm_sessions;
  200 static struct mtx                               ng_btsocket_rfcomm_sessions_mtx;
  201 static LIST_HEAD(, ng_btsocket_rfcomm_pcb)      ng_btsocket_rfcomm_sockets;
  202 static struct mtx                               ng_btsocket_rfcomm_sockets_mtx;
  203 static struct timeval                           ng_btsocket_rfcomm_lasttime;
  204 static int                                      ng_btsocket_rfcomm_curpps;
  205 
  206 /* Sysctl tree */
  207 SYSCTL_DECL(_net_bluetooth_rfcomm_sockets);
  208 static SYSCTL_NODE(_net_bluetooth_rfcomm_sockets, OID_AUTO, stream,
  209     CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
  210     "Bluetooth STREAM RFCOMM sockets family");
  211 SYSCTL_UINT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, debug_level,
  212         CTLFLAG_RW,
  213         &ng_btsocket_rfcomm_debug_level, NG_BTSOCKET_INFO_LEVEL,
  214         "Bluetooth STREAM RFCOMM sockets debug level");
  215 SYSCTL_UINT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, timeout,
  216         CTLFLAG_RW,
  217         &ng_btsocket_rfcomm_timo, 60,
  218         "Bluetooth STREAM RFCOMM sockets timeout");
  219 
  220 /*****************************************************************************
  221  *****************************************************************************
  222  **                              RFCOMM CRC
  223  *****************************************************************************
  224  *****************************************************************************/
  225 
  226 static u_int8_t ng_btsocket_rfcomm_crc_table[256] = {
  227         0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
  228         0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
  229         0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
  230         0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
  231 
  232         0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
  233         0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
  234         0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
  235         0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
  236 
  237         0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
  238         0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
  239         0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
  240         0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
  241 
  242         0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
  243         0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
  244         0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
  245         0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
  246 
  247         0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
  248         0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
  249         0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
  250         0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
  251 
  252         0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
  253         0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
  254         0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
  255         0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
  256 
  257         0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
  258         0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
  259         0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
  260         0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
  261 
  262         0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
  263         0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
  264         0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
  265         0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
  266 };
  267 
  268 /* CRC */
  269 static u_int8_t
  270 ng_btsocket_rfcomm_crc(u_int8_t *data, int length)
  271 {
  272         u_int8_t        crc = 0xff;
  273 
  274         while (length --)
  275                 crc = ng_btsocket_rfcomm_crc_table[crc ^ *data++];
  276 
  277         return (crc);
  278 } /* ng_btsocket_rfcomm_crc */
  279 
  280 /* FCS on 2 bytes */
  281 static u_int8_t
  282 ng_btsocket_rfcomm_fcs2(u_int8_t *data)
  283 {
  284         return (0xff - ng_btsocket_rfcomm_crc(data, 2));
  285 } /* ng_btsocket_rfcomm_fcs2 */
  286   
  287 /* FCS on 3 bytes */
  288 static u_int8_t
  289 ng_btsocket_rfcomm_fcs3(u_int8_t *data)
  290 {
  291         return (0xff - ng_btsocket_rfcomm_crc(data, 3));
  292 } /* ng_btsocket_rfcomm_fcs3 */
  293 
  294 /* 
  295  * Check FCS
  296  *
  297  * From Bluetooth spec
  298  *
  299  * "... In 07.10, the frame check sequence (FCS) is calculated on different 
  300  * sets of fields for different frame types. These are the fields that the 
  301  * FCS are calculated on:
  302  *
  303  * For SABM, DISC, UA, DM frames: on Address, Control and length field.
  304  * For UIH frames: on Address and Control field.
  305  *
  306  * (This is stated here for clarification, and to set the standard for RFCOMM;
  307  * the fields included in FCS calculation have actually changed in version
  308  * 7.0.0 of TS 07.10, but RFCOMM will not change the FCS calculation scheme
  309  * from the one above.) ..."
  310  */
  311 
  312 static int
  313 ng_btsocket_rfcomm_check_fcs(u_int8_t *data, int type, u_int8_t fcs)
  314 {
  315         if (type != RFCOMM_FRAME_UIH)
  316                 return (ng_btsocket_rfcomm_fcs3(data) != fcs);
  317 
  318         return (ng_btsocket_rfcomm_fcs2(data) != fcs);
  319 } /* ng_btsocket_rfcomm_check_fcs */
  320 
  321 /*****************************************************************************
  322  *****************************************************************************
  323  **                              Socket interface
  324  *****************************************************************************
  325  *****************************************************************************/
  326 
  327 /* 
  328  * Initialize everything
  329  */
  330 
  331 static void
  332 ng_btsocket_rfcomm_init(void *arg __unused)
  333 {
  334 
  335         ng_btsocket_rfcomm_debug_level = NG_BTSOCKET_WARN_LEVEL;
  336         ng_btsocket_rfcomm_timo = 60;
  337 
  338         /* RFCOMM task */
  339         TASK_INIT(&ng_btsocket_rfcomm_task, 0,
  340                 ng_btsocket_rfcomm_sessions_task, NULL);
  341 
  342         /* RFCOMM sessions list */
  343         LIST_INIT(&ng_btsocket_rfcomm_sessions);
  344         mtx_init(&ng_btsocket_rfcomm_sessions_mtx,
  345                 "btsocks_rfcomm_sessions_mtx", NULL, MTX_DEF);
  346 
  347         /* RFCOMM sockets list */
  348         LIST_INIT(&ng_btsocket_rfcomm_sockets);
  349         mtx_init(&ng_btsocket_rfcomm_sockets_mtx,
  350                 "btsocks_rfcomm_sockets_mtx", NULL, MTX_DEF);
  351 } /* ng_btsocket_rfcomm_init */
  352 SYSINIT(ng_btsocket_rfcomm_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD,
  353     ng_btsocket_rfcomm_init, NULL);
  354 
  355 /*
  356  * Abort connection on socket
  357  */
  358 
  359 void
  360 ng_btsocket_rfcomm_abort(struct socket *so)
  361 {
  362 
  363         so->so_error = ECONNABORTED;
  364         (void)ng_btsocket_rfcomm_disconnect(so);
  365 } /* ng_btsocket_rfcomm_abort */
  366 
  367 void
  368 ng_btsocket_rfcomm_close(struct socket *so)
  369 {
  370 
  371         (void)ng_btsocket_rfcomm_disconnect(so);
  372 } /* ng_btsocket_rfcomm_close */
  373 
  374 /*
  375  * Accept connection on socket. Nothing to do here, socket must be connected
  376  * and ready, so just return peer address and be done with it.
  377  */
  378 
  379 int
  380 ng_btsocket_rfcomm_accept(struct socket *so, struct sockaddr **nam)
  381 {
  382         return (ng_btsocket_rfcomm_peeraddr(so, nam));
  383 } /* ng_btsocket_rfcomm_accept */
  384 
  385 /*
  386  * Create and attach new socket
  387  */
  388 
  389 int
  390 ng_btsocket_rfcomm_attach(struct socket *so, int proto, struct thread *td)
  391 {
  392         ng_btsocket_rfcomm_pcb_p        pcb = so2rfcomm_pcb(so);
  393         int                             error;
  394 
  395         /* Check socket and protocol */
  396         if (so->so_type != SOCK_STREAM)
  397                 return (ESOCKTNOSUPPORT);
  398 
  399 #if 0 /* XXX sonewconn() calls "pru_attach" with proto == 0 */
  400         if (proto != 0) 
  401                 if (proto != BLUETOOTH_PROTO_RFCOMM)
  402                         return (EPROTONOSUPPORT);
  403 #endif /* XXX */
  404 
  405         if (pcb != NULL)
  406                 return (EISCONN);
  407 
  408         /* Reserve send and receive space if it is not reserved yet */
  409         if ((so->so_snd.sb_hiwat == 0) || (so->so_rcv.sb_hiwat == 0)) {
  410                 error = soreserve(so, NG_BTSOCKET_RFCOMM_SENDSPACE,
  411                                         NG_BTSOCKET_RFCOMM_RECVSPACE);
  412                 if (error != 0)
  413                         return (error);
  414         }
  415 
  416         /* Allocate the PCB */
  417         pcb = malloc(sizeof(*pcb),
  418                 M_NETGRAPH_BTSOCKET_RFCOMM, M_NOWAIT | M_ZERO);
  419         if (pcb == NULL)
  420                 return (ENOMEM);
  421 
  422         /* Link the PCB and the socket */
  423         so->so_pcb = (caddr_t) pcb;
  424         pcb->so = so;
  425 
  426         /* Initialize PCB */
  427         pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED;
  428         pcb->flags = NG_BTSOCKET_RFCOMM_DLC_CFC;
  429 
  430         pcb->lmodem =
  431         pcb->rmodem = (RFCOMM_MODEM_RTC | RFCOMM_MODEM_RTR | RFCOMM_MODEM_DV);
  432 
  433         pcb->mtu = RFCOMM_DEFAULT_MTU;
  434         pcb->tx_cred = 0;
  435         pcb->rx_cred = RFCOMM_DEFAULT_CREDITS;
  436 
  437         mtx_init(&pcb->pcb_mtx, "btsocks_rfcomm_pcb_mtx", NULL, MTX_DEF);
  438         callout_init_mtx(&pcb->timo, &pcb->pcb_mtx, 0);
  439 
  440         /* Add the PCB to the list */
  441         mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
  442         LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sockets, pcb, next);
  443         mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
  444 
  445         return (0);
  446 } /* ng_btsocket_rfcomm_attach */
  447 
  448 /*
  449  * Bind socket
  450  */
  451 
  452 int
  453 ng_btsocket_rfcomm_bind(struct socket *so, struct sockaddr *nam, 
  454                 struct thread *td)
  455 {
  456         ng_btsocket_rfcomm_pcb_t        *pcb = so2rfcomm_pcb(so), *pcb1;
  457         struct sockaddr_rfcomm          *sa = (struct sockaddr_rfcomm *) nam;
  458 
  459         if (pcb == NULL)
  460                 return (EINVAL);
  461 
  462         /* Verify address */
  463         if (sa == NULL)
  464                 return (EINVAL);
  465         if (sa->rfcomm_family != AF_BLUETOOTH)
  466                 return (EAFNOSUPPORT);
  467         if (sa->rfcomm_len != sizeof(*sa))
  468                 return (EINVAL);
  469         if (sa->rfcomm_channel > 30)
  470                 return (EINVAL);
  471 
  472         mtx_lock(&pcb->pcb_mtx);
  473 
  474         if (sa->rfcomm_channel != 0) {
  475                 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
  476 
  477                 LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next) {
  478                         if (pcb1->channel == sa->rfcomm_channel &&
  479                             bcmp(&pcb1->src, &sa->rfcomm_bdaddr,
  480                                         sizeof(pcb1->src)) == 0) {
  481                                 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
  482                                 mtx_unlock(&pcb->pcb_mtx);
  483 
  484                                 return (EADDRINUSE);
  485                         }
  486                 }
  487 
  488                 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
  489         }
  490 
  491         bcopy(&sa->rfcomm_bdaddr, &pcb->src, sizeof(pcb->src));
  492         pcb->channel = sa->rfcomm_channel;
  493 
  494         mtx_unlock(&pcb->pcb_mtx);
  495 
  496         return (0);
  497 } /* ng_btsocket_rfcomm_bind */
  498 
  499 /*
  500  * Connect socket
  501  */
  502 
  503 int
  504 ng_btsocket_rfcomm_connect(struct socket *so, struct sockaddr *nam, 
  505                 struct thread *td)
  506 {
  507         ng_btsocket_rfcomm_pcb_t        *pcb = so2rfcomm_pcb(so);
  508         struct sockaddr_rfcomm          *sa = (struct sockaddr_rfcomm *) nam;
  509         ng_btsocket_rfcomm_session_t    *s = NULL;
  510         struct socket                   *l2so = NULL;
  511         int                              dlci, error = 0;
  512 
  513         if (pcb == NULL)
  514                 return (EINVAL);
  515 
  516         /* Verify address */
  517         if (sa == NULL)
  518                 return (EINVAL);
  519         if (sa->rfcomm_family != AF_BLUETOOTH)
  520                 return (EAFNOSUPPORT);
  521         if (sa->rfcomm_len != sizeof(*sa))
  522                 return (EINVAL);
  523         if (sa->rfcomm_channel > 30)
  524                 return (EINVAL);
  525         if (sa->rfcomm_channel == 0 ||
  526             bcmp(&sa->rfcomm_bdaddr, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
  527                 return (EDESTADDRREQ);
  528 
  529         /*
  530          * Note that we will not check for errors in socreate() because
  531          * if we failed to create L2CAP socket at this point we still
  532          * might have already open session.
  533          */
  534 
  535         error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET,
  536                         BLUETOOTH_PROTO_L2CAP, td->td_ucred, td);
  537 
  538         /* 
  539          * Look for session between "pcb->src" and "sa->rfcomm_bdaddr" (dst)
  540          */
  541 
  542         mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
  543 
  544         s = ng_btsocket_rfcomm_session_by_addr(&pcb->src, &sa->rfcomm_bdaddr);
  545         if (s == NULL) {
  546                 /*
  547                  * We need to create new RFCOMM session. Check if we have L2CAP
  548                  * socket. If l2so == NULL then error has the error code from
  549                  * socreate()
  550                  */
  551 
  552                 if (l2so == NULL) {
  553                         mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
  554                         return (error);
  555                 }
  556 
  557                 error = ng_btsocket_rfcomm_session_create(&s, l2so,
  558                                 &pcb->src, &sa->rfcomm_bdaddr, td);
  559                 if (error != 0) {
  560                         mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
  561                         soclose(l2so);
  562 
  563                         return (error);
  564                 }
  565         } else if (l2so != NULL)
  566                 soclose(l2so); /* we don't need new L2CAP socket */
  567 
  568         /*
  569          * Check if we already have the same DLCI the same session
  570          */
  571 
  572         mtx_lock(&s->session_mtx);
  573         mtx_lock(&pcb->pcb_mtx);
  574 
  575         dlci = RFCOMM_MKDLCI(!INITIATOR(s), sa->rfcomm_channel);
  576 
  577         if (ng_btsocket_rfcomm_pcb_by_dlci(s, dlci) != NULL) {
  578                 mtx_unlock(&pcb->pcb_mtx);
  579                 mtx_unlock(&s->session_mtx);
  580                 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
  581 
  582                 return (EBUSY);
  583         }
  584 
  585         /*
  586          * Check session state and if its not acceptable then refuse connection
  587          */
  588 
  589         switch (s->state) {
  590         case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
  591         case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
  592         case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
  593                 /*
  594                  * Update destination address and channel and attach 
  595                  * DLC to the session
  596                  */
  597 
  598                 bcopy(&sa->rfcomm_bdaddr, &pcb->dst, sizeof(pcb->dst));
  599                 pcb->channel = sa->rfcomm_channel;
  600                 pcb->dlci = dlci;
  601 
  602                 LIST_INSERT_HEAD(&s->dlcs, pcb, session_next);
  603                 pcb->session = s;
  604 
  605                 ng_btsocket_rfcomm_timeout(pcb);
  606                 soisconnecting(pcb->so);
  607 
  608                 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_OPEN) {
  609                         pcb->mtu = s->mtu;
  610                         bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src,
  611                                 sizeof(pcb->src));
  612 
  613                         pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONFIGURING;
  614 
  615                         error = ng_btsocket_rfcomm_send_pn(pcb);
  616                         if (error == 0)
  617                                 error = ng_btsocket_rfcomm_task_wakeup();
  618                 } else
  619                         pcb->state = NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT;
  620                 break;
  621 
  622         default:
  623                 error = ECONNRESET;
  624                 break;
  625         }
  626 
  627         mtx_unlock(&pcb->pcb_mtx);
  628         mtx_unlock(&s->session_mtx);
  629         mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
  630 
  631         return (error);
  632 } /* ng_btsocket_rfcomm_connect */
  633 
  634 /*
  635  * Process ioctl's calls on socket.
  636  * XXX FIXME this should provide interface to the RFCOMM multiplexor channel
  637  */
  638 
  639 int
  640 ng_btsocket_rfcomm_control(struct socket *so, u_long cmd, void *data,
  641                 struct ifnet *ifp, struct thread *td)
  642 {
  643         return (EINVAL);
  644 } /* ng_btsocket_rfcomm_control */
  645 
  646 /*
  647  * Process getsockopt/setsockopt system calls
  648  */
  649 
  650 int
  651 ng_btsocket_rfcomm_ctloutput(struct socket *so, struct sockopt *sopt)
  652 {
  653         ng_btsocket_rfcomm_pcb_p                pcb = so2rfcomm_pcb(so);
  654         struct ng_btsocket_rfcomm_fc_info       fcinfo;
  655         int                                     error = 0;
  656 
  657         if (pcb == NULL)
  658                 return (EINVAL);
  659         if (sopt->sopt_level != SOL_RFCOMM)
  660                 return (0);
  661 
  662         mtx_lock(&pcb->pcb_mtx);
  663 
  664         switch (sopt->sopt_dir) {
  665         case SOPT_GET:
  666                 switch (sopt->sopt_name) {
  667                 case SO_RFCOMM_MTU:
  668                         error = sooptcopyout(sopt, &pcb->mtu, sizeof(pcb->mtu));
  669                         break;
  670 
  671                 case SO_RFCOMM_FC_INFO:
  672                         fcinfo.lmodem = pcb->lmodem;
  673                         fcinfo.rmodem = pcb->rmodem;
  674                         fcinfo.tx_cred = pcb->tx_cred;
  675                         fcinfo.rx_cred = pcb->rx_cred;
  676                         fcinfo.cfc = (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)?
  677                                 1 : 0;
  678                         fcinfo.reserved = 0;
  679 
  680                         error = sooptcopyout(sopt, &fcinfo, sizeof(fcinfo));
  681                         break;
  682 
  683                 default:
  684                         error = ENOPROTOOPT;
  685                         break;
  686                 }
  687                 break;
  688 
  689         case SOPT_SET:
  690                 switch (sopt->sopt_name) {
  691                 default:
  692                         error = ENOPROTOOPT;
  693                         break;
  694                 }
  695                 break;
  696 
  697         default:
  698                 error = EINVAL;
  699                 break;
  700         }
  701 
  702         mtx_unlock(&pcb->pcb_mtx);
  703 
  704         return (error);
  705 } /* ng_btsocket_rfcomm_ctloutput */
  706 
  707 /*
  708  * Detach and destroy socket
  709  */
  710 
  711 void
  712 ng_btsocket_rfcomm_detach(struct socket *so)
  713 {
  714         ng_btsocket_rfcomm_pcb_p        pcb = so2rfcomm_pcb(so);
  715 
  716         KASSERT(pcb != NULL, ("ng_btsocket_rfcomm_detach: pcb == NULL"));
  717 
  718         mtx_lock(&pcb->pcb_mtx);
  719 
  720         switch (pcb->state) {
  721         case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
  722         case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
  723         case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
  724         case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
  725                 /* XXX What to do with pending request? */
  726                 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
  727                         ng_btsocket_rfcomm_untimeout(pcb);
  728 
  729                 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT)
  730                         pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_DETACHED;
  731                 else
  732                         pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
  733 
  734                 ng_btsocket_rfcomm_task_wakeup();
  735                 break;
  736 
  737         case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
  738                 ng_btsocket_rfcomm_task_wakeup();
  739                 break;
  740         }
  741 
  742         while (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CLOSED)
  743                 msleep(&pcb->state, &pcb->pcb_mtx, PZERO, "rf_det", 0);
  744 
  745         if (pcb->session != NULL)
  746                 panic("%s: pcb->session != NULL\n", __func__);
  747         if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
  748                 panic("%s: timeout on closed DLC, flags=%#x\n",
  749                         __func__, pcb->flags);
  750 
  751         mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
  752         LIST_REMOVE(pcb, next);
  753         mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
  754 
  755         mtx_unlock(&pcb->pcb_mtx);
  756 
  757         mtx_destroy(&pcb->pcb_mtx);
  758         bzero(pcb, sizeof(*pcb));
  759         free(pcb, M_NETGRAPH_BTSOCKET_RFCOMM);
  760 
  761         soisdisconnected(so);
  762         so->so_pcb = NULL;
  763 } /* ng_btsocket_rfcomm_detach */
  764 
  765 /*
  766  * Disconnect socket
  767  */
  768 
  769 int
  770 ng_btsocket_rfcomm_disconnect(struct socket *so)
  771 {
  772         ng_btsocket_rfcomm_pcb_p        pcb = so2rfcomm_pcb(so);
  773 
  774         if (pcb == NULL)
  775                 return (EINVAL);
  776 
  777         mtx_lock(&pcb->pcb_mtx);
  778 
  779         if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING) {
  780                 mtx_unlock(&pcb->pcb_mtx);
  781                 return (EINPROGRESS);
  782         }
  783 
  784         /* XXX What to do with pending request? */
  785         if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
  786                 ng_btsocket_rfcomm_untimeout(pcb);
  787 
  788         switch (pcb->state) {
  789         case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING: /* XXX can we get here? */
  790         case NG_BTSOCKET_RFCOMM_DLC_CONNECTING: /* XXX can we get here? */
  791         case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
  792 
  793                 /*
  794                  * Just change DLC state and enqueue RFCOMM task. It will
  795                  * queue and send DISC on the DLC.
  796                  */ 
  797 
  798                 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
  799                 soisdisconnecting(so);
  800 
  801                 ng_btsocket_rfcomm_task_wakeup();
  802                 break;
  803 
  804         case NG_BTSOCKET_RFCOMM_DLC_CLOSED:
  805         case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
  806                 break;
  807 
  808         default:
  809                 panic("%s: Invalid DLC state=%d, flags=%#x\n",
  810                         __func__, pcb->state, pcb->flags);
  811                 break;
  812         }
  813 
  814         mtx_unlock(&pcb->pcb_mtx);
  815 
  816         return (0);
  817 } /* ng_btsocket_rfcomm_disconnect */
  818 
  819 /*
  820  * Listen on socket. First call to listen() will create listening RFCOMM session
  821  */
  822 
  823 int
  824 ng_btsocket_rfcomm_listen(struct socket *so, int backlog, struct thread *td)
  825 {
  826         ng_btsocket_rfcomm_pcb_p         pcb = so2rfcomm_pcb(so), pcb1;
  827         ng_btsocket_rfcomm_session_p     s = NULL;
  828         struct socket                   *l2so = NULL;
  829         int                              error, socreate_error, usedchannels;
  830 
  831         if (pcb == NULL)
  832                 return (EINVAL);
  833         if (pcb->channel > 30)
  834                 return (EADDRNOTAVAIL);
  835 
  836         usedchannels = 0;
  837 
  838         mtx_lock(&pcb->pcb_mtx);
  839 
  840         if (pcb->channel == 0) {
  841                 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
  842 
  843                 LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next)
  844                         if (pcb1->channel != 0 &&
  845                             bcmp(&pcb1->src, &pcb->src, sizeof(pcb->src)) == 0)
  846                                 usedchannels |= (1 << (pcb1->channel - 1));
  847 
  848                 for (pcb->channel = 30; pcb->channel > 0; pcb->channel --)
  849                         if (!(usedchannels & (1 << (pcb->channel - 1))))
  850                                 break;
  851 
  852                 if (pcb->channel == 0) {
  853                         mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
  854                         mtx_unlock(&pcb->pcb_mtx);
  855 
  856                         return (EADDRNOTAVAIL);
  857                 }
  858 
  859                 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
  860         }
  861 
  862         mtx_unlock(&pcb->pcb_mtx);
  863 
  864         /*
  865          * Note that we will not check for errors in socreate() because
  866          * if we failed to create L2CAP socket at this point we still
  867          * might have already open session.
  868          */
  869 
  870         socreate_error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET,
  871                         BLUETOOTH_PROTO_L2CAP, td->td_ucred, td);
  872 
  873         /*
  874          * Transition the socket and session into the LISTENING state.  Check
  875          * for collisions first, as there can only be one.
  876          */
  877         mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
  878         SOCK_LOCK(so);
  879         error = solisten_proto_check(so);
  880         SOCK_UNLOCK(so);
  881         if (error != 0)
  882                 goto out;
  883 
  884         LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next)
  885                 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_LISTENING)
  886                         break;
  887 
  888         if (s == NULL) {
  889                 /*
  890                  * We need to create default RFCOMM session. Check if we have 
  891                  * L2CAP socket. If l2so == NULL then error has the error code 
  892                  * from socreate()
  893                  */
  894                 if (l2so == NULL) {
  895                         solisten_proto_abort(so);
  896                         error = socreate_error;
  897                         goto out;
  898                 }
  899 
  900                 /* 
  901                  * Create default listen RFCOMM session. The default RFCOMM 
  902                  * session will listen on ANY address.
  903                  *
  904                  * XXX FIXME Note that currently there is no way to adjust MTU
  905                  * for the default session.
  906                  */
  907                 error = ng_btsocket_rfcomm_session_create(&s, l2so,
  908                                         NG_HCI_BDADDR_ANY, NULL, td);
  909                 if (error != 0) {
  910                         solisten_proto_abort(so);
  911                         goto out;
  912                 }
  913                 l2so = NULL;
  914         }
  915         SOCK_LOCK(so);
  916         solisten_proto(so, backlog);
  917         SOCK_UNLOCK(so);
  918 out:
  919         mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
  920         /*
  921          * If we still have an l2so reference here, it's unneeded, so release
  922          * it.
  923          */
  924         if (l2so != NULL)
  925                 soclose(l2so);
  926         return (error);
  927 } /* ng_btsocket_listen */
  928 
  929 /*
  930  * Get peer address
  931  */
  932 
  933 int
  934 ng_btsocket_rfcomm_peeraddr(struct socket *so, struct sockaddr **nam)
  935 {
  936         ng_btsocket_rfcomm_pcb_p        pcb = so2rfcomm_pcb(so);
  937         struct sockaddr_rfcomm          sa;
  938 
  939         if (pcb == NULL)
  940                 return (EINVAL);
  941 
  942         bcopy(&pcb->dst, &sa.rfcomm_bdaddr, sizeof(sa.rfcomm_bdaddr));
  943         sa.rfcomm_channel = pcb->channel;
  944         sa.rfcomm_len = sizeof(sa);
  945         sa.rfcomm_family = AF_BLUETOOTH;
  946 
  947         *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT);
  948 
  949         return ((*nam == NULL)? ENOMEM : 0);
  950 } /* ng_btsocket_rfcomm_peeraddr */
  951 
  952 /*
  953  * Send data to socket
  954  */
  955 
  956 int
  957 ng_btsocket_rfcomm_send(struct socket *so, int flags, struct mbuf *m,
  958                 struct sockaddr *nam, struct mbuf *control, struct thread *td)
  959 {
  960         ng_btsocket_rfcomm_pcb_t        *pcb = so2rfcomm_pcb(so);
  961         int                              error = 0;
  962 
  963         /* Check socket and input */
  964         if (pcb == NULL || m == NULL || control != NULL) {
  965                 error = EINVAL;
  966                 goto drop;
  967         }
  968 
  969         mtx_lock(&pcb->pcb_mtx);
  970 
  971         /* Make sure DLC is connected */
  972         if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
  973                 mtx_unlock(&pcb->pcb_mtx);
  974                 error = ENOTCONN;
  975                 goto drop;
  976         }
  977 
  978         /* Put the packet on the socket's send queue and wakeup RFCOMM task */
  979         sbappend(&pcb->so->so_snd, m, flags);
  980         m = NULL;
  981 
  982         if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_SENDING)) {
  983                 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_SENDING;
  984                 error = ng_btsocket_rfcomm_task_wakeup();
  985         }
  986 
  987         mtx_unlock(&pcb->pcb_mtx);
  988 drop:
  989         NG_FREE_M(m); /* checks for != NULL */
  990         NG_FREE_M(control);
  991 
  992         return (error);
  993 } /* ng_btsocket_rfcomm_send */
  994 
  995 /*
  996  * Get socket address
  997  */
  998 
  999 int
 1000 ng_btsocket_rfcomm_sockaddr(struct socket *so, struct sockaddr **nam)
 1001 {
 1002         ng_btsocket_rfcomm_pcb_p        pcb = so2rfcomm_pcb(so);
 1003         struct sockaddr_rfcomm          sa;
 1004 
 1005         if (pcb == NULL)
 1006                 return (EINVAL);
 1007 
 1008         bcopy(&pcb->src, &sa.rfcomm_bdaddr, sizeof(sa.rfcomm_bdaddr));
 1009         sa.rfcomm_channel = pcb->channel;
 1010         sa.rfcomm_len = sizeof(sa);
 1011         sa.rfcomm_family = AF_BLUETOOTH;
 1012 
 1013         *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT);
 1014 
 1015         return ((*nam == NULL)? ENOMEM : 0);
 1016 } /* ng_btsocket_rfcomm_sockaddr */
 1017 
 1018 /*
 1019  * Upcall function for L2CAP sockets. Enqueue RFCOMM task.
 1020  */
 1021 
 1022 static int
 1023 ng_btsocket_rfcomm_upcall(struct socket *so, void *arg, int waitflag)
 1024 {
 1025         int     error;
 1026 
 1027         if (so == NULL)
 1028                 panic("%s: so == NULL\n", __func__);
 1029 
 1030         if ((error = ng_btsocket_rfcomm_task_wakeup()) != 0)
 1031                 NG_BTSOCKET_RFCOMM_ALERT(
 1032 "%s: Could not enqueue RFCOMM task, error=%d\n", __func__, error);
 1033         return (SU_OK);
 1034 } /* ng_btsocket_rfcomm_upcall */
 1035 
 1036 /*
 1037  * RFCOMM task. Will handle all RFCOMM sessions in one pass.
 1038  * XXX FIXME does not scale very well
 1039  */
 1040 
 1041 static void
 1042 ng_btsocket_rfcomm_sessions_task(void *ctx, int pending)
 1043 {
 1044         ng_btsocket_rfcomm_session_p    s = NULL, s_next = NULL;
 1045 
 1046         mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
 1047 
 1048         for (s = LIST_FIRST(&ng_btsocket_rfcomm_sessions); s != NULL; ) {
 1049                 mtx_lock(&s->session_mtx);
 1050                 s_next = LIST_NEXT(s, next);
 1051 
 1052                 ng_btsocket_rfcomm_session_task(s);
 1053 
 1054                 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_CLOSED) {
 1055                         /* Unlink and clean the session */
 1056                         LIST_REMOVE(s, next);
 1057 
 1058                         NG_BT_MBUFQ_DRAIN(&s->outq);
 1059                         if (!LIST_EMPTY(&s->dlcs))
 1060                                 panic("%s: DLC list is not empty\n", __func__);
 1061 
 1062                         /* Close L2CAP socket */
 1063                         SOCKBUF_LOCK(&s->l2so->so_rcv);
 1064                         soupcall_clear(s->l2so, SO_RCV);
 1065                         SOCKBUF_UNLOCK(&s->l2so->so_rcv);
 1066                         SOCKBUF_LOCK(&s->l2so->so_snd);
 1067                         soupcall_clear(s->l2so, SO_SND);
 1068                         SOCKBUF_UNLOCK(&s->l2so->so_snd);
 1069                         soclose(s->l2so);
 1070 
 1071                         mtx_unlock(&s->session_mtx);
 1072 
 1073                         mtx_destroy(&s->session_mtx);
 1074                         bzero(s, sizeof(*s));
 1075                         free(s, M_NETGRAPH_BTSOCKET_RFCOMM);
 1076                 } else
 1077                         mtx_unlock(&s->session_mtx);
 1078 
 1079                 s = s_next;
 1080         }
 1081 
 1082         mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
 1083 } /* ng_btsocket_rfcomm_sessions_task */
 1084 
 1085 /*
 1086  * Process RFCOMM session. Will handle all RFCOMM sockets in one pass.
 1087  */
 1088 
 1089 static void
 1090 ng_btsocket_rfcomm_session_task(ng_btsocket_rfcomm_session_p s)
 1091 {
 1092         mtx_assert(&s->session_mtx, MA_OWNED);
 1093 
 1094         if (s->l2so->so_rcv.sb_state & SBS_CANTRCVMORE) {
 1095                 NG_BTSOCKET_RFCOMM_INFO(
 1096 "%s: L2CAP connection has been terminated, so=%p, so_state=%#x, so_count=%d, " \
 1097 "state=%d, flags=%#x\n", __func__, s->l2so, s->l2so->so_state, 
 1098                         s->l2so->so_count, s->state, s->flags);
 1099 
 1100                 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
 1101                 ng_btsocket_rfcomm_session_clean(s);
 1102         }
 1103 
 1104         /* Now process upcall */
 1105         switch (s->state) {
 1106         /* Try to accept new L2CAP connection(s) */
 1107         case NG_BTSOCKET_RFCOMM_SESSION_LISTENING:
 1108                 while (ng_btsocket_rfcomm_session_accept(s) == 0)
 1109                         ;
 1110                 break;
 1111 
 1112         /* Process the results of the L2CAP connect */
 1113         case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
 1114                 ng_btsocket_rfcomm_session_process_pcb(s);
 1115 
 1116                 if (ng_btsocket_rfcomm_session_connect(s) != 0) {
 1117                         s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
 1118                         ng_btsocket_rfcomm_session_clean(s);
 1119                 } 
 1120                 break;
 1121 
 1122         /* Try to receive/send more data */
 1123         case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
 1124         case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
 1125         case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
 1126                 ng_btsocket_rfcomm_session_process_pcb(s);
 1127 
 1128                 if (ng_btsocket_rfcomm_session_receive(s) != 0) {
 1129                         s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
 1130                         ng_btsocket_rfcomm_session_clean(s);
 1131                 } else if (ng_btsocket_rfcomm_session_send(s) != 0) {
 1132                         s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
 1133                         ng_btsocket_rfcomm_session_clean(s);
 1134                 }
 1135                 break;
 1136 
 1137         case NG_BTSOCKET_RFCOMM_SESSION_CLOSED:
 1138                 break;
 1139 
 1140         default:
 1141                 panic("%s: Invalid session state=%d, flags=%#x\n",
 1142                         __func__, s->state, s->flags);
 1143                 break;
 1144         }
 1145 } /* ng_btsocket_rfcomm_session_task */
 1146 
 1147 /*
 1148  * Process RFCOMM connection indicator. Caller must hold s->session_mtx
 1149  */
 1150 
 1151 static ng_btsocket_rfcomm_pcb_p
 1152 ng_btsocket_rfcomm_connect_ind(ng_btsocket_rfcomm_session_p s, int channel)
 1153 {
 1154         ng_btsocket_rfcomm_pcb_p         pcb = NULL, pcb1 = NULL;
 1155         ng_btsocket_l2cap_pcb_p          l2pcb = NULL;
 1156         struct socket                   *so1;
 1157 
 1158         mtx_assert(&s->session_mtx, MA_OWNED);
 1159 
 1160         /*
 1161          * Try to find RFCOMM socket that listens on given source address 
 1162          * and channel. This will return the best possible match.
 1163          */
 1164 
 1165         l2pcb = so2l2cap_pcb(s->l2so);
 1166         pcb = ng_btsocket_rfcomm_pcb_listener(&l2pcb->src, channel);
 1167         if (pcb == NULL)
 1168                 return (NULL);
 1169 
 1170         /*
 1171          * Check the pending connections queue and if we have space then 
 1172          * create new socket and set proper source and destination address,
 1173          * and channel.
 1174          */
 1175 
 1176         mtx_lock(&pcb->pcb_mtx);
 1177 
 1178         CURVNET_SET(pcb->so->so_vnet);
 1179         so1 = sonewconn(pcb->so, 0);
 1180         CURVNET_RESTORE();
 1181 
 1182         mtx_unlock(&pcb->pcb_mtx);
 1183 
 1184         if (so1 == NULL)
 1185                 return (NULL);
 1186 
 1187         /*
 1188          * If we got here than we have created new socket. So complete the 
 1189          * connection. Set source and destination address from the session.
 1190          */
 1191 
 1192         pcb1 = so2rfcomm_pcb(so1);
 1193         if (pcb1 == NULL)
 1194                 panic("%s: pcb1 == NULL\n", __func__);
 1195 
 1196         mtx_lock(&pcb1->pcb_mtx);
 1197 
 1198         bcopy(&l2pcb->src, &pcb1->src, sizeof(pcb1->src));
 1199         bcopy(&l2pcb->dst, &pcb1->dst, sizeof(pcb1->dst));
 1200         pcb1->channel = channel;
 1201 
 1202         /* Link new DLC to the session. We already hold s->session_mtx */
 1203         LIST_INSERT_HEAD(&s->dlcs, pcb1, session_next);
 1204         pcb1->session = s;
 1205                         
 1206         mtx_unlock(&pcb1->pcb_mtx);
 1207 
 1208         return (pcb1);
 1209 } /* ng_btsocket_rfcomm_connect_ind */
 1210 
 1211 /*
 1212  * Process RFCOMM connect confirmation. Caller must hold s->session_mtx.
 1213  */
 1214 
 1215 static void
 1216 ng_btsocket_rfcomm_connect_cfm(ng_btsocket_rfcomm_session_p s)
 1217 {
 1218         ng_btsocket_rfcomm_pcb_p        pcb = NULL, pcb_next = NULL;
 1219         int                             error;
 1220 
 1221         mtx_assert(&s->session_mtx, MA_OWNED);
 1222 
 1223         /*
 1224          * Wake up all waiting sockets and send PN request for each of them. 
 1225          * Note that timeout already been set in ng_btsocket_rfcomm_connect()
 1226          *
 1227          * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
 1228          * will unlink DLC from the session
 1229          */
 1230 
 1231         for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
 1232                 mtx_lock(&pcb->pcb_mtx);
 1233                 pcb_next = LIST_NEXT(pcb, session_next);
 1234 
 1235                 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT) {
 1236                         pcb->mtu = s->mtu;
 1237                         bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src,
 1238                                 sizeof(pcb->src));
 1239 
 1240                         error = ng_btsocket_rfcomm_send_pn(pcb);
 1241                         if (error == 0)
 1242                                 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONFIGURING;
 1243                         else
 1244                                 ng_btsocket_rfcomm_pcb_kill(pcb, error);
 1245                 }
 1246 
 1247                 mtx_unlock(&pcb->pcb_mtx);
 1248                 pcb = pcb_next;
 1249         }
 1250 } /* ng_btsocket_rfcomm_connect_cfm */
 1251 
 1252 /*****************************************************************************
 1253  *****************************************************************************
 1254  **                              RFCOMM sessions
 1255  *****************************************************************************
 1256  *****************************************************************************/
 1257 
 1258 /*
 1259  * Create new RFCOMM session. That function WILL NOT take ownership over l2so.
 1260  * Caller MUST free l2so if function failed.
 1261  */
 1262 
 1263 static int
 1264 ng_btsocket_rfcomm_session_create(ng_btsocket_rfcomm_session_p *sp,
 1265                 struct socket *l2so, bdaddr_p src, bdaddr_p dst,
 1266                 struct thread *td)
 1267 {
 1268         ng_btsocket_rfcomm_session_p    s = NULL;
 1269         struct sockaddr_l2cap           l2sa;
 1270         struct sockopt                  l2sopt;
 1271         int                             error;
 1272         u_int16_t                       mtu;
 1273 
 1274         mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
 1275 
 1276         /* Allocate the RFCOMM session */
 1277         s = malloc(sizeof(*s),
 1278                 M_NETGRAPH_BTSOCKET_RFCOMM, M_NOWAIT | M_ZERO);
 1279         if (s == NULL)
 1280                 return (ENOMEM);
 1281 
 1282         /* Set defaults */
 1283         s->mtu = RFCOMM_DEFAULT_MTU;
 1284         s->flags = 0;
 1285         s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
 1286         NG_BT_MBUFQ_INIT(&s->outq, ifqmaxlen);
 1287 
 1288         /*
 1289          * XXX Mark session mutex as DUPOK to prevent "duplicated lock of 
 1290          * the same type" message. When accepting new L2CAP connection
 1291          * ng_btsocket_rfcomm_session_accept() holds both session mutexes 
 1292          * for "old" (accepting) session and "new" (created) session.
 1293          */
 1294 
 1295         mtx_init(&s->session_mtx, "btsocks_rfcomm_session_mtx", NULL,
 1296                 MTX_DEF|MTX_DUPOK);
 1297 
 1298         LIST_INIT(&s->dlcs);
 1299 
 1300         /* Prepare L2CAP socket */
 1301         SOCKBUF_LOCK(&l2so->so_rcv);
 1302         soupcall_set(l2so, SO_RCV, ng_btsocket_rfcomm_upcall, NULL);
 1303         SOCKBUF_UNLOCK(&l2so->so_rcv);
 1304         SOCKBUF_LOCK(&l2so->so_snd);
 1305         soupcall_set(l2so, SO_SND, ng_btsocket_rfcomm_upcall, NULL);
 1306         SOCKBUF_UNLOCK(&l2so->so_snd);
 1307         l2so->so_state |= SS_NBIO;
 1308         s->l2so = l2so;
 1309 
 1310         mtx_lock(&s->session_mtx);
 1311 
 1312         /*
 1313          * "src" == NULL and "dst" == NULL means just create session.
 1314          * caller must do the rest
 1315          */
 1316 
 1317         if (src == NULL && dst == NULL)
 1318                 goto done;
 1319 
 1320         /*
 1321          * Set incoming MTU on L2CAP socket. It is RFCOMM session default MTU 
 1322          * plus 5 bytes: RFCOMM frame header, one extra byte for length and one
 1323          * extra byte for credits.
 1324          */
 1325 
 1326         mtu = s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1;
 1327 
 1328         l2sopt.sopt_dir = SOPT_SET;
 1329         l2sopt.sopt_level = SOL_L2CAP;
 1330         l2sopt.sopt_name = SO_L2CAP_IMTU;
 1331         l2sopt.sopt_val = (void *) &mtu;
 1332         l2sopt.sopt_valsize = sizeof(mtu);
 1333         l2sopt.sopt_td = NULL;
 1334 
 1335         error = sosetopt(s->l2so, &l2sopt);
 1336         if (error != 0)
 1337                 goto bad;
 1338 
 1339         /* Bind socket to "src" address */
 1340         l2sa.l2cap_len = sizeof(l2sa);
 1341         l2sa.l2cap_family = AF_BLUETOOTH;
 1342         l2sa.l2cap_psm = (dst == NULL)? htole16(NG_L2CAP_PSM_RFCOMM) : 0;
 1343         bcopy(src, &l2sa.l2cap_bdaddr, sizeof(l2sa.l2cap_bdaddr));
 1344         l2sa.l2cap_cid = 0;
 1345         l2sa.l2cap_bdaddr_type = BDADDR_BREDR;
 1346 
 1347         error = sobind(s->l2so, (struct sockaddr *) &l2sa, td);
 1348         if (error != 0)
 1349                 goto bad;
 1350 
 1351         /* If "dst" is not NULL then initiate connect(), otherwise listen() */
 1352         if (dst == NULL) {
 1353                 s->flags = 0;
 1354                 s->state = NG_BTSOCKET_RFCOMM_SESSION_LISTENING;
 1355 
 1356                 error = solisten(s->l2so, 10, td);
 1357                 if (error != 0)
 1358                         goto bad;
 1359         } else {
 1360                 s->flags = NG_BTSOCKET_RFCOMM_SESSION_INITIATOR;
 1361                 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTING;
 1362 
 1363                 l2sa.l2cap_len = sizeof(l2sa);   
 1364                 l2sa.l2cap_family = AF_BLUETOOTH;
 1365                 l2sa.l2cap_psm = htole16(NG_L2CAP_PSM_RFCOMM);
 1366                 bcopy(dst, &l2sa.l2cap_bdaddr, sizeof(l2sa.l2cap_bdaddr));
 1367                 l2sa.l2cap_cid = 0;
 1368                 l2sa.l2cap_bdaddr_type = BDADDR_BREDR;
 1369 
 1370                 error = soconnect(s->l2so, (struct sockaddr *) &l2sa, td);
 1371                 if (error != 0)
 1372                         goto bad;
 1373         }
 1374 
 1375 done:
 1376         LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sessions, s, next);
 1377         *sp = s;
 1378 
 1379         mtx_unlock(&s->session_mtx);
 1380 
 1381         return (0);
 1382 
 1383 bad:
 1384         mtx_unlock(&s->session_mtx);
 1385 
 1386         /* Return L2CAP socket back to its original state */
 1387         SOCKBUF_LOCK(&l2so->so_rcv);
 1388         soupcall_clear(s->l2so, SO_RCV);
 1389         SOCKBUF_UNLOCK(&l2so->so_rcv);
 1390         SOCKBUF_LOCK(&l2so->so_snd);
 1391         soupcall_clear(s->l2so, SO_SND);
 1392         SOCKBUF_UNLOCK(&l2so->so_snd);
 1393         l2so->so_state &= ~SS_NBIO;
 1394 
 1395         mtx_destroy(&s->session_mtx);
 1396         bzero(s, sizeof(*s));
 1397         free(s, M_NETGRAPH_BTSOCKET_RFCOMM);
 1398 
 1399         return (error);
 1400 } /* ng_btsocket_rfcomm_session_create */
 1401 
 1402 /*
 1403  * Process accept() on RFCOMM session
 1404  * XXX FIXME locking for "l2so"?
 1405  */
 1406 
 1407 static int
 1408 ng_btsocket_rfcomm_session_accept(ng_btsocket_rfcomm_session_p s0)
 1409 {
 1410         struct socket                   *l2so;
 1411         struct sockaddr_l2cap           *l2sa = NULL;
 1412         ng_btsocket_l2cap_pcb_t         *l2pcb = NULL;
 1413         ng_btsocket_rfcomm_session_p     s = NULL;
 1414         int                              error;
 1415 
 1416         mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
 1417         mtx_assert(&s0->session_mtx, MA_OWNED);
 1418 
 1419         SOLISTEN_LOCK(s0->l2so);
 1420         error = solisten_dequeue(s0->l2so, &l2so, 0);
 1421         if (error == EWOULDBLOCK)
 1422                 return (error);
 1423         if (error) {
 1424                 NG_BTSOCKET_RFCOMM_ERR(
 1425 "%s: Could not accept connection on L2CAP socket, error=%d\n", __func__, error);
 1426                 return (error);
 1427         }
 1428 
 1429         error = soaccept(l2so, (struct sockaddr **) &l2sa);
 1430         if (error != 0) {
 1431                 NG_BTSOCKET_RFCOMM_ERR(
 1432 "%s: soaccept() on L2CAP socket failed, error=%d\n", __func__, error);
 1433                 soclose(l2so);
 1434 
 1435                 return (error);
 1436         }
 1437 
 1438         /*
 1439          * Check if there is already active RFCOMM session between two devices.
 1440          * If so then close L2CAP connection. We only support one RFCOMM session
 1441          * between each pair of devices. Note that here we assume session in any
 1442          * state. The session even could be in the middle of disconnecting.
 1443          */
 1444 
 1445         l2pcb = so2l2cap_pcb(l2so);
 1446         s = ng_btsocket_rfcomm_session_by_addr(&l2pcb->src, &l2pcb->dst);
 1447         if (s == NULL) {
 1448                 /* Create a new RFCOMM session */
 1449                 error = ng_btsocket_rfcomm_session_create(&s, l2so, NULL, NULL,
 1450                                 curthread /* XXX */);
 1451                 if (error == 0) {
 1452                         mtx_lock(&s->session_mtx);
 1453 
 1454                         s->flags = 0;
 1455                         s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
 1456 
 1457                         /*
 1458                          * Adjust MTU on incoming connection. Reserve 5 bytes:
 1459                          * RFCOMM frame header, one extra byte for length and 
 1460                          * one extra byte for credits.
 1461                          */
 1462 
 1463                         s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
 1464                                         sizeof(struct rfcomm_frame_hdr) - 1 - 1;
 1465 
 1466                         mtx_unlock(&s->session_mtx);
 1467                 } else {
 1468                         NG_BTSOCKET_RFCOMM_ALERT(
 1469 "%s: Failed to create new RFCOMM session, error=%d\n", __func__, error);
 1470 
 1471                         soclose(l2so);
 1472                 }
 1473         } else {
 1474                 NG_BTSOCKET_RFCOMM_WARN(
 1475 "%s: Rejecting duplicating RFCOMM session between src=%x:%x:%x:%x:%x:%x and " \
 1476 "dst=%x:%x:%x:%x:%x:%x, state=%d, flags=%#x\n", __func__,
 1477                         l2pcb->src.b[5], l2pcb->src.b[4], l2pcb->src.b[3],
 1478                         l2pcb->src.b[2], l2pcb->src.b[1], l2pcb->src.b[0],
 1479                         l2pcb->dst.b[5], l2pcb->dst.b[4], l2pcb->dst.b[3],
 1480                         l2pcb->dst.b[2], l2pcb->dst.b[1], l2pcb->dst.b[0],
 1481                         s->state, s->flags);
 1482 
 1483                 error = EBUSY;
 1484                 soclose(l2so);
 1485         }
 1486 
 1487         return (error);
 1488 } /* ng_btsocket_rfcomm_session_accept */
 1489 
 1490 /*
 1491  * Process connect() on RFCOMM session
 1492  * XXX FIXME locking for "l2so"?
 1493  */
 1494 
 1495 static int
 1496 ng_btsocket_rfcomm_session_connect(ng_btsocket_rfcomm_session_p s)
 1497 {
 1498         ng_btsocket_l2cap_pcb_p l2pcb = so2l2cap_pcb(s->l2so);
 1499         int                     error;
 1500 
 1501         mtx_assert(&s->session_mtx, MA_OWNED);
 1502 
 1503         /* First check if connection has failed */
 1504         if ((error = s->l2so->so_error) != 0) {
 1505                 s->l2so->so_error = 0;
 1506 
 1507                 NG_BTSOCKET_RFCOMM_ERR(
 1508 "%s: Could not connect RFCOMM session, error=%d, state=%d, flags=%#x\n",
 1509                         __func__, error, s->state, s->flags);
 1510 
 1511                 return (error);
 1512         }
 1513 
 1514         /* Is connection still in progress? */
 1515         if (s->l2so->so_state & SS_ISCONNECTING)
 1516                 return (0); 
 1517 
 1518         /* 
 1519          * If we got here then we are connected. Send SABM on DLCI 0 to 
 1520          * open multiplexor channel.
 1521          */
 1522 
 1523         if (error == 0) {
 1524                 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
 1525 
 1526                 /*
 1527                  * Adjust MTU on outgoing connection. Reserve 5 bytes: RFCOMM 
 1528                  * frame header, one extra byte for length and one extra byte 
 1529                  * for credits.
 1530                  */
 1531 
 1532                 s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
 1533                                 sizeof(struct rfcomm_frame_hdr) - 1 - 1;
 1534 
 1535                 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_SABM,0);
 1536                 if (error == 0)
 1537                         error = ng_btsocket_rfcomm_task_wakeup();
 1538         }
 1539 
 1540         return (error);
 1541 }/* ng_btsocket_rfcomm_session_connect */
 1542 
 1543 /*
 1544  * Receive data on RFCOMM session
 1545  * XXX FIXME locking for "l2so"?
 1546  */
 1547 
 1548 static int
 1549 ng_btsocket_rfcomm_session_receive(ng_btsocket_rfcomm_session_p s)
 1550 {
 1551         struct mbuf     *m = NULL;
 1552         struct uio       uio;
 1553         int              more, flags, error;
 1554 
 1555         mtx_assert(&s->session_mtx, MA_OWNED);
 1556 
 1557         /* Can we read from the L2CAP socket? */
 1558         if (!soreadable(s->l2so))
 1559                 return (0);
 1560 
 1561         /* First check for error on L2CAP socket */
 1562         if ((error = s->l2so->so_error) != 0) {
 1563                 s->l2so->so_error = 0;
 1564 
 1565                 NG_BTSOCKET_RFCOMM_ERR(
 1566 "%s: Could not receive data from L2CAP socket, error=%d, state=%d, flags=%#x\n",
 1567                         __func__, error, s->state, s->flags);
 1568 
 1569                 return (error);
 1570         }
 1571 
 1572         /*
 1573          * Read all packets from the L2CAP socket. 
 1574          * XXX FIXME/VERIFY is that correct? For now use m->m_nextpkt as
 1575          * indication that there is more packets on the socket's buffer.
 1576          * Also what should we use in uio.uio_resid?
 1577          * May be s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1?
 1578          */
 1579 
 1580         for (more = 1; more; ) {
 1581                 /* Try to get next packet from socket */
 1582                 bzero(&uio, sizeof(uio));
 1583 /*              uio.uio_td = NULL; */
 1584                 uio.uio_resid = 1000000000;
 1585                 flags = MSG_DONTWAIT;
 1586 
 1587                 m = NULL;
 1588                 error = soreceive(s->l2so, NULL, &uio, &m,
 1589                     (struct mbuf **) NULL, &flags);
 1590                 if (error != 0) {
 1591                         if (error == EWOULDBLOCK)
 1592                                 return (0); /* XXX can happen? */
 1593 
 1594                         NG_BTSOCKET_RFCOMM_ERR(
 1595 "%s: Could not receive data from L2CAP socket, error=%d\n", __func__, error);
 1596 
 1597                         return (error);
 1598                 }
 1599 
 1600                 more = (m->m_nextpkt != NULL);
 1601                 m->m_nextpkt = NULL;
 1602 
 1603                 ng_btsocket_rfcomm_receive_frame(s, m);
 1604         }
 1605 
 1606         return (0);
 1607 } /* ng_btsocket_rfcomm_session_receive */
 1608 
 1609 /*
 1610  * Send data on RFCOMM session
 1611  * XXX FIXME locking for "l2so"?
 1612  */
 1613 
 1614 static int
 1615 ng_btsocket_rfcomm_session_send(ng_btsocket_rfcomm_session_p s)
 1616 {
 1617         struct mbuf     *m = NULL;
 1618         int              error;
 1619 
 1620         mtx_assert(&s->session_mtx, MA_OWNED);
 1621 
 1622         /* Send as much as we can from the session queue */
 1623         while (sowriteable(s->l2so)) {
 1624                 /* Check if socket still OK */
 1625                 if ((error = s->l2so->so_error) != 0) {
 1626                         s->l2so->so_error = 0;
 1627 
 1628                         NG_BTSOCKET_RFCOMM_ERR(
 1629 "%s: Detected error=%d on L2CAP socket, state=%d, flags=%#x\n",
 1630                                 __func__, error, s->state, s->flags);
 1631 
 1632                         return (error);
 1633                 }
 1634 
 1635                 NG_BT_MBUFQ_DEQUEUE(&s->outq, m);
 1636                 if (m == NULL)
 1637                         return (0); /* we are done */
 1638 
 1639                 /* Call send function on the L2CAP socket */
 1640                 error = s->l2so->so_proto->pr_send(s->l2so, 0, m, NULL, NULL,
 1641                     curthread /* XXX */);
 1642                 if (error != 0) {
 1643                         NG_BTSOCKET_RFCOMM_ERR(
 1644 "%s: Could not send data to L2CAP socket, error=%d\n", __func__, error);
 1645 
 1646                         return (error);
 1647                 }
 1648         }
 1649 
 1650         return (0);
 1651 } /* ng_btsocket_rfcomm_session_send */
 1652 
 1653 /*
 1654  * Close and disconnect all DLCs for the given session. Caller must hold 
 1655  * s->sesson_mtx. Will wakeup session.
 1656  */
 1657 
 1658 static void
 1659 ng_btsocket_rfcomm_session_clean(ng_btsocket_rfcomm_session_p s)
 1660 {
 1661         ng_btsocket_rfcomm_pcb_p        pcb = NULL, pcb_next = NULL;
 1662         int                             error;
 1663 
 1664         mtx_assert(&s->session_mtx, MA_OWNED);
 1665 
 1666         /*
 1667          * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
 1668          * will unlink DLC from the session
 1669          */
 1670 
 1671         for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
 1672                 mtx_lock(&pcb->pcb_mtx);
 1673                 pcb_next = LIST_NEXT(pcb, session_next);
 1674 
 1675                 NG_BTSOCKET_RFCOMM_INFO(
 1676 "%s: Disconnecting dlci=%d, state=%d, flags=%#x\n",
 1677                         __func__, pcb->dlci, pcb->state, pcb->flags);
 1678 
 1679                 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
 1680                         error = ECONNRESET;
 1681                 else
 1682                         error = ECONNREFUSED;
 1683 
 1684                 ng_btsocket_rfcomm_pcb_kill(pcb, error);
 1685 
 1686                 mtx_unlock(&pcb->pcb_mtx);
 1687                 pcb = pcb_next;
 1688         }
 1689 } /* ng_btsocket_rfcomm_session_clean */
 1690 
 1691 /*
 1692  * Process all DLCs on the session. Caller MUST hold s->session_mtx.
 1693  */
 1694 
 1695 static void
 1696 ng_btsocket_rfcomm_session_process_pcb(ng_btsocket_rfcomm_session_p s)
 1697 {
 1698         ng_btsocket_rfcomm_pcb_p        pcb = NULL, pcb_next = NULL;
 1699         int                             error;
 1700 
 1701         mtx_assert(&s->session_mtx, MA_OWNED);
 1702 
 1703         /*
 1704          * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
 1705          * will unlink DLC from the session
 1706          */
 1707 
 1708         for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
 1709                 mtx_lock(&pcb->pcb_mtx);
 1710                 pcb_next = LIST_NEXT(pcb, session_next);
 1711 
 1712                 switch (pcb->state) {
 1713                 /*
 1714                  * If DLC in W4_CONNECT state then we should check for both
 1715                  * timeout and detach.
 1716                  */
 1717 
 1718                 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
 1719                         if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_DETACHED)
 1720                                 ng_btsocket_rfcomm_pcb_kill(pcb, 0);
 1721                         else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
 1722                                 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
 1723                         break;
 1724 
 1725                 /*
 1726                  * If DLC in CONFIGURING or CONNECTING state then we only
 1727                  * should check for timeout. If detach() was called then
 1728                  * DLC will be moved into DISCONNECTING state.
 1729                  */
 1730 
 1731                 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
 1732                 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
 1733                         if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
 1734                                 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
 1735                         break;
 1736 
 1737                 /*
 1738                  * If DLC in CONNECTED state then we need to send data (if any)
 1739                  * from the socket's send queue. Note that we will send data
 1740                  * from either all sockets or none. This may overload session's
 1741                  * outgoing queue (but we do not check for that).
 1742                  *
 1743                  * XXX FIXME need scheduler for RFCOMM sockets
 1744                  */
 1745 
 1746                 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
 1747                         error = ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
 1748                         if (error != 0)
 1749                                 ng_btsocket_rfcomm_pcb_kill(pcb, error);
 1750                         break;
 1751 
 1752                 /*
 1753                  * If DLC in DISCONNECTING state then we must send DISC frame.
 1754                  * Note that if DLC has timeout set then we do not need to 
 1755                  * resend DISC frame.
 1756                  *
 1757                  * XXX FIXME need to drain all data from the socket's queue
 1758                  * if LINGER option was set
 1759                  */
 1760 
 1761                 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
 1762                         if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
 1763                                 error = ng_btsocket_rfcomm_send_command(
 1764                                                 pcb->session, RFCOMM_FRAME_DISC,
 1765                                                 pcb->dlci);
 1766                                 if (error == 0)
 1767                                         ng_btsocket_rfcomm_timeout(pcb);
 1768                                 else
 1769                                         ng_btsocket_rfcomm_pcb_kill(pcb, error);
 1770                         } else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
 1771                                 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
 1772                         break;
 1773                 
 1774 /*              case NG_BTSOCKET_RFCOMM_DLC_CLOSED: */
 1775                 default:
 1776                         panic("%s: Invalid DLC state=%d, flags=%#x\n",
 1777                                 __func__, pcb->state, pcb->flags);
 1778                         break;
 1779                 }
 1780 
 1781                 mtx_unlock(&pcb->pcb_mtx);
 1782                 pcb = pcb_next;
 1783         }
 1784 } /* ng_btsocket_rfcomm_session_process_pcb */
 1785 
 1786 /*
 1787  * Find RFCOMM session between "src" and "dst".
 1788  * Caller MUST hold ng_btsocket_rfcomm_sessions_mtx.
 1789  */
 1790 
 1791 static ng_btsocket_rfcomm_session_p
 1792 ng_btsocket_rfcomm_session_by_addr(bdaddr_p src, bdaddr_p dst)
 1793 {
 1794         ng_btsocket_rfcomm_session_p    s = NULL;
 1795         ng_btsocket_l2cap_pcb_p         l2pcb = NULL;
 1796         int                             any_src;
 1797 
 1798         mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
 1799 
 1800         any_src = (bcmp(src, NG_HCI_BDADDR_ANY, sizeof(*src)) == 0);
 1801 
 1802         LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next) {
 1803                 l2pcb = so2l2cap_pcb(s->l2so);
 1804 
 1805                 if ((any_src || bcmp(&l2pcb->src, src, sizeof(*src)) == 0) &&
 1806                     bcmp(&l2pcb->dst, dst, sizeof(*dst)) == 0)
 1807                         break;
 1808         }
 1809 
 1810         return (s);
 1811 } /* ng_btsocket_rfcomm_session_by_addr */
 1812 
 1813 /*****************************************************************************
 1814  *****************************************************************************
 1815  **                                  RFCOMM 
 1816  *****************************************************************************
 1817  *****************************************************************************/
 1818 
 1819 /*
 1820  * Process incoming RFCOMM frame. Caller must hold s->session_mtx.
 1821  * XXX FIXME check frame length
 1822  */
 1823 
 1824 static int
 1825 ng_btsocket_rfcomm_receive_frame(ng_btsocket_rfcomm_session_p s,
 1826                 struct mbuf *m0)
 1827 {
 1828         struct rfcomm_frame_hdr *hdr = NULL;
 1829         struct mbuf             *m = NULL;
 1830         u_int16_t                length;
 1831         u_int8_t                 dlci, type;
 1832         int                      error = 0;
 1833 
 1834         mtx_assert(&s->session_mtx, MA_OWNED);
 1835 
 1836         /* Pullup as much as we can into first mbuf (for direct access) */
 1837         length = min(m0->m_pkthdr.len, MHLEN);
 1838         if (m0->m_len < length) {
 1839                 if ((m0 = m_pullup(m0, length)) == NULL) {
 1840                         NG_BTSOCKET_RFCOMM_ALERT(
 1841 "%s: m_pullup(%d) failed\n", __func__, length);
 1842 
 1843                         return (ENOBUFS);
 1844                 }
 1845         }
 1846 
 1847         hdr = mtod(m0, struct rfcomm_frame_hdr *);
 1848         dlci = RFCOMM_DLCI(hdr->address);
 1849         type = RFCOMM_TYPE(hdr->control);
 1850 
 1851         /* Test EA bit in length. If not set then we have 2 bytes of length */
 1852         if (!RFCOMM_EA(hdr->length)) {
 1853                 bcopy(&hdr->length, &length, sizeof(length));
 1854                 length = le16toh(length) >> 1;
 1855                 m_adj(m0, sizeof(*hdr) + 1);
 1856         } else {
 1857                 length = hdr->length >> 1;
 1858                 m_adj(m0, sizeof(*hdr));
 1859         }
 1860 
 1861         NG_BTSOCKET_RFCOMM_INFO(
 1862 "%s: Got frame type=%#x, dlci=%d, length=%d, cr=%d, pf=%d, len=%d\n",
 1863                 __func__, type, dlci, length, RFCOMM_CR(hdr->address),
 1864                 RFCOMM_PF(hdr->control), m0->m_pkthdr.len);
 1865 
 1866         /*
 1867          * Get FCS (the last byte in the frame)
 1868          * XXX this will not work if mbuf chain ends with empty mbuf.
 1869          * XXX let's hope it never happens :)
 1870          */
 1871 
 1872         for (m = m0; m->m_next != NULL; m = m->m_next)
 1873                 ;
 1874         if (m->m_len <= 0)
 1875                 panic("%s: Empty mbuf at the end of the chain, len=%d\n",
 1876                         __func__, m->m_len);
 1877 
 1878         /*
 1879          * Check FCS. We only need to calculate FCS on first 2 or 3 bytes
 1880          * and already m_pullup'ed mbuf chain, so it should be safe.
 1881          */
 1882 
 1883         if (ng_btsocket_rfcomm_check_fcs((u_int8_t *) hdr, type, m->m_data[m->m_len - 1])) {
 1884                 NG_BTSOCKET_RFCOMM_ERR(
 1885 "%s: Invalid RFCOMM packet. Bad checksum\n", __func__);
 1886                 NG_FREE_M(m0);
 1887 
 1888                 return (EINVAL);
 1889         }
 1890 
 1891         m_adj(m0, -1); /* Trim FCS byte */
 1892 
 1893         /*
 1894          * Process RFCOMM frame.
 1895          *
 1896          * From TS 07.10 spec
 1897          * 
 1898          * "... In the case where a SABM or DISC command with the P bit set
 1899          * to 0 is received then the received frame shall be discarded..."
 1900          *
 1901          * "... If a unsolicited DM response is received then the frame shall
 1902          * be processed irrespective of the P/F setting... "
 1903          *
 1904          * "... The station may transmit response frames with the F bit set 
 1905          * to 0 at any opportunity on an asynchronous basis. However, in the 
 1906          * case where a UA response is received with the F bit set to 0 then 
 1907          * the received frame shall be discarded..."
 1908          *
 1909          * From Bluetooth spec
 1910          *
 1911          * "... When credit based flow control is being used, the meaning of
 1912          * the P/F bit in the control field of the RFCOMM header is redefined
 1913          * for UIH frames..."
 1914          */
 1915 
 1916         switch (type) {
 1917         case RFCOMM_FRAME_SABM:
 1918                 if (RFCOMM_PF(hdr->control))
 1919                         error = ng_btsocket_rfcomm_receive_sabm(s, dlci);
 1920                 break;
 1921 
 1922         case RFCOMM_FRAME_DISC:
 1923                 if (RFCOMM_PF(hdr->control))
 1924                         error = ng_btsocket_rfcomm_receive_disc(s, dlci);
 1925                 break;
 1926 
 1927         case RFCOMM_FRAME_UA:
 1928                 if (RFCOMM_PF(hdr->control))
 1929                         error = ng_btsocket_rfcomm_receive_ua(s, dlci);
 1930                 break;
 1931 
 1932         case RFCOMM_FRAME_DM:
 1933                 error = ng_btsocket_rfcomm_receive_dm(s, dlci);
 1934                 break;
 1935 
 1936         case RFCOMM_FRAME_UIH:
 1937                 if (dlci == 0)
 1938                         error = ng_btsocket_rfcomm_receive_mcc(s, m0);
 1939                 else
 1940                         error = ng_btsocket_rfcomm_receive_uih(s, dlci,
 1941                                         RFCOMM_PF(hdr->control), m0);
 1942 
 1943                 return (error);
 1944                 /* NOT REACHED */
 1945 
 1946         default:
 1947                 NG_BTSOCKET_RFCOMM_ERR(
 1948 "%s: Invalid RFCOMM packet. Unknown type=%#x\n", __func__, type);
 1949                 error = EINVAL;
 1950                 break;
 1951         }
 1952 
 1953         NG_FREE_M(m0);
 1954 
 1955         return (error);
 1956 } /* ng_btsocket_rfcomm_receive_frame */
 1957 
 1958 /*
 1959  * Process RFCOMM SABM frame
 1960  */
 1961 
 1962 static int
 1963 ng_btsocket_rfcomm_receive_sabm(ng_btsocket_rfcomm_session_p s, int dlci)
 1964 {
 1965         ng_btsocket_rfcomm_pcb_p        pcb = NULL;
 1966         int                             error = 0;
 1967 
 1968         mtx_assert(&s->session_mtx, MA_OWNED);
 1969 
 1970         NG_BTSOCKET_RFCOMM_INFO(
 1971 "%s: Got SABM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
 1972                 __func__, s->state, s->flags, s->mtu, dlci);
 1973 
 1974         /* DLCI == 0 means open multiplexor channel */
 1975         if (dlci == 0) {
 1976                 switch (s->state) {
 1977                 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
 1978                 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
 1979                         error = ng_btsocket_rfcomm_send_command(s,
 1980                                         RFCOMM_FRAME_UA, dlci);
 1981                         if (error == 0) {
 1982                                 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
 1983                                 ng_btsocket_rfcomm_connect_cfm(s);
 1984                         } else {
 1985                                 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
 1986                                 ng_btsocket_rfcomm_session_clean(s);
 1987                         }
 1988                         break;
 1989 
 1990                 default:
 1991                         NG_BTSOCKET_RFCOMM_WARN(
 1992 "%s: Got SABM for session in invalid state state=%d, flags=%#x\n",
 1993                                 __func__, s->state, s->flags);
 1994                         error = EINVAL;
 1995                         break;
 1996                 }
 1997 
 1998                 return (error);
 1999         }
 2000 
 2001         /* Make sure multiplexor channel is open */
 2002         if (s->state != NG_BTSOCKET_RFCOMM_SESSION_OPEN) {
 2003                 NG_BTSOCKET_RFCOMM_ERR(
 2004 "%s: Got SABM for dlci=%d with multiplexor channel closed, state=%d, " \
 2005 "flags=%#x\n",          __func__, dlci, s->state, s->flags);
 2006 
 2007                 return (EINVAL);
 2008         }
 2009 
 2010         /*
 2011          * Check if we have this DLCI. This might happen when remote
 2012          * peer uses PN command before actual open (SABM) happens.
 2013          */
 2014 
 2015         pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
 2016         if (pcb != NULL) {
 2017                 mtx_lock(&pcb->pcb_mtx);
 2018 
 2019                 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING) {
 2020                         NG_BTSOCKET_RFCOMM_ERR(
 2021 "%s: Got SABM for dlci=%d in invalid state=%d, flags=%#x\n",
 2022                                 __func__, dlci, pcb->state, pcb->flags);
 2023                         mtx_unlock(&pcb->pcb_mtx);
 2024 
 2025                         return (ENOENT);
 2026                 }
 2027 
 2028                 ng_btsocket_rfcomm_untimeout(pcb);
 2029 
 2030                 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
 2031                 if (error == 0)
 2032                         error = ng_btsocket_rfcomm_send_msc(pcb);
 2033 
 2034                 if (error == 0) {
 2035                         pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
 2036                         soisconnected(pcb->so);
 2037                 } else
 2038                         ng_btsocket_rfcomm_pcb_kill(pcb, error);
 2039 
 2040                 mtx_unlock(&pcb->pcb_mtx);
 2041 
 2042                 return (error);
 2043         }
 2044 
 2045         /*
 2046          * We do not have requested DLCI, so it must be an incoming connection
 2047          * with default parameters. Try to accept it.
 2048          */ 
 2049 
 2050         pcb = ng_btsocket_rfcomm_connect_ind(s, RFCOMM_SRVCHANNEL(dlci));
 2051         if (pcb != NULL) {
 2052                 mtx_lock(&pcb->pcb_mtx);
 2053 
 2054                 pcb->dlci = dlci;
 2055 
 2056                 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
 2057                 if (error == 0)
 2058                         error = ng_btsocket_rfcomm_send_msc(pcb);
 2059 
 2060                 if (error == 0) {
 2061                         pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
 2062                         soisconnected(pcb->so);
 2063                 } else
 2064                         ng_btsocket_rfcomm_pcb_kill(pcb, error);
 2065 
 2066                 mtx_unlock(&pcb->pcb_mtx);
 2067         } else
 2068                 /* Nobody is listen()ing on the requested DLCI */
 2069                 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
 2070 
 2071         return (error);
 2072 } /* ng_btsocket_rfcomm_receive_sabm */
 2073 
 2074 /*
 2075  * Process RFCOMM DISC frame
 2076  */
 2077 
 2078 static int
 2079 ng_btsocket_rfcomm_receive_disc(ng_btsocket_rfcomm_session_p s, int dlci)
 2080 {
 2081         ng_btsocket_rfcomm_pcb_p        pcb = NULL;
 2082         int                             error = 0;
 2083 
 2084         mtx_assert(&s->session_mtx, MA_OWNED);
 2085 
 2086         NG_BTSOCKET_RFCOMM_INFO(
 2087 "%s: Got DISC, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
 2088                 __func__, s->state, s->flags, s->mtu, dlci);
 2089 
 2090         /* DLCI == 0 means close multiplexor channel */
 2091         if (dlci == 0) {
 2092                 /* XXX FIXME assume that remote side will close the socket */
 2093                 error = ng_btsocket_rfcomm_send_command(s, RFCOMM_FRAME_UA, 0);
 2094                 if (error == 0) {
 2095                         if (s->state == NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING)
 2096                                 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
 2097                         else
 2098                                 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
 2099                 } else
 2100                         s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
 2101 
 2102                 ng_btsocket_rfcomm_session_clean(s);
 2103         } else {
 2104                 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
 2105                 if (pcb != NULL) {
 2106                         int     err;
 2107 
 2108                         mtx_lock(&pcb->pcb_mtx);
 2109 
 2110                         NG_BTSOCKET_RFCOMM_INFO(
 2111 "%s: Got DISC for dlci=%d, state=%d, flags=%#x\n",
 2112                                 __func__, dlci, pcb->state, pcb->flags);
 2113 
 2114                         error = ng_btsocket_rfcomm_send_command(s,
 2115                                         RFCOMM_FRAME_UA, dlci);
 2116 
 2117                         if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
 2118                                 err = 0;
 2119                         else
 2120                                 err = ECONNREFUSED;
 2121 
 2122                         ng_btsocket_rfcomm_pcb_kill(pcb, err);
 2123 
 2124                         mtx_unlock(&pcb->pcb_mtx);
 2125                 } else {
 2126                         NG_BTSOCKET_RFCOMM_WARN(
 2127 "%s: Got DISC for non-existing dlci=%d\n", __func__, dlci);
 2128 
 2129                         error = ng_btsocket_rfcomm_send_command(s,
 2130                                         RFCOMM_FRAME_DM, dlci);
 2131                 }
 2132         }
 2133 
 2134         return (error);
 2135 } /* ng_btsocket_rfcomm_receive_disc */
 2136 
 2137 /*
 2138  * Process RFCOMM UA frame
 2139  */
 2140 
 2141 static int
 2142 ng_btsocket_rfcomm_receive_ua(ng_btsocket_rfcomm_session_p s, int dlci)
 2143 {
 2144         ng_btsocket_rfcomm_pcb_p        pcb = NULL;
 2145         int                             error = 0;
 2146 
 2147         mtx_assert(&s->session_mtx, MA_OWNED);
 2148 
 2149         NG_BTSOCKET_RFCOMM_INFO(
 2150 "%s: Got UA, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
 2151                 __func__, s->state, s->flags, s->mtu, dlci);
 2152 
 2153         /* dlci == 0 means multiplexor channel */
 2154         if (dlci == 0) {
 2155                 switch (s->state) {
 2156                 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
 2157                         s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
 2158                         ng_btsocket_rfcomm_connect_cfm(s);
 2159                         break;
 2160 
 2161                 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
 2162                         s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
 2163                         ng_btsocket_rfcomm_session_clean(s);
 2164                         break;
 2165 
 2166                 default:
 2167                         NG_BTSOCKET_RFCOMM_WARN(
 2168 "%s: Got UA for session in invalid state=%d(%d), flags=%#x, mtu=%d\n",
 2169                                 __func__, s->state, INITIATOR(s), s->flags,
 2170                                 s->mtu);
 2171                         error = ENOENT;
 2172                         break;
 2173                 }
 2174 
 2175                 return (error);
 2176         }
 2177 
 2178         /* Check if we have this DLCI */
 2179         pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
 2180         if (pcb != NULL) {
 2181                 mtx_lock(&pcb->pcb_mtx);
 2182 
 2183                 NG_BTSOCKET_RFCOMM_INFO(
 2184 "%s: Got UA for dlci=%d, state=%d, flags=%#x\n",
 2185                         __func__, dlci, pcb->state, pcb->flags);
 2186 
 2187                 switch (pcb->state) {
 2188                 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
 2189                         ng_btsocket_rfcomm_untimeout(pcb);
 2190 
 2191                         error = ng_btsocket_rfcomm_send_msc(pcb);
 2192                         if (error == 0) {
 2193                                 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
 2194                                 soisconnected(pcb->so);
 2195                         }
 2196                         break;
 2197 
 2198                 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
 2199                         ng_btsocket_rfcomm_pcb_kill(pcb, 0);
 2200                         break;
 2201 
 2202                 default:
 2203                         NG_BTSOCKET_RFCOMM_WARN(
 2204 "%s: Got UA for dlci=%d in invalid state=%d, flags=%#x\n",
 2205                                 __func__, dlci, pcb->state, pcb->flags);
 2206                         error = ENOENT;
 2207                         break;
 2208                 }
 2209 
 2210                 mtx_unlock(&pcb->pcb_mtx);
 2211         } else {
 2212                 NG_BTSOCKET_RFCOMM_WARN(
 2213 "%s: Got UA for non-existing dlci=%d\n", __func__, dlci);
 2214 
 2215                 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
 2216         }
 2217 
 2218         return (error);
 2219 } /* ng_btsocket_rfcomm_receive_ua */
 2220 
 2221 /*
 2222  * Process RFCOMM DM frame
 2223  */
 2224 
 2225 static int
 2226 ng_btsocket_rfcomm_receive_dm(ng_btsocket_rfcomm_session_p s, int dlci)
 2227 {
 2228         ng_btsocket_rfcomm_pcb_p        pcb = NULL;
 2229         int                             error;
 2230 
 2231         mtx_assert(&s->session_mtx, MA_OWNED);
 2232 
 2233         NG_BTSOCKET_RFCOMM_INFO(
 2234 "%s: Got DM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
 2235                 __func__, s->state, s->flags, s->mtu, dlci);
 2236 
 2237         /* DLCI == 0 means multiplexor channel */
 2238         if (dlci == 0) {
 2239                 /* Disconnect all dlc's on the session */
 2240                 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
 2241                 ng_btsocket_rfcomm_session_clean(s);
 2242         } else {
 2243                 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
 2244                 if (pcb != NULL) {
 2245                         mtx_lock(&pcb->pcb_mtx);
 2246 
 2247                         NG_BTSOCKET_RFCOMM_INFO(
 2248 "%s: Got DM for dlci=%d, state=%d, flags=%#x\n",
 2249                                 __func__, dlci, pcb->state, pcb->flags);
 2250 
 2251                         if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
 2252                                 error = ECONNRESET;
 2253                         else
 2254                                 error = ECONNREFUSED;
 2255 
 2256                         ng_btsocket_rfcomm_pcb_kill(pcb, error);
 2257 
 2258                         mtx_unlock(&pcb->pcb_mtx);
 2259                 } else
 2260                         NG_BTSOCKET_RFCOMM_WARN(
 2261 "%s: Got DM for non-existing dlci=%d\n", __func__, dlci);
 2262         }
 2263 
 2264         return (0);
 2265 } /* ng_btsocket_rfcomm_receive_dm */
 2266 
 2267 /*
 2268  * Process RFCOMM UIH frame (data)
 2269  */
 2270 
 2271 static int
 2272 ng_btsocket_rfcomm_receive_uih(ng_btsocket_rfcomm_session_p s, int dlci,
 2273                 int pf, struct mbuf *m0)
 2274 {
 2275         ng_btsocket_rfcomm_pcb_p        pcb = NULL;
 2276         int                             error = 0;
 2277 
 2278         mtx_assert(&s->session_mtx, MA_OWNED);
 2279 
 2280         NG_BTSOCKET_RFCOMM_INFO(
 2281 "%s: Got UIH, session state=%d, flags=%#x, mtu=%d, dlci=%d, pf=%d, len=%d\n",
 2282                 __func__, s->state, s->flags, s->mtu, dlci, pf,
 2283                 m0->m_pkthdr.len);
 2284 
 2285         /* XXX should we do it here? Check for session flow control */
 2286         if (s->flags & NG_BTSOCKET_RFCOMM_SESSION_LFC) {
 2287                 NG_BTSOCKET_RFCOMM_WARN(
 2288 "%s: Got UIH with session flow control asserted, state=%d, flags=%#x\n",
 2289                         __func__, s->state, s->flags);
 2290                 goto drop;
 2291         }
 2292 
 2293         /* Check if we have this dlci */
 2294         pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
 2295         if (pcb == NULL) {
 2296                 NG_BTSOCKET_RFCOMM_WARN(
 2297 "%s: Got UIH for non-existing dlci=%d\n", __func__, dlci);
 2298                 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
 2299                 goto drop;
 2300         }
 2301 
 2302         mtx_lock(&pcb->pcb_mtx);
 2303 
 2304         /* Check dlci state */  
 2305         if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
 2306                 NG_BTSOCKET_RFCOMM_WARN(
 2307 "%s: Got UIH for dlci=%d in invalid state=%d, flags=%#x\n",
 2308                         __func__, dlci, pcb->state, pcb->flags);
 2309                 error = EINVAL;
 2310                 goto drop1;
 2311         }
 2312 
 2313         /* Check dlci flow control */
 2314         if (((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pcb->rx_cred <= 0) ||
 2315              (pcb->lmodem & RFCOMM_MODEM_FC)) {
 2316                 NG_BTSOCKET_RFCOMM_ERR(
 2317 "%s: Got UIH for dlci=%d with asserted flow control, state=%d, " \
 2318 "flags=%#x, rx_cred=%d, lmodem=%#x\n",
 2319                         __func__, dlci, pcb->state, pcb->flags,
 2320                         pcb->rx_cred, pcb->lmodem);
 2321                 goto drop1;
 2322         }
 2323 
 2324         /* Did we get any credits? */
 2325         if ((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pf) {
 2326                 NG_BTSOCKET_RFCOMM_INFO(
 2327 "%s: Got %d more credits for dlci=%d, state=%d, flags=%#x, " \
 2328 "rx_cred=%d, tx_cred=%d\n",
 2329                         __func__, *mtod(m0, u_int8_t *), dlci, pcb->state, 
 2330                         pcb->flags, pcb->rx_cred, pcb->tx_cred);
 2331 
 2332                 pcb->tx_cred += *mtod(m0, u_int8_t *);
 2333                 m_adj(m0, 1);
 2334 
 2335                 /* Send more from the DLC. XXX check for errors? */
 2336                 ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
 2337         } 
 2338 
 2339         /* OK the of the rest of the mbuf is the data */
 2340         if (m0->m_pkthdr.len > 0) {
 2341                 /* If we are using credit flow control decrease rx_cred here */
 2342                 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
 2343                         /* Give remote peer more credits (if needed) */
 2344                         if (-- pcb->rx_cred <= RFCOMM_MAX_CREDITS / 2)
 2345                                 ng_btsocket_rfcomm_send_credits(pcb);
 2346                         else
 2347                                 NG_BTSOCKET_RFCOMM_INFO(
 2348 "%s: Remote side still has credits, dlci=%d, state=%d, flags=%#x, " \
 2349 "rx_cred=%d, tx_cred=%d\n",             __func__, dlci, pcb->state, pcb->flags,
 2350                                         pcb->rx_cred, pcb->tx_cred);
 2351                 }
 2352                 
 2353                 /* Check packet against mtu on dlci */
 2354                 if (m0->m_pkthdr.len > pcb->mtu) {
 2355                         NG_BTSOCKET_RFCOMM_ERR(
 2356 "%s: Got oversized UIH for dlci=%d, state=%d, flags=%#x, mtu=%d, len=%d\n",
 2357                                 __func__, dlci, pcb->state, pcb->flags,
 2358                                 pcb->mtu, m0->m_pkthdr.len);
 2359 
 2360                         error = EMSGSIZE;
 2361                 } else if (m0->m_pkthdr.len > sbspace(&pcb->so->so_rcv)) {
 2362                         /*
 2363                          * This is really bad. Receive queue on socket does
 2364                          * not have enough space for the packet. We do not
 2365                          * have any other choice but drop the packet. 
 2366                          */
 2367 
 2368                         NG_BTSOCKET_RFCOMM_ERR(
 2369 "%s: Not enough space in socket receive queue. Dropping UIH for dlci=%d, " \
 2370 "state=%d, flags=%#x, len=%d, space=%ld\n",
 2371                                 __func__, dlci, pcb->state, pcb->flags,
 2372                                 m0->m_pkthdr.len, sbspace(&pcb->so->so_rcv));
 2373 
 2374                         error = ENOBUFS;
 2375                 } else {
 2376                         /* Append packet to the socket receive queue */
 2377                         sbappend(&pcb->so->so_rcv, m0, 0);
 2378                         m0 = NULL;
 2379 
 2380                         sorwakeup(pcb->so);
 2381                 }
 2382         }
 2383 drop1:
 2384         mtx_unlock(&pcb->pcb_mtx);
 2385 drop:
 2386         NG_FREE_M(m0); /* checks for != NULL */
 2387 
 2388         return (error);
 2389 } /* ng_btsocket_rfcomm_receive_uih */
 2390 
 2391 /*
 2392  * Process RFCOMM MCC command (Multiplexor)
 2393  * 
 2394  * From TS 07.10 spec
 2395  *
 2396  * "5.4.3.1 Information Data
 2397  * 
 2398  *  ...The frames (UIH) sent by the initiating station have the C/R bit set 
 2399  *  to 1 and those sent by the responding station have the C/R bit set to 0..."
 2400  *
 2401  * "5.4.6.2 Operating procedures
 2402  *
 2403  *  Messages always exist in pairs; a command message and a corresponding 
 2404  *  response message. If the C/R bit is set to 1 the message is a command, 
 2405  *  if it is set to 0 the message is a response...
 2406  *
 2407  *  ...
 2408  * 
 2409  *  NOTE: Notice that when UIH frames are used to convey information on DLCI 0
 2410  *  there are at least two different fields that contain a C/R bit, and the 
 2411  *  bits are set of different form. The C/R bit in the Type field shall be set
 2412  *  as it is stated above, while the C/R bit in the Address field (see subclause
 2413  *  5.2.1.2) shall be set as it is described in subclause 5.4.3.1."
 2414  */
 2415 
 2416 static int
 2417 ng_btsocket_rfcomm_receive_mcc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
 2418 {
 2419         struct rfcomm_mcc_hdr   *hdr = NULL;
 2420         u_int8_t                 cr, type, length;
 2421 
 2422         mtx_assert(&s->session_mtx, MA_OWNED);
 2423 
 2424         /*
 2425          * We can access data directly in the first mbuf, because we have
 2426          * m_pullup()'ed mbuf chain in ng_btsocket_rfcomm_receive_frame().
 2427          * All MCC commands should fit into single mbuf (except probably TEST).
 2428          */
 2429 
 2430         hdr = mtod(m0, struct rfcomm_mcc_hdr *);
 2431         cr = RFCOMM_CR(hdr->type);
 2432         type = RFCOMM_MCC_TYPE(hdr->type);
 2433         length = RFCOMM_MCC_LENGTH(hdr->length);
 2434 
 2435         /* Check MCC frame length */
 2436         if (sizeof(*hdr) + length != m0->m_pkthdr.len) {
 2437                 NG_BTSOCKET_RFCOMM_ERR(
 2438 "%s: Invalid MCC frame length=%d, len=%d\n",
 2439                         __func__, length, m0->m_pkthdr.len);
 2440                 NG_FREE_M(m0);
 2441 
 2442                 return (EMSGSIZE);
 2443         }
 2444 
 2445         switch (type) {
 2446         case RFCOMM_MCC_TEST:
 2447                 return (ng_btsocket_rfcomm_receive_test(s, m0));
 2448                 /* NOT REACHED */
 2449 
 2450         case RFCOMM_MCC_FCON:
 2451         case RFCOMM_MCC_FCOFF:
 2452                 return (ng_btsocket_rfcomm_receive_fc(s, m0));
 2453                 /* NOT REACHED */
 2454 
 2455         case RFCOMM_MCC_MSC:
 2456                 return (ng_btsocket_rfcomm_receive_msc(s, m0));
 2457                 /* NOT REACHED */
 2458 
 2459         case RFCOMM_MCC_RPN:
 2460                 return (ng_btsocket_rfcomm_receive_rpn(s, m0));
 2461                 /* NOT REACHED */
 2462 
 2463         case RFCOMM_MCC_RLS:
 2464                 return (ng_btsocket_rfcomm_receive_rls(s, m0));
 2465                 /* NOT REACHED */
 2466 
 2467         case RFCOMM_MCC_PN:
 2468                 return (ng_btsocket_rfcomm_receive_pn(s, m0));
 2469                 /* NOT REACHED */
 2470 
 2471         case RFCOMM_MCC_NSC:
 2472                 NG_BTSOCKET_RFCOMM_ERR(
 2473 "%s: Got MCC NSC, type=%#x, cr=%d, length=%d, session state=%d, flags=%#x, " \
 2474 "mtu=%d, len=%d\n",     __func__, RFCOMM_MCC_TYPE(*((u_int8_t *)(hdr + 1))), cr,
 2475                          length, s->state, s->flags, s->mtu, m0->m_pkthdr.len);
 2476                 NG_FREE_M(m0);
 2477                 break;
 2478 
 2479         default:
 2480                 NG_BTSOCKET_RFCOMM_ERR(
 2481 "%s: Got unknown MCC, type=%#x, cr=%d, length=%d, session state=%d, " \
 2482 "flags=%#x, mtu=%d, len=%d\n",
 2483                         __func__, type, cr, length, s->state, s->flags,
 2484                         s->mtu, m0->m_pkthdr.len);
 2485 
 2486                 /* Reuse mbuf to send NSC */
 2487                 hdr = mtod(m0, struct rfcomm_mcc_hdr *);
 2488                 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr);
 2489 
 2490                 /* Create MCC NSC header */
 2491                 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_NSC);
 2492                 hdr->length = RFCOMM_MKLEN8(1);
 2493 
 2494                 /* Put back MCC command type we did not like */
 2495                 m0->m_data[m0->m_len] = RFCOMM_MKMCC_TYPE(cr, type);
 2496                 m0->m_pkthdr.len ++;
 2497                 m0->m_len ++;
 2498 
 2499                 /* Send UIH frame */
 2500                 return (ng_btsocket_rfcomm_send_uih(s,
 2501                                 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0));
 2502                 /* NOT REACHED */
 2503         }
 2504 
 2505         return (0);
 2506 } /* ng_btsocket_rfcomm_receive_mcc */
 2507 
 2508 /*
 2509  * Receive RFCOMM TEST MCC command
 2510  */
 2511 
 2512 static int
 2513 ng_btsocket_rfcomm_receive_test(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
 2514 {
 2515         struct rfcomm_mcc_hdr   *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
 2516         int                      error = 0;
 2517 
 2518         mtx_assert(&s->session_mtx, MA_OWNED);
 2519 
 2520         NG_BTSOCKET_RFCOMM_INFO(
 2521 "%s: Got MCC TEST, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
 2522 "len=%d\n",     __func__, RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
 2523                 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
 2524 
 2525         if (RFCOMM_CR(hdr->type)) {
 2526                 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_TEST);
 2527                 error = ng_btsocket_rfcomm_send_uih(s,
 2528                                 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
 2529         } else
 2530                 NG_FREE_M(m0); /* XXX ignore response */
 2531 
 2532         return (error);
 2533 } /* ng_btsocket_rfcomm_receive_test */
 2534 
 2535 /*
 2536  * Receive RFCOMM FCON/FCOFF MCC command
 2537  */
 2538 
 2539 static int
 2540 ng_btsocket_rfcomm_receive_fc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
 2541 {
 2542         struct rfcomm_mcc_hdr   *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
 2543         u_int8_t                 type = RFCOMM_MCC_TYPE(hdr->type);
 2544         int                      error = 0;
 2545 
 2546         mtx_assert(&s->session_mtx, MA_OWNED);
 2547 
 2548         /*
 2549          * Turn ON/OFF aggregate flow on the entire session. When remote peer 
 2550          * asserted flow control no transmission shall occur except on dlci 0
 2551          * (control channel).
 2552          */
 2553 
 2554         NG_BTSOCKET_RFCOMM_INFO(
 2555 "%s: Got MCC FC%s, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
 2556 "len=%d\n",     __func__, (type == RFCOMM_MCC_FCON)? "ON" : "OFF",
 2557                 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
 2558                 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
 2559 
 2560         if (RFCOMM_CR(hdr->type)) {
 2561                 if (type == RFCOMM_MCC_FCON)
 2562                         s->flags &= ~NG_BTSOCKET_RFCOMM_SESSION_RFC;
 2563                 else
 2564                         s->flags |= NG_BTSOCKET_RFCOMM_SESSION_RFC;
 2565 
 2566                 hdr->type = RFCOMM_MKMCC_TYPE(0, type);
 2567                 error = ng_btsocket_rfcomm_send_uih(s,
 2568                                 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
 2569         } else
 2570                 NG_FREE_M(m0); /* XXX ignore response */
 2571 
 2572         return (error);
 2573 } /* ng_btsocket_rfcomm_receive_fc  */
 2574 
 2575 /*
 2576  * Receive RFCOMM MSC MCC command
 2577  */
 2578 
 2579 static int
 2580 ng_btsocket_rfcomm_receive_msc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
 2581 {
 2582         struct rfcomm_mcc_hdr           *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
 2583         struct rfcomm_mcc_msc           *msc = (struct rfcomm_mcc_msc *)(hdr+1);
 2584         ng_btsocket_rfcomm_pcb_t        *pcb = NULL;
 2585         int                              error = 0;
 2586 
 2587         mtx_assert(&s->session_mtx, MA_OWNED);
 2588 
 2589         NG_BTSOCKET_RFCOMM_INFO(
 2590 "%s: Got MCC MSC, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
 2591 "mtu=%d, len=%d\n",
 2592                 __func__,  RFCOMM_DLCI(msc->address), RFCOMM_CR(hdr->type),
 2593                 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
 2594                 s->mtu, m0->m_pkthdr.len);
 2595 
 2596         if (RFCOMM_CR(hdr->type)) {
 2597                 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, RFCOMM_DLCI(msc->address));
 2598                 if (pcb == NULL) {
 2599                         NG_BTSOCKET_RFCOMM_WARN(
 2600 "%s: Got MSC command for non-existing dlci=%d\n",
 2601                                 __func__, RFCOMM_DLCI(msc->address));
 2602                         NG_FREE_M(m0);
 2603 
 2604                         return (ENOENT);
 2605                 }
 2606 
 2607                 mtx_lock(&pcb->pcb_mtx);
 2608 
 2609                 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING &&
 2610                     pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
 2611                         NG_BTSOCKET_RFCOMM_WARN(
 2612 "%s: Got MSC on dlci=%d in invalid state=%d\n",
 2613                                 __func__, RFCOMM_DLCI(msc->address),
 2614                                 pcb->state);
 2615 
 2616                         mtx_unlock(&pcb->pcb_mtx);
 2617                         NG_FREE_M(m0);
 2618 
 2619                         return (EINVAL);
 2620                 }
 2621 
 2622                 pcb->rmodem = msc->modem; /* Update remote port signals */
 2623 
 2624                 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_MSC);
 2625                 error = ng_btsocket_rfcomm_send_uih(s,
 2626                                 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
 2627 
 2628 #if 0 /* YYY */
 2629                 /* Send more data from DLC. XXX check for errors? */
 2630                 if (!(pcb->rmodem & RFCOMM_MODEM_FC) &&
 2631                     !(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC))
 2632                         ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
 2633 #endif /* YYY */
 2634 
 2635                 mtx_unlock(&pcb->pcb_mtx);
 2636         } else
 2637                 NG_FREE_M(m0); /* XXX ignore response */
 2638 
 2639         return (error);
 2640 } /* ng_btsocket_rfcomm_receive_msc */
 2641 
 2642 /*
 2643  * Receive RFCOMM RPN MCC command
 2644  * XXX FIXME do we need htole16/le16toh for RPN param_mask?
 2645  */
 2646 
 2647 static int
 2648 ng_btsocket_rfcomm_receive_rpn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
 2649 {
 2650         struct rfcomm_mcc_hdr   *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
 2651         struct rfcomm_mcc_rpn   *rpn = (struct rfcomm_mcc_rpn *)(hdr + 1);
 2652         int                      error = 0;
 2653         u_int16_t                param_mask;
 2654         u_int8_t                 bit_rate, data_bits, stop_bits, parity,
 2655                                  flow_control, xon_char, xoff_char;
 2656 
 2657         mtx_assert(&s->session_mtx, MA_OWNED);
 2658 
 2659         NG_BTSOCKET_RFCOMM_INFO(
 2660 "%s: Got MCC RPN, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
 2661 "mtu=%d, len=%d\n",
 2662                 __func__, RFCOMM_DLCI(rpn->dlci), RFCOMM_CR(hdr->type),
 2663                 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
 2664                 s->mtu, m0->m_pkthdr.len);
 2665 
 2666         if (RFCOMM_CR(hdr->type)) {
 2667                 param_mask = RFCOMM_RPN_PM_ALL;
 2668 
 2669                 if (RFCOMM_MCC_LENGTH(hdr->length) == 1) {
 2670                         /* Request - return default setting */
 2671                         bit_rate = RFCOMM_RPN_BR_115200;
 2672                         data_bits = RFCOMM_RPN_DATA_8;
 2673                         stop_bits = RFCOMM_RPN_STOP_1;
 2674                         parity = RFCOMM_RPN_PARITY_NONE;
 2675                         flow_control = RFCOMM_RPN_FLOW_NONE;
 2676                         xon_char = RFCOMM_RPN_XON_CHAR;
 2677                         xoff_char = RFCOMM_RPN_XOFF_CHAR;
 2678                 } else {
 2679                         /*
 2680                          * Ignore/accept bit_rate, 8 bits, 1 stop bit, no 
 2681                          * parity, no flow control lines, default XON/XOFF 
 2682                          * chars.
 2683                          */
 2684 
 2685                         bit_rate = rpn->bit_rate;
 2686                         rpn->param_mask = le16toh(rpn->param_mask); /* XXX */
 2687 
 2688                         data_bits = RFCOMM_RPN_DATA_BITS(rpn->line_settings);
 2689                         if (rpn->param_mask & RFCOMM_RPN_PM_DATA &&
 2690                             data_bits != RFCOMM_RPN_DATA_8) {
 2691                                 data_bits = RFCOMM_RPN_DATA_8;
 2692                                 param_mask ^= RFCOMM_RPN_PM_DATA;
 2693                         }
 2694 
 2695                         stop_bits = RFCOMM_RPN_STOP_BITS(rpn->line_settings);
 2696                         if (rpn->param_mask & RFCOMM_RPN_PM_STOP &&
 2697                             stop_bits != RFCOMM_RPN_STOP_1) {
 2698                                 stop_bits = RFCOMM_RPN_STOP_1;
 2699                                 param_mask ^= RFCOMM_RPN_PM_STOP;
 2700                         }
 2701 
 2702                         parity = RFCOMM_RPN_PARITY(rpn->line_settings);
 2703                         if (rpn->param_mask & RFCOMM_RPN_PM_PARITY &&
 2704                             parity != RFCOMM_RPN_PARITY_NONE) {
 2705                                 parity = RFCOMM_RPN_PARITY_NONE;
 2706                                 param_mask ^= RFCOMM_RPN_PM_PARITY;
 2707                         }
 2708 
 2709                         flow_control = rpn->flow_control;
 2710                         if (rpn->param_mask & RFCOMM_RPN_PM_FLOW &&
 2711                             flow_control != RFCOMM_RPN_FLOW_NONE) {
 2712                                 flow_control = RFCOMM_RPN_FLOW_NONE;
 2713                                 param_mask ^= RFCOMM_RPN_PM_FLOW;
 2714                         }
 2715 
 2716                         xon_char = rpn->xon_char;
 2717                         if (rpn->param_mask & RFCOMM_RPN_PM_XON &&
 2718                             xon_char != RFCOMM_RPN_XON_CHAR) {
 2719                                 xon_char = RFCOMM_RPN_XON_CHAR;
 2720                                 param_mask ^= RFCOMM_RPN_PM_XON;
 2721                         }
 2722 
 2723                         xoff_char = rpn->xoff_char;
 2724                         if (rpn->param_mask & RFCOMM_RPN_PM_XOFF &&
 2725                             xoff_char != RFCOMM_RPN_XOFF_CHAR) {
 2726                                 xoff_char = RFCOMM_RPN_XOFF_CHAR;
 2727                                 param_mask ^= RFCOMM_RPN_PM_XOFF;
 2728                         }
 2729                 }
 2730 
 2731                 rpn->bit_rate = bit_rate;
 2732                 rpn->line_settings = RFCOMM_MKRPN_LINE_SETTINGS(data_bits, 
 2733                                                 stop_bits, parity);
 2734                 rpn->flow_control = flow_control;
 2735                 rpn->xon_char = xon_char;
 2736                 rpn->xoff_char = xoff_char;
 2737                 rpn->param_mask = htole16(param_mask); /* XXX */
 2738 
 2739                 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr) + sizeof(*rpn);
 2740 
 2741                 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RPN);
 2742                 error = ng_btsocket_rfcomm_send_uih(s,
 2743                                 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
 2744         } else
 2745                 NG_FREE_M(m0); /* XXX ignore response */
 2746 
 2747         return (error);
 2748 } /* ng_btsocket_rfcomm_receive_rpn */
 2749 
 2750 /*
 2751  * Receive RFCOMM RLS MCC command
 2752  */
 2753 
 2754 static int
 2755 ng_btsocket_rfcomm_receive_rls(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
 2756 {
 2757         struct rfcomm_mcc_hdr   *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
 2758         struct rfcomm_mcc_rls   *rls = (struct rfcomm_mcc_rls *)(hdr + 1);
 2759         int                      error = 0;
 2760 
 2761         mtx_assert(&s->session_mtx, MA_OWNED);
 2762 
 2763         /*
 2764          * XXX FIXME Do we have to do anything else here? Remote peer tries to 
 2765          * tell us something about DLCI. Just report what we have received and
 2766          * return back received values as required by TS 07.10 spec.
 2767          */
 2768 
 2769         NG_BTSOCKET_RFCOMM_INFO(
 2770 "%s: Got MCC RLS, dlci=%d, status=%#x, cr=%d, length=%d, session state=%d, " \
 2771 "flags=%#x, mtu=%d, len=%d\n",
 2772                 __func__, RFCOMM_DLCI(rls->address), rls->status,
 2773                 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
 2774                 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
 2775 
 2776         if (RFCOMM_CR(hdr->type)) {
 2777                 if (rls->status & 0x1)
 2778                         NG_BTSOCKET_RFCOMM_ERR(
 2779 "%s: Got RLS dlci=%d, error=%#x\n", __func__, RFCOMM_DLCI(rls->address),
 2780                                 rls->status >> 1);
 2781 
 2782                 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RLS);
 2783                 error = ng_btsocket_rfcomm_send_uih(s,
 2784                                 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
 2785         } else
 2786                 NG_FREE_M(m0); /* XXX ignore responses */
 2787 
 2788         return (error);
 2789 } /* ng_btsocket_rfcomm_receive_rls */
 2790 
 2791 /*
 2792  * Receive RFCOMM PN MCC command
 2793  */
 2794 
 2795 static int
 2796 ng_btsocket_rfcomm_receive_pn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
 2797 {
 2798         struct rfcomm_mcc_hdr           *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
 2799         struct rfcomm_mcc_pn            *pn = (struct rfcomm_mcc_pn *)(hdr+1);
 2800         ng_btsocket_rfcomm_pcb_t        *pcb = NULL;
 2801         int                              error = 0;
 2802 
 2803         mtx_assert(&s->session_mtx, MA_OWNED);
 2804 
 2805         NG_BTSOCKET_RFCOMM_INFO(
 2806 "%s: Got MCC PN, dlci=%d, cr=%d, length=%d, flow_control=%#x, priority=%d, " \
 2807 "ack_timer=%d, mtu=%d, max_retrans=%d, credits=%d, session state=%d, " \
 2808 "flags=%#x, session mtu=%d, len=%d\n",
 2809                 __func__, pn->dlci, RFCOMM_CR(hdr->type),
 2810                 RFCOMM_MCC_LENGTH(hdr->length), pn->flow_control, pn->priority,
 2811                 pn->ack_timer, le16toh(pn->mtu), pn->max_retrans, pn->credits,
 2812                 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
 2813 
 2814         if (pn->dlci == 0) {
 2815                 NG_BTSOCKET_RFCOMM_ERR("%s: Zero dlci in MCC PN\n", __func__);
 2816                 NG_FREE_M(m0);
 2817 
 2818                 return (EINVAL);
 2819         }
 2820 
 2821         /* Check if we have this dlci */
 2822         pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, pn->dlci);
 2823         if (pcb != NULL) {
 2824                 mtx_lock(&pcb->pcb_mtx);
 2825 
 2826                 if (RFCOMM_CR(hdr->type)) {
 2827                         /* PN Request */
 2828                         ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
 2829                                 pn->credits, pn->mtu);
 2830 
 2831                         if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
 2832                                 pn->flow_control = 0xe0;
 2833                                 pn->credits = RFCOMM_DEFAULT_CREDITS;
 2834                         } else {
 2835                                 pn->flow_control = 0;
 2836                                 pn->credits = 0;
 2837                         }
 2838 
 2839                         hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
 2840                         error = ng_btsocket_rfcomm_send_uih(s, 
 2841                                         RFCOMM_MKADDRESS(INITIATOR(s), 0),
 2842                                         0, 0, m0);
 2843                 } else {
 2844                         /* PN Response - proceed with SABM. Timeout still set */
 2845                         if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONFIGURING) {
 2846                                 ng_btsocket_rfcomm_set_pn(pcb, 0,
 2847                                         pn->flow_control, pn->credits, pn->mtu);
 2848 
 2849                                 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
 2850                                 error = ng_btsocket_rfcomm_send_command(s,
 2851                                                 RFCOMM_FRAME_SABM, pn->dlci);
 2852                         } else
 2853                                 NG_BTSOCKET_RFCOMM_WARN(
 2854 "%s: Got PN response for dlci=%d in invalid state=%d\n",
 2855                                         __func__, pn->dlci, pcb->state);
 2856 
 2857                         NG_FREE_M(m0);
 2858                 }
 2859 
 2860                 mtx_unlock(&pcb->pcb_mtx);
 2861         } else if (RFCOMM_CR(hdr->type)) {
 2862                 /* PN request to non-existing dlci - incoming connection */
 2863                 pcb = ng_btsocket_rfcomm_connect_ind(s,
 2864                                 RFCOMM_SRVCHANNEL(pn->dlci));
 2865                 if (pcb != NULL) {
 2866                         mtx_lock(&pcb->pcb_mtx);
 2867 
 2868                         pcb->dlci = pn->dlci;
 2869 
 2870                         ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
 2871                                 pn->credits, pn->mtu);
 2872 
 2873                         if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
 2874                                 pn->flow_control = 0xe0;
 2875                                 pn->credits = RFCOMM_DEFAULT_CREDITS;
 2876                         } else {
 2877                                 pn->flow_control = 0;
 2878                                 pn->credits = 0;
 2879                         }
 2880 
 2881                         hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
 2882                         error = ng_btsocket_rfcomm_send_uih(s, 
 2883                                         RFCOMM_MKADDRESS(INITIATOR(s), 0),
 2884                                         0, 0, m0);
 2885 
 2886                         if (error == 0) {
 2887                                 ng_btsocket_rfcomm_timeout(pcb);
 2888                                 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
 2889                                 soisconnecting(pcb->so);
 2890                         } else
 2891                                 ng_btsocket_rfcomm_pcb_kill(pcb, error);
 2892 
 2893                         mtx_unlock(&pcb->pcb_mtx);
 2894                 } else {
 2895                         /* Nobody is listen()ing on this channel */
 2896                         error = ng_btsocket_rfcomm_send_command(s,
 2897                                         RFCOMM_FRAME_DM, pn->dlci);
 2898                         NG_FREE_M(m0);
 2899                 }
 2900         } else
 2901                 NG_FREE_M(m0); /* XXX ignore response to non-existing dlci */
 2902 
 2903         return (error);
 2904 } /* ng_btsocket_rfcomm_receive_pn */
 2905 
 2906 /*
 2907  * Set PN parameters for dlci. Caller must hold pcb->pcb_mtx.
 2908  * 
 2909  * From Bluetooth spec.
 2910  * 
 2911  * "... The CL1 - CL4 field is completely redefined. (In TS07.10 this defines 
 2912  *  the convergence layer to use, which is not applicable to RFCOMM. In RFCOMM,
 2913  *  in Bluetooth versions up to 1.0B, this field was forced to 0).
 2914  *
 2915  *  In the PN request sent prior to a DLC establishment, this field must contain
 2916  *  the value 15 (0xF), indicating support of credit based flow control in the 
 2917  *  sender. See Table 5.3 below. If the PN response contains any other value 
 2918  *  than 14 (0xE) in this field, it is inferred that the peer RFCOMM entity is 
 2919  *  not supporting the credit based flow control feature. (This is only possible
 2920  *  if the peer RFCOMM implementation is only conforming to Bluetooth version 
 2921  *  1.0B.) If a PN request is sent on an already open DLC, then this field must
 2922  *  contain the value zero; it is not possible to set initial credits  more 
 2923  *  than once per DLC activation. A responding implementation must set this 
 2924  *  field in the PN response to 14 (0xE), if (and only if) the value in the PN 
 2925  *  request was 15..."
 2926  */
 2927 
 2928 static void
 2929 ng_btsocket_rfcomm_set_pn(ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr,
 2930                 u_int8_t flow_control, u_int8_t credits, u_int16_t mtu)
 2931 {
 2932         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
 2933 
 2934         pcb->mtu = le16toh(mtu);
 2935 
 2936         if (cr) {
 2937                 if (flow_control == 0xf0) {
 2938                         pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
 2939                         pcb->tx_cred = credits;
 2940                 } else {
 2941                         pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
 2942                         pcb->tx_cred = 0;
 2943                 }
 2944         } else {
 2945                 if (flow_control == 0xe0) {
 2946                         pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
 2947                         pcb->tx_cred = credits;
 2948                 } else {
 2949                         pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
 2950                         pcb->tx_cred = 0;
 2951                 }
 2952         }
 2953 
 2954         NG_BTSOCKET_RFCOMM_INFO(
 2955 "%s: cr=%d, dlci=%d, state=%d, flags=%#x, mtu=%d, rx_cred=%d, tx_cred=%d\n",
 2956                 __func__, cr, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
 2957                 pcb->rx_cred, pcb->tx_cred);
 2958 } /* ng_btsocket_rfcomm_set_pn */
 2959 
 2960 /*
 2961  * Send RFCOMM SABM/DISC/UA/DM frames. Caller must hold s->session_mtx
 2962  */
 2963 
 2964 static int
 2965 ng_btsocket_rfcomm_send_command(ng_btsocket_rfcomm_session_p s,
 2966                 u_int8_t type, u_int8_t dlci)
 2967 {
 2968         struct rfcomm_cmd_hdr   *hdr = NULL;
 2969         struct mbuf             *m = NULL;
 2970         int                      cr;
 2971 
 2972         mtx_assert(&s->session_mtx, MA_OWNED);
 2973 
 2974         NG_BTSOCKET_RFCOMM_INFO(
 2975 "%s: Sending command type %#x, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
 2976                 __func__, type, s->state, s->flags, s->mtu, dlci);
 2977 
 2978         switch (type) {
 2979         case RFCOMM_FRAME_SABM:
 2980         case RFCOMM_FRAME_DISC:
 2981                 cr = INITIATOR(s);
 2982                 break;
 2983 
 2984         case RFCOMM_FRAME_UA:
 2985         case RFCOMM_FRAME_DM:
 2986                 cr = !INITIATOR(s);
 2987                 break;
 2988 
 2989         default:
 2990                 panic("%s: Invalid frame type=%#x\n", __func__, type);
 2991                 return (EINVAL);
 2992                 /* NOT REACHED */
 2993         }
 2994 
 2995         MGETHDR(m, M_NOWAIT, MT_DATA);
 2996         if (m == NULL)
 2997                 return (ENOBUFS);
 2998 
 2999         m->m_pkthdr.len = m->m_len = sizeof(*hdr);
 3000 
 3001         hdr = mtod(m, struct rfcomm_cmd_hdr *);
 3002         hdr->address = RFCOMM_MKADDRESS(cr, dlci);
 3003         hdr->control = RFCOMM_MKCONTROL(type, 1);
 3004         hdr->length = RFCOMM_MKLEN8(0);
 3005         hdr->fcs = ng_btsocket_rfcomm_fcs3((u_int8_t *) hdr);
 3006 
 3007         NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
 3008 
 3009         return (0);
 3010 } /* ng_btsocket_rfcomm_send_command */
 3011 
 3012 /*
 3013  * Send RFCOMM UIH frame. Caller must hold s->session_mtx
 3014  */
 3015 
 3016 static int
 3017 ng_btsocket_rfcomm_send_uih(ng_btsocket_rfcomm_session_p s, u_int8_t address,
 3018                 u_int8_t pf, u_int8_t credits, struct mbuf *data)
 3019 {
 3020         struct rfcomm_frame_hdr *hdr = NULL;
 3021         struct mbuf             *m = NULL, *mcrc = NULL;
 3022         u_int16_t                length;
 3023 
 3024         mtx_assert(&s->session_mtx, MA_OWNED);
 3025 
 3026         MGETHDR(m, M_NOWAIT, MT_DATA);
 3027         if (m == NULL) {
 3028                 NG_FREE_M(data);
 3029                 return (ENOBUFS);
 3030         }
 3031         m->m_pkthdr.len = m->m_len = sizeof(*hdr);
 3032 
 3033         MGET(mcrc, M_NOWAIT, MT_DATA);
 3034         if (mcrc == NULL) {
 3035                 NG_FREE_M(data);
 3036                 return (ENOBUFS);
 3037         }
 3038         mcrc->m_len = 1;
 3039 
 3040         /* Fill UIH frame header */
 3041         hdr = mtod(m, struct rfcomm_frame_hdr *);
 3042         hdr->address = address;
 3043         hdr->control = RFCOMM_MKCONTROL(RFCOMM_FRAME_UIH, pf);
 3044 
 3045         /* Calculate FCS */
 3046         mcrc->m_data[0] = ng_btsocket_rfcomm_fcs2((u_int8_t *) hdr);
 3047 
 3048         /* Put length back */
 3049         length = (data != NULL)? data->m_pkthdr.len : 0;
 3050         if (length > 127) {
 3051                 u_int16_t       l = htole16(RFCOMM_MKLEN16(length));
 3052 
 3053                 bcopy(&l, &hdr->length, sizeof(l));
 3054                 m->m_pkthdr.len ++;
 3055                 m->m_len ++;
 3056         } else
 3057                 hdr->length = RFCOMM_MKLEN8(length);
 3058 
 3059         if (pf) {
 3060                 m->m_data[m->m_len] = credits;
 3061                 m->m_pkthdr.len ++;
 3062                 m->m_len ++;
 3063         }
 3064 
 3065         /* Add payload */
 3066         if (data != NULL) {
 3067                 m_cat(m, data);
 3068                 m->m_pkthdr.len += length;
 3069         }
 3070 
 3071         /* Put FCS back */
 3072         m_cat(m, mcrc);
 3073         m->m_pkthdr.len ++;
 3074 
 3075         NG_BTSOCKET_RFCOMM_INFO(
 3076 "%s: Sending UIH state=%d, flags=%#x, address=%d, length=%d, pf=%d, " \
 3077 "credits=%d, len=%d\n",
 3078                 __func__, s->state, s->flags, address, length, pf, credits,
 3079                 m->m_pkthdr.len);
 3080 
 3081         NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
 3082 
 3083         return (0);
 3084 } /* ng_btsocket_rfcomm_send_uih */
 3085 
 3086 /*
 3087  * Send MSC request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
 3088  */
 3089 
 3090 static int
 3091 ng_btsocket_rfcomm_send_msc(ng_btsocket_rfcomm_pcb_p pcb)
 3092 {
 3093         struct mbuf             *m = NULL;
 3094         struct rfcomm_mcc_hdr   *hdr = NULL;
 3095         struct rfcomm_mcc_msc   *msc = NULL;
 3096 
 3097         mtx_assert(&pcb->session->session_mtx, MA_OWNED);
 3098         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
 3099 
 3100         MGETHDR(m, M_NOWAIT, MT_DATA);
 3101         if (m == NULL)
 3102                 return (ENOBUFS);
 3103 
 3104         m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*msc);
 3105 
 3106         hdr = mtod(m, struct rfcomm_mcc_hdr *);
 3107         msc = (struct rfcomm_mcc_msc *)(hdr + 1);
 3108 
 3109         hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_MSC);
 3110         hdr->length = RFCOMM_MKLEN8(sizeof(*msc));
 3111 
 3112         msc->address = RFCOMM_MKADDRESS(1, pcb->dlci);
 3113         msc->modem = pcb->lmodem;
 3114 
 3115         NG_BTSOCKET_RFCOMM_INFO(
 3116 "%s: Sending MSC dlci=%d, state=%d, flags=%#x, address=%d, modem=%#x\n",
 3117                 __func__, pcb->dlci, pcb->state, pcb->flags, msc->address,
 3118                 msc->modem);
 3119 
 3120         return (ng_btsocket_rfcomm_send_uih(pcb->session,
 3121                         RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
 3122 } /* ng_btsocket_rfcomm_send_msc */
 3123 
 3124 /*
 3125  * Send PN request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
 3126  */
 3127 
 3128 static int
 3129 ng_btsocket_rfcomm_send_pn(ng_btsocket_rfcomm_pcb_p pcb)
 3130 {
 3131         struct mbuf             *m = NULL;
 3132         struct rfcomm_mcc_hdr   *hdr = NULL;
 3133         struct rfcomm_mcc_pn    *pn = NULL;
 3134 
 3135         mtx_assert(&pcb->session->session_mtx, MA_OWNED);
 3136         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
 3137 
 3138         MGETHDR(m, M_NOWAIT, MT_DATA);
 3139         if (m == NULL)
 3140                 return (ENOBUFS);
 3141 
 3142         m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*pn);
 3143 
 3144         hdr = mtod(m, struct rfcomm_mcc_hdr *);
 3145         pn = (struct rfcomm_mcc_pn *)(hdr + 1);
 3146 
 3147         hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_PN);
 3148         hdr->length = RFCOMM_MKLEN8(sizeof(*pn));
 3149 
 3150         pn->dlci = pcb->dlci;
 3151 
 3152         /*
 3153          * Set default DLCI priority as described in GSM 07.10
 3154          * (ETSI TS 101 369) clause 5.6 page 42
 3155          */
 3156 
 3157         pn->priority = (pcb->dlci < 56)? (((pcb->dlci >> 3) << 3) + 7) : 61;
 3158         pn->ack_timer = 0;
 3159         pn->mtu = htole16(pcb->mtu);
 3160         pn->max_retrans = 0;
 3161 
 3162         if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
 3163                 pn->flow_control = 0xf0;
 3164                 pn->credits = pcb->rx_cred;
 3165         } else {
 3166                 pn->flow_control = 0;
 3167                 pn->credits = 0;
 3168         }
 3169 
 3170         NG_BTSOCKET_RFCOMM_INFO(
 3171 "%s: Sending PN dlci=%d, state=%d, flags=%#x, mtu=%d, flow_control=%#x, " \
 3172 "credits=%d\n", __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
 3173                 pn->flow_control, pn->credits);
 3174 
 3175         return (ng_btsocket_rfcomm_send_uih(pcb->session,
 3176                         RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
 3177 } /* ng_btsocket_rfcomm_send_pn */
 3178 
 3179 /*
 3180  * Calculate and send credits based on available space in receive buffer
 3181  */
 3182 
 3183 static int
 3184 ng_btsocket_rfcomm_send_credits(ng_btsocket_rfcomm_pcb_p pcb)
 3185 {
 3186         int             error = 0;
 3187         u_int8_t        credits;
 3188 
 3189         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
 3190         mtx_assert(&pcb->session->session_mtx, MA_OWNED);
 3191 
 3192         NG_BTSOCKET_RFCOMM_INFO(
 3193 "%s: Sending more credits, dlci=%d, state=%d, flags=%#x, mtu=%d, " \
 3194 "space=%ld, tx_cred=%d, rx_cred=%d\n",
 3195                 __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
 3196                 sbspace(&pcb->so->so_rcv), pcb->tx_cred, pcb->rx_cred);
 3197 
 3198         credits = sbspace(&pcb->so->so_rcv) / pcb->mtu;
 3199         if (credits > 0) {
 3200                 if (pcb->rx_cred + credits > RFCOMM_MAX_CREDITS)
 3201                         credits = RFCOMM_MAX_CREDITS - pcb->rx_cred;
 3202 
 3203                 error = ng_btsocket_rfcomm_send_uih(
 3204                                 pcb->session,
 3205                                 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
 3206                                         pcb->dlci), 1, credits, NULL);
 3207                 if (error == 0) {
 3208                         pcb->rx_cred += credits;
 3209 
 3210                         NG_BTSOCKET_RFCOMM_INFO(
 3211 "%s: Gave remote side %d more credits, dlci=%d, state=%d, flags=%#x, " \
 3212 "rx_cred=%d, tx_cred=%d\n",     __func__, credits, pcb->dlci, pcb->state,
 3213                                 pcb->flags, pcb->rx_cred, pcb->tx_cred);
 3214                 } else
 3215                         NG_BTSOCKET_RFCOMM_ERR(
 3216 "%s: Could not send credits, error=%d, dlci=%d, state=%d, flags=%#x, " \
 3217 "mtu=%d, space=%ld, tx_cred=%d, rx_cred=%d\n",
 3218                                 __func__, error, pcb->dlci, pcb->state,
 3219                                 pcb->flags, pcb->mtu, sbspace(&pcb->so->so_rcv),
 3220                                 pcb->tx_cred, pcb->rx_cred);
 3221         }
 3222 
 3223         return (error);
 3224 } /* ng_btsocket_rfcomm_send_credits */
 3225 
 3226 /*****************************************************************************
 3227  *****************************************************************************
 3228  **                              RFCOMM DLCs
 3229  *****************************************************************************
 3230  *****************************************************************************/
 3231 
 3232 /*
 3233  * Send data from socket send buffer
 3234  * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
 3235  */
 3236 
 3237 static int
 3238 ng_btsocket_rfcomm_pcb_send(ng_btsocket_rfcomm_pcb_p pcb, int limit)
 3239 {
 3240         struct mbuf     *m = NULL;
 3241         int              sent, length, error;
 3242 
 3243         mtx_assert(&pcb->session->session_mtx, MA_OWNED);
 3244         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
 3245 
 3246         if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
 3247                 limit = min(limit, pcb->tx_cred);
 3248         else if (!(pcb->rmodem & RFCOMM_MODEM_FC))
 3249                 limit = min(limit, RFCOMM_MAX_CREDITS); /* XXX ??? */
 3250         else
 3251                 limit = 0;
 3252 
 3253         if (limit == 0) {
 3254                 NG_BTSOCKET_RFCOMM_INFO(
 3255 "%s: Could not send - remote flow control asserted, dlci=%d, flags=%#x, " \
 3256 "rmodem=%#x, tx_cred=%d\n",
 3257                         __func__, pcb->dlci, pcb->flags, pcb->rmodem,
 3258                         pcb->tx_cred);
 3259 
 3260                 return (0);
 3261         }
 3262 
 3263         for (error = 0, sent = 0; sent < limit; sent ++) { 
 3264                 length = min(pcb->mtu, sbavail(&pcb->so->so_snd));
 3265                 if (length == 0)
 3266                         break;
 3267 
 3268                 /* Get the chunk from the socket's send buffer */
 3269                 m = ng_btsocket_rfcomm_prepare_packet(&pcb->so->so_snd, length);
 3270                 if (m == NULL) {
 3271                         error = ENOBUFS;
 3272                         break;
 3273                 }
 3274 
 3275                 sbdrop(&pcb->so->so_snd, length);
 3276 
 3277                 error = ng_btsocket_rfcomm_send_uih(pcb->session,
 3278                                 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
 3279                                         pcb->dlci), 0, 0, m);
 3280                 if (error != 0)
 3281                         break;
 3282         }
 3283 
 3284         if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
 3285                 pcb->tx_cred -= sent;
 3286 
 3287         if (error == 0 && sent > 0) {
 3288                 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_SENDING;
 3289                 sowwakeup(pcb->so);
 3290         }
 3291 
 3292         return (error);
 3293 } /* ng_btsocket_rfcomm_pcb_send */
 3294 
 3295 /*
 3296  * Unlink and disconnect DLC. If ng_btsocket_rfcomm_pcb_kill() returns
 3297  * non zero value than socket has no reference and has to be detached.
 3298  * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
 3299  */
 3300 
 3301 static void
 3302 ng_btsocket_rfcomm_pcb_kill(ng_btsocket_rfcomm_pcb_p pcb, int error)
 3303 {
 3304         ng_btsocket_rfcomm_session_p    s = pcb->session;
 3305 
 3306         NG_BTSOCKET_RFCOMM_INFO(
 3307 "%s: Killing DLC, so=%p, dlci=%d, state=%d, flags=%#x, error=%d\n",
 3308                 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags, error);
 3309 
 3310         if (pcb->session == NULL)
 3311                 panic("%s: DLC without session, pcb=%p, state=%d, flags=%#x\n",
 3312                         __func__, pcb, pcb->state, pcb->flags);
 3313 
 3314         mtx_assert(&pcb->session->session_mtx, MA_OWNED);
 3315         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
 3316 
 3317         if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
 3318                 ng_btsocket_rfcomm_untimeout(pcb);
 3319 
 3320         /* Detach DLC from the session. Does not matter which state DLC in */
 3321         LIST_REMOVE(pcb, session_next);
 3322         pcb->session = NULL;
 3323 
 3324         /* Change DLC state and wakeup all sleepers */
 3325         pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED;
 3326         pcb->so->so_error = error;
 3327         soisdisconnected(pcb->so);
 3328         wakeup(&pcb->state);
 3329 
 3330         /* Check if we have any DLCs left on the session */
 3331         if (LIST_EMPTY(&s->dlcs) && INITIATOR(s)) {
 3332                 NG_BTSOCKET_RFCOMM_INFO(
 3333 "%s: Disconnecting session, state=%d, flags=%#x, mtu=%d\n",
 3334                         __func__, s->state, s->flags, s->mtu);
 3335 
 3336                 switch (s->state) {
 3337                 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED:
 3338                 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
 3339                         /*
 3340                          * Do not have to do anything here. We can get here
 3341                          * when L2CAP connection was terminated or we have 
 3342                          * received DISC on multiplexor channel
 3343                          */
 3344                         break;
 3345 
 3346                 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
 3347                         /* Send DISC on multiplexor channel */
 3348                         error = ng_btsocket_rfcomm_send_command(s,
 3349                                         RFCOMM_FRAME_DISC, 0);
 3350                         if (error == 0) {
 3351                                 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
 3352                                 break;
 3353                         }
 3354                         /* FALL THROUGH */
 3355 
 3356                 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
 3357                 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
 3358                         s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
 3359                         break;
 3360 
 3361 /*              case NG_BTSOCKET_RFCOMM_SESSION_LISTENING: */
 3362                 default:
 3363                         panic("%s: Invalid session state=%d, flags=%#x\n",
 3364                                 __func__, s->state, s->flags);
 3365                         break;
 3366                 }
 3367 
 3368                 ng_btsocket_rfcomm_task_wakeup();
 3369         }
 3370 } /* ng_btsocket_rfcomm_pcb_kill */
 3371 
 3372 /*
 3373  * Look for given dlci for given RFCOMM session. Caller must hold s->session_mtx
 3374  */
 3375 
 3376 static ng_btsocket_rfcomm_pcb_p
 3377 ng_btsocket_rfcomm_pcb_by_dlci(ng_btsocket_rfcomm_session_p s, int dlci)
 3378 {
 3379         ng_btsocket_rfcomm_pcb_p        pcb = NULL;
 3380 
 3381         mtx_assert(&s->session_mtx, MA_OWNED);
 3382 
 3383         LIST_FOREACH(pcb, &s->dlcs, session_next)
 3384                 if (pcb->dlci == dlci)
 3385                         break;
 3386 
 3387         return (pcb);
 3388 } /* ng_btsocket_rfcomm_pcb_by_dlci */
 3389 
 3390 /*
 3391  * Look for socket that listens on given src address and given channel
 3392  */
 3393 
 3394 static ng_btsocket_rfcomm_pcb_p
 3395 ng_btsocket_rfcomm_pcb_listener(bdaddr_p src, int channel)
 3396 {
 3397         ng_btsocket_rfcomm_pcb_p        pcb = NULL, pcb1 = NULL;
 3398 
 3399         mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
 3400 
 3401         LIST_FOREACH(pcb, &ng_btsocket_rfcomm_sockets, next) {
 3402                 if (pcb->channel != channel || !SOLISTENING(pcb->so))
 3403                         continue;
 3404 
 3405                 if (bcmp(&pcb->src, src, sizeof(*src)) == 0)
 3406                         break;
 3407 
 3408                 if (bcmp(&pcb->src, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
 3409                         pcb1 = pcb;
 3410         }
 3411 
 3412         mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
 3413 
 3414         return ((pcb != NULL)? pcb : pcb1);
 3415 } /* ng_btsocket_rfcomm_pcb_listener */
 3416 
 3417 /*****************************************************************************
 3418  *****************************************************************************
 3419  **                              Misc. functions 
 3420  *****************************************************************************
 3421  *****************************************************************************/
 3422 
 3423 /*
 3424  *  Set timeout. Caller MUST hold pcb_mtx
 3425  */
 3426 
 3427 static void
 3428 ng_btsocket_rfcomm_timeout(ng_btsocket_rfcomm_pcb_p pcb)
 3429 {
 3430         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
 3431 
 3432         if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
 3433                 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMO;
 3434                 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
 3435                 callout_reset(&pcb->timo, ng_btsocket_rfcomm_timo * hz,
 3436                     ng_btsocket_rfcomm_process_timeout, pcb);
 3437         } else
 3438                 panic("%s: Duplicated socket timeout?!\n", __func__);
 3439 } /* ng_btsocket_rfcomm_timeout */
 3440 
 3441 /*
 3442  *  Unset pcb timeout. Caller MUST hold pcb_mtx
 3443  */
 3444 
 3445 static void
 3446 ng_btsocket_rfcomm_untimeout(ng_btsocket_rfcomm_pcb_p pcb)
 3447 {
 3448         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
 3449 
 3450         if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO) {
 3451                 callout_stop(&pcb->timo);
 3452                 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
 3453                 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
 3454         } else
 3455                 panic("%s: No socket timeout?!\n", __func__);
 3456 } /* ng_btsocket_rfcomm_timeout */
 3457 
 3458 /*
 3459  * Process pcb timeout
 3460  */
 3461 
 3462 static void
 3463 ng_btsocket_rfcomm_process_timeout(void *xpcb)
 3464 {
 3465         ng_btsocket_rfcomm_pcb_p        pcb = (ng_btsocket_rfcomm_pcb_p) xpcb;
 3466 
 3467         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
 3468 
 3469         NG_BTSOCKET_RFCOMM_INFO(
 3470 "%s: Timeout, so=%p, dlci=%d, state=%d, flags=%#x\n",
 3471                 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags);
 3472 
 3473         pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
 3474         pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
 3475 
 3476         switch (pcb->state) {
 3477         case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
 3478         case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
 3479                 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
 3480                 break;
 3481 
 3482         case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
 3483         case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
 3484                 break;
 3485 
 3486         default:
 3487                 panic(
 3488 "%s: DLC timeout in invalid state, dlci=%d, state=%d, flags=%#x\n",
 3489                         __func__, pcb->dlci, pcb->state, pcb->flags);
 3490                 break;
 3491         }
 3492 
 3493         ng_btsocket_rfcomm_task_wakeup();
 3494 } /* ng_btsocket_rfcomm_process_timeout */
 3495 
 3496 /*
 3497  * Get up to length bytes from the socket buffer
 3498  */
 3499 
 3500 static struct mbuf *
 3501 ng_btsocket_rfcomm_prepare_packet(struct sockbuf *sb, int length)
 3502 {
 3503         struct mbuf     *top = NULL, *m = NULL, *n = NULL, *nextpkt = NULL;
 3504         int              mlen, noff, len;
 3505 
 3506         MGETHDR(top, M_NOWAIT, MT_DATA);
 3507         if (top == NULL)
 3508                 return (NULL);
 3509 
 3510         top->m_pkthdr.len = length;
 3511         top->m_len = 0;
 3512         mlen = MHLEN;
 3513 
 3514         m = top;
 3515         n = sb->sb_mb;
 3516         nextpkt = n->m_nextpkt;
 3517         noff = 0;
 3518 
 3519         while (length > 0 && n != NULL) {
 3520                 len = min(mlen - m->m_len, n->m_len - noff);
 3521                 if (len > length)
 3522                         len = length;
 3523 
 3524                 bcopy(mtod(n, caddr_t)+noff, mtod(m, caddr_t)+m->m_len, len);
 3525                 m->m_len += len;
 3526                 noff += len;
 3527                 length -= len;
 3528 
 3529                 if (length > 0 && m->m_len == mlen) {
 3530                         MGET(m->m_next, M_NOWAIT, MT_DATA);
 3531                         if (m->m_next == NULL) {
 3532                                 NG_FREE_M(top);
 3533                                 return (NULL);
 3534                         }
 3535 
 3536                         m = m->m_next;
 3537                         m->m_len = 0;
 3538                         mlen = MLEN;
 3539                 }
 3540 
 3541                 if (noff == n->m_len) {
 3542                         noff = 0;
 3543                         n = n->m_next;
 3544 
 3545                         if (n == NULL)
 3546                                 n = nextpkt;
 3547 
 3548                         nextpkt = (n != NULL)? n->m_nextpkt : NULL;
 3549                 }
 3550         }
 3551 
 3552         if (length < 0)
 3553                 panic("%s: length=%d\n", __func__, length);
 3554         if (length > 0 && n == NULL)
 3555                 panic("%s: bogus length=%d, n=%p\n", __func__, length, n);
 3556 
 3557         return (top);
 3558 } /* ng_btsocket_rfcomm_prepare_packet */

Cache object: e756e18f034347a8484ef4713f3e0e6f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.