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